使用VBA的MS Access打印报告
我有一个非常强大的VBA报告。当我预览它时,一切都很棒,但是当我预览完东西后打印出来的时候会变得古怪。我花了很多时间缩小了可能性,并且以一定的信心得出结论,这是MS Access中的一个错误。使用VBA的MS Access打印报告
到目前为止,我打印报告的方法是使用docmd.openreport "report"
打开报告。然后我使用docmd.printout
命令,以便我可以设置页面范围,排序规则等。
有没有办法直接打印报告,并且仍然可以设置诸如页面风格,整理等选项,而无需首先进行预览?
感谢, 杰夫
不久前,我有一个非常困难的情况下。我不得不做一些现场创作,移动和格式化,这只能以一种方式完成。我采取了一种大胆的方式,它变成了唯一的方法:我在设计模式下隐藏了报告,让vba做到了这一点,完成后,报告变为正常显示和打印。
一种解决方案是在报告设计中设置打印机选项,保存这些更改并打印出来。缺点是,除非您进入设计并进行更改,否则这会将报告与特定的打印机相关联。
DoCmd.OpenReport "ReportName", acViewDesign, Null, Null, acHidden
Dim oRpt As Report
Set oRpt = Reports(0)
oRpt.UseDefaultPrinter = False
oRpt.Printer = Application.Printers("printer name")
With oRpt.Printer
.PaperBin = acPRBNAuto
.PaperSize = acPRPSLetter
.Copies = 1
.PrintQuality = acPRPQMedium
End With
DoCmd.Close acReport, "ReportName", acSaveYes
DoCmd.OpenReport "ReportName", acViewNormal
Set oRpt = Nothing
不幸的是没有办法在代码中做到这一点完全整齐,但它仍然出台以来DoCmd.OpenReport方法的WindowMode参数来完成。这样就可以在打印预览模式下打开报告并将其隐藏起来。然后,您可以设置报表的打印机对象的属性(如输出打印机和方向),然后使用DoCmd.PrintOut打印页面范围。
有一点需要注意:
你不能在报表的OnOpen事件做到这一点,因为改变任何对布局产生影响,不会给你正确的结果。例如,如果在OnOpen事件中,您已从纵向更改为横向,您将无法准确计数报告中有多少页面,因为报告在OnOpen事件触发时未被格式化。尽管对于除页面以外的所有内容都没有问题。
我要实现这个的方式是使用公共函数和对话框。该功能会是这个样子:
Public Function PrintReport(strReport As String) As Boolean
' open report in PREVIEW mode but HIDDEN
DoCmd.OpenReport strReport, acViewPreview, , , acHidden
' open the dialog form to let the user choose printing options
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, strReport
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 Function
对话框的形式会是这个样子:
alt text http://dfenton.com/DFA/examples/PrinterProperties.png
正如你可以在上面看到,我打开此对话框与OpenArg参数,这是报告的名称。在对话框的onload事件,我初始化窗体上的控件:
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
Me!txtPageTo = Reports(strReport).Pages
End If
End If
我使用窗体的.TAG财产报告名称,然后以此为基础进行的一切,包括进行更改的飞行报告属性,这是可能的,因为报告以预览模式打开,但不可见。
举例来说,我有布局选项组这背后更新后事件:
With Reports(Me.Tag)
.Printer.Orientation = Me!optLayout
Me!txtPageTo = .Pages
End With
我改变页面范围内的数字的原因是因为改变方向将最有可能改变的页数。与OnOpen事件不同,在打印预览模式下无形打开的报告的格式属性更改会立即发生。
我用我的标准方法对话框的形式,这是有设置窗体的。可见属性设为False,它允许调用代码继续取消并继续按钮。对于“取消”按钮,我将表单的.Tag属性设置为“取消”,并在代码在调用上下文中继续时检查.Tag属性(请参见上文)。
那么,这是不是一样大,这将是能够直接将打印机对象的页面范围,但它能够完成任务。
生产代码中需要更改的一件事是确保PrintReport函数中有一个错误处理程序,以便如果出现错误,可以重新启用Application.Echo(否则,用户可能会卡住与一个空白的屏幕,无法工作)。另一种方法是在调用DoCmd.SelectObject方法时让报告出现在屏幕上。但是,如果我隐藏用户的报告预览,我会想要一路走下去。
欲了解更多信息,您应该在对象浏览器(VBE中的F2)中调查.Printer对象,并且MS Knowledge Base article 290293有助于解释Application.Printers集合和Application.Printer对象之间的交互以及与特定报告相关联。我还发现a little tutorial on the Office site澄清了一些事情。
这个答案是UNNECESSARILY COMPLEX。我能够使用Access'在我张贴在我的问题结束,在这个环节的答案内置方法做同样的事情在更少的代码:http://stackoverflow.com/questions/19802553/runtime-error -2448-你-着指派-a值到这个对象 – CodeMed 2013-11-06 18:14:47
唉。这听起来很丑陋。另一方面,它适合于正常的Access范例! – MJB 2010-04-18 14:59:38
BZZZZT !!!!它绝对不适合任何访问范例。直到Access 2002推出一个适当的打印机对象才能完全控制打印。这是因为VB和Windows打印系统存在遗留问题。引进MDE之前,它是不是这样的一个问题,因为你可以使在设计视图中的变化,但随着越来越多地使用MDES的(背后的幕后首先介绍了A95,并首次引入到最终用户的A97 ),它成了一个真正的问题。为什么花了他们这么长的时间才解决它,我不能说。 – 2010-04-18 22:50:05
相信与否,这实际上解决了我的问题。我知道这是很丑陋的,不得不在设计模式下打开它,但是,如果它有效,你能说什么? – Icode4food 2010-04-19 12:36:13