运行时错误2448你不能一个值分配给此对象对象、错误

2023-09-09 21:21:58 作者:此男危險!請勿靠近か

我使用大卫-W-芬顿回答这个问题以尽量让用户打印报表时,他们点击一个控制,但我收到以下错误消息:

I am using David-W-Fenton's answer to this question to try to allow users to print a report when they click on a control, but I am getting the following error message:

runtime error 2448: you cannot assign a value to this object.

的code触发错误的行是:

The line of code triggering the error is:

Me.txtPageTo.Value = numPages  

下面是在onload事件处理程序的形式充分code:

Here is the full code of the OnLoad event handler for the form:

Private Sub Form_Load()
    Dim varPrinter As Printer
    Dim strRowsource As String
    Dim strReport As String

    If Len(Me.OpenArgs) > 0 Then
        strReport = Me.OpenArgs
        Me.Tag = strReport
        For Each varPrinter In Application.Printers
            strRowsource = strRowsource & "; " & varPrinter.DeviceName
        Next varPrinter
        Me!cmbPrinter.RowSource = Mid(strRowsource, 3)
        ' first check to see that the report is still open
        If (1 = SysCmd(acSysCmdGetObjectState, acReport, strReport)) Then
            With Reports(strReport).Printer
                Me!cmbPrinter = .DeviceName
                Me!optLayout = .Orientation
            End With
            Dim numPages As String
            numPages = Reports(strReport).Pages
            Debug.Print "numPages = " & numPages
            TypeName(Me.txtPageTo) 'added this line as a test after
            Me.txtPageTo.Value = numPages
        End If
    End If
End Sub

NUMPAGES打印出等于0时,则会引发错误之前,尽管报告应至少有一个页面。此外,误差不抛出时,窗体已经打开。该错误仅被抛出时,形式必须打开。 (大概是因为得罪code是在onload事件。)

numPages prints out to equal 0 just before the error is thrown, even though the report should have at least one page. Also, the error does not get thrown when the form is already open. The error only gets thrown when the form has to be opened. (Probably because the offending code is in the onload event.)

当我加入类型名(Me.txtPageTo),它引发运行时错误2424:您输入的EX pression具有的 mydatabasename 的不能找到一个字段,控件或属性名称。

When I added TypeName(Me.txtPageTo) , it triggered runtime error 2424: The expression you entered has a field, control, or property name that mydatabasename cant find.

我认为这个问题是我需要设置控制源txtPageFrom和txtPageTo。但如何做呢?这种形式只能通过VBA方法试图打印报表加载,所以对于txtPageFrom和txtPageTo值将​​来自调用的方法,而不是从一些基础数据表。 (有此对话框的形式没有基础数据表。)

I think the problem is that I need to set the control source for txtPageFrom and txtPageTo. But how do I do that? This form will only be loaded by a vba method that is trying to print a report, so the values for txtPageFrom and txtPageTo will come from the calling method, not from some underlying data table. (there is no underlying data table for this dialog form.)

cmbPrinter和optLayout似乎正确地使用上面的code进行填充。

cmbPrinter and optLayout seem to be populating correctly using the code above.

谁能告诉我怎么走过去,这样的形式加载正确的错误消息?

Can anyone show me how to get past the error messages so that the form loads properly?

正确的,完整的答案:的

CORRECT, COMPLETE ANSWER:

回答这个问题是大大简化了code。在code在此张贴顶部的链接是太复杂,试图重塑的东西都是通过内置Access和VBA工具已经做得很好。我可以简单地使用下面的code在上单击事件报告相关的窗体上的控件的打印报告,没有任何复杂的解决方案:

The answer to this problem was to greatly simplify the code. The code in the link at the top of this posting is WAY TOO COMPLEX, and tries to reinvent things that are already done well by the tools built into Access and VBA. I was able to print reports without any of the complicated solutions by simply using the following code in the on-click event of a control on a form associated with the report:

Private Sub txtPrintReport_Click()
    On Error GoTo Error_Handler
    Dim commNum As Long
    commNum = Me.CommunicationNumber
    Dim strReport As String
    Dim strVarName As String
    strReport = "rptCommunicationFormForPrinting"
    strVarName = "CommunicationNumber"
    DoCmd.OpenReport strReport, acViewPreview, , strVarName & " = " & commNum, acWindowNormal, acHidden
    DoCmd.RunCommand acCmdPrint
    DoCmd.Close acReport, strReport
Exit_Point:
Exit Sub
Error_Handler:  'this handles the case where user clicks cancel button
    If Err.Number <> 2501 Then
        MsgBox Err.Description, _
        vbExclamation, "Error " & Err.Number
    End If
    DoCmd.Close acReport, strReport
End Sub  

这是所有被要求的code。比很多在这个问题开始的联系较少。和比下面的答案也少得多。我标志着约翰·宾汉姆的答案被接受的答案,因为他清楚地做了很多关于这一点,我非常感激。不过,我结束了少了很多code解决问题。我的解决方案并不需要自定义对话框形式,因为它使用了Windows打印对话框的形式。因此,在负载情况下code在我的帖子(取自上面的链接),是没有必要的。

That is all the code that was required. Much less than the link at the start of this question. And also much less than the answer below. I am marking John Bingham's answer as the accepted answer because he clearly worked a lot on this, and I am very grateful for that. But I ended up solving the problem with A LOT LESS CODE. My solution does not require the custom dialog form because it uses the Windows print dialog form. As such, the on load event code in my posting (taken from the link above), is not necessary.

推荐答案

在code贴不能正常工作,因为当一个形式打开一个对话框:

The code posted cannot work, because when a form is opened as a dialog:

DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport

这行后没有其他逻辑执行,直到形式已被关闭,这时控制返回到下一行这一块,和逻辑继续上 - 当然,除非你再也不能以这样的形式引用任何东西,因为现在是关闭的。

no other logic after this line is executed until the form has been closed, at which point control returns to the next line after this one, and logic continues on - except of course you can no longer reference anything in that form, because it is now closed.

好了,现在有一个问题,哪里是用户点击打印报表的按钮?

Ok, now there is a question, where is the button the user clicks to print a report?

我在想什么是在PrintReport逻辑分为两种方法,一种是启动它,并告诉表格对自身进行配置(在做注释的东西的建议),但PrintReport其余则需要发生用户点击后确定(或取消);

What I'm thinking is to split the logic in PrintReport into two methods, one that launches it, and tells the form to configure itself (doing the stuff suggested in the comment), but the rest of PrintReport then needs to happen after the user clicks OK (or Cancel);

所以,如果我假设你已经有了可以启动一个或多个报表的形式,和按钮是这种形式,我的建议是这样的:

So if I assume that you've got a form which can launch one or more reports, and the button is on this form, what I would suggest is this:

在单击事件的按钮 - 没有改变你有什么

In the click event for that button - no changes to what you've got.

在该按钮的形式,补充一点:

In that buttons form, add this:

Public Sub DialogAccept()
    With Forms!dlgPrinter
        If .Tag <> "Cancel" Then
            Set Reports(strReport).Printer = Application.Printers((!cmbPrinter))
            Reports(strReport).Printer.Orientation = !optLayout
            Application.Echo False
            DoCmd.SelectObject acReport, strReport
            DoCmd.PrintOut acPages, !txtPageFrom, !txtPageTo
            PrintReport = True
        End If
    End With
    DoCmd.Close acForm, "dlgPrinter"
    DoCmd.Close acReport, strReport
    Application.Echo True
End Sub

更改PrintReport为:

Change PrintReport to:

Public Function PrintReport(strReport As String, strVarName As String, numVal As Long) As Boolean
    ' open report in PREVIEW mode but HIDDEN
    DoCmd.OpenReport strReport, acViewPreview, , strVarName & " = " & numVal, acHidden

    'DoCmd.OpenReport strReport, acViewPreview, , , acHidden
    ' open the dialog form to let the user choose printing options
    DoCmd.OpenForm "dlgPrinter", , , , , , strReport
    Forms!dlgPrinter.Configure
End Function

在确定/取消对dlgPrinter放按钮点击事件(现有code,但去掉Docmd.close的任何实例后):

In the OK/Cancel button click events on dlgPrinter put (after existing code, but removing any instances of "Docmd.close"):

Forms!Calling_Form_Name.DialogAccept

这则调用该方法,这样做是为了发生后用户的东西,说:我与对话完成。

This then calls that method, to do the stuff that is meant to happen after the user says "I'm done with the dialog".

最后的配置方法添加到dlgPrinter:

Finally add the configure method to dlgPrinter:

Public Sub Configure()
    With Reports(Me.Tag).Printer
        Me!cmbPrinter = .DeviceName
        Me!optLayout = .Orientation
    End With
    Dim numPages As String
    numPages = Reports(Me.Tag).Pages
    Debug.Print "numPages = " & numPages
    TypeName(Me.txtPageTo) 'added this line as a test after
    Me.txtPageTo.Value = numPages
End Sub

和距离的Form_Load删除此code部分。

And remove this code section from Form_Load.

Hoep这会有所帮助。

Hoep this helps.

最后,如果该键启动dlgPrinter可以不同的形式,改变这一行:

Lastly, if the form on which the button launching dlgPrinter can vary, change this line:

DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport

DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport & ";" & me.Name

在dlgPrinter中的Form_Load,用左()及分手me.Openargs; MID()与INSTR(),并保存me.Name成什么形式的标记(这你不是已经在使用的标记)。

In form_load of dlgPrinter, break up me.Openargs using left() & mid() with instr(), and save me.Name into the tag of something on the form (which you're not already using the tag of).

在确定/取消按钮点击事件,改变code以上:

In the OK/Cancel button click events, change the code above to:

Forms(Object.Tag).DialogAccept