运行时错误 2448 你不能给这个对象赋值
Posted
技术标签:
【中文标题】运行时错误 2448 你不能给这个对象赋值【英文标题】:runtime error 2448 you cant assign a value to this object 【发布时间】:2013-11-06 01:47:03 【问题描述】:我正在使用David-W-Fenton's answer to this question 尝试允许用户在单击控件时打印报告,但我收到以下错误消息:
runtime error 2448: you cannot assign a value to this object.
触发错误的代码行是:
Me.txtPageTo.Value = numPages
这是表单的 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 在抛出错误之前打印出等于 0,即使报告应该至少有一页。此外,当表单已经打开时,不会引发错误。只有在必须打开表单时才会引发错误。 (可能是因为违规代码在 onload 事件中。)
当我添加 TypeName(Me.txtPageTo) 时,它触发了运行时错误 2424:您输入的表达式具有 mydatabasename 找不到的字段、控件或属性名称。
我认为问题是我需要为txtPageFrom和txtPageTo设置控制源。但是我该怎么做呢?此表单将仅由尝试打印报告的 vba 方法加载,因此 txtPageFrom 和 txtPageTo 的值将来自调用方法,而不是来自某些基础数据表。 (此对话框没有基础数据表。)
cmbPrinter 和 optLayout 似乎使用上面的代码正确填充。
谁能告诉我如何绕过错误消息以便正确加载表单?
正确,完整答案:
这个问题的答案是大大简化代码。这篇文章顶部链接中的代码太复杂了,它试图重新发明 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
这就是所需的所有代码。比这个问题开头的链接要少得多。而且也比下面的答案少得多。我将 John Bingham 的答案标记为已接受的答案,因为他显然在这方面做了很多工作,对此我非常感激。但我最终用 A LOT LESS CODE 解决了这个问题。我的解决方案不需要自定义对话框表单,因为它使用 Windows 打印对话框表单。因此,我的帖子中的加载事件代码(取自上面的链接)是不必要的。
【问题讨论】:
您需要将赋值给该对象的代码放入该对象所在部分的on格式事件中。 (昨天遇到这个问题!) 从您的描述中可以看出,控件是未绑定的。我本来希望它可以工作,但是将 .Value 从语句中删除,所以它只是:txtPageTo = numpages。这有帮助吗? 什么是numPages?即 debug.print 显示什么? 另外添加这一行:debug.Print Me.Name - 这给你什么? 这对我最有帮助还有一个原因。我以前使用 DoCmd.Printout 来打印报告,这很麻烦,因为作业直接进入默认打印机。使用 DoCmd.RunCommand acCmdPrint 首先弹出打印机对话框——正是我需要的。感谢 CodeMed 的提示。您相信 MSDN 上的 DoCmd.PrintOut 帮助页面中没有提及这一点吗? (我加了一个) 【参考方案1】:发布的代码无法工作,因为当表单作为对话框打开时:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
在关闭表单之前不会执行此行之后的其他逻辑,此时控制返回到该行之后的下一行,并且逻辑继续进行 - 当然您不能再引用该表单中的任何内容,因为现在关门了。
好的,现在有一个问题,用户点击打印报告的按钮在哪里?
我的想法是将 PrintReport 中的逻辑拆分为两种方法,一种是启动它,然后告诉表单进行自我配置(执行评论中建议的操作),但 PrintReport 的其余部分需要发生用户点击确定(或取消)后;
因此,如果我假设您有一个可以启动一个或多个报告的表单,并且按钮位于此表单上,那么我的建议是:
在该按钮的点击事件中 - 你所拥有的没有任何变化。
在那个按钮表单中,添加这个:
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 更改为:
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 put 上的 OK/Cancel 按钮单击事件(在现有代码之后,但删除“Docmd.close”的任何实例):
Forms!Calling_Form_Name.DialogAccept
然后这会调用该方法,以执行用户说“我已完成对话”后应该发生的事情。
最后在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
并从 Form_Load 中删除此代码部分。
希望这会有所帮助。
最后,如果启动 dlgPrinter 的按钮所在的窗体可以变化,请更改此行:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
到:
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport & ";" & me.Name
在 dlgPrinter 的 form_load 中,使用 left() 和 mid() 和 instr() 分解 me.Openargs,并将 me.Name 保存到表单上某些内容的标签中(您尚未使用)。
在OK/Cancel按钮点击事件中,将上面的代码改成:
Forms(Object.Tag).DialogAccept
【讨论】:
再次感谢您。我将此标记为正确答案,因为您为此花费了很多时间和精力。但我最终找到了一个更简单的解决方案,我在上面的原始帖子末尾发布了该解决方案。以上是关于运行时错误 2448 你不能给这个对象赋值的主要内容,如果未能解决你的问题,请参考以下文章
python中构建了一个类,在定义了一个函数时为啥括号第一个self有啥用,为啥不能给他赋值