vba 运行时错误 2448 你不能给这个对象赋值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19802553/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
runtime error 2448 you cant assign a value to this object
提问by CodeMed
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:
我正在使用David-W-Fenton 对此问题的回答来尝试允许用户在单击控件时打印报告,但我收到以下错误消息:
runtime error 2448: you cannot assign a value to this object.
The line of code triggering the error is:
触发错误的代码行是:
Me.txtPageTo.Value = numPages
Here is the full code of the OnLoad event handler for the form:
这是表单的 OnLoad 事件处理程序的完整代码:
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 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.)
numPages 在抛出错误之前打印出来等于 0,即使报告应该至少有一页。此外,当表单已经打开时,不会抛出错误。只有在必须打开表单时才会抛出错误。(可能是因为违规代码在 onload 事件中。)
When I added TypeName(Me.txtPageTo) , it triggered runtime error 2424: The expression you entered has a field, control, or property name that mydatabasenamecant find.
当我添加 TypeName(Me.txtPageTo) 时,它触发了运行时错误 2424:您输入的表达式具有mydatabasename无法找到的字段、控件或属性名称。
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.)
我认为问题是我需要为txtPageFrom和txtPageTo设置控件源。但是我该怎么做呢?此表单将仅由尝试打印报告的 vba 方法加载,因此 txtPageFrom 和 txtPageTo 的值将来自调用方法,而不是来自某些基础数据表。(此对话框表单没有基础数据表。)
cmbPrinter and optLayout seem to be populating correctly using the code above.
cmbPrinter 和 optLayout 似乎使用上面的代码正确填充。
Can anyone show me how to get past the error messages so that the form loads properly?
谁能告诉我如何绕过错误消息以便正确加载表单?
CORRECT, COMPLETE ANSWER:
正确、完整的答案:
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:
这个问题的答案是大大简化代码。这篇文章顶部链接中的代码太复杂了,它试图重新发明那些已经被 Access 和 VBA 中内置的工具做得很好的东西。只需在与报告关联的表单上的控件的点击事件中使用以下代码,我就可以在没有任何复杂解决方案的情况下打印报告:
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
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.
这就是所需的全部代码。比这个问题开头的链接少得多。而且比下面的答案要少得多。我将约翰宾厄姆的答案标记为已接受的答案,因为他显然在这方面做了很多工作,对此我非常感激。但我最终用更少的代码解决了这个问题。我的解决方案不需要自定义对话框表单,因为它使用 Windows 打印对话框表单。因此,我的帖子中的 on load 事件代码(取自上面的链接)不是必需的。
采纳答案by John Bingham
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?
好的,现在有一个问题,用户点击打印报表的按钮在哪里?
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);
我在想的是将 PrintReport 中的逻辑拆分为两种方法,一种是启动它,并告诉表单进行自我配置(执行评论中建议的操作),但是 PrintReport 的其余部分需要在用户之后发生单击确定(或取消);
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
Change PrintReport to:
将 PrintReport 更改为:
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
In the OK/Cancel button click events on dlgPrinter put (after existing code, but removing any instances of "Docmd.close"):
在 dlgPrinter put 上的 OK/Cancel 按钮单击事件中(在现有代码之后,但删除“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".
然后调用该方法,以执行在用户说“我已完成对话框”之后发生的事情。
Finally add the configure method to dlgPrinter:
最后在dlgPrinter中添加configure方法:
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
And remove this code section from Form_Load.
并从 Form_Load 中删除此代码部分。
Hoep this helps.
希望这有帮助。
Lastly, if the form on which the button launching dlgPrinter can vary, change this line:
最后,如果启动 dlgPrinter 的按钮的表单可能有所不同,请更改以下行:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
to:
到:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport & ";" & 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).
在 dlgPrinter 的 form_load 中,使用 left() 和 mid() 将 me.Openargs 与 instr() 分开,并将 me.Name 保存到表单上某物的标记中(您尚未使用该标记)。
In the OK/Cancel button click events, change the code above to:
在确定/取消按钮单击事件中,将上面的代码更改为:
Forms(Object.Tag).DialogAccept