使用 VBA 的 MS Access 打印报告
Posted
技术标签:
【中文标题】使用 VBA 的 MS Access 打印报告【英文标题】:MS Access Print Report using VBA 【发布时间】:2010-04-18 01:06:13 【问题描述】:我有一份 VBA 密集型报告。当我预览它时,一切都很好,但是当我在预览后打印它时,事情就变得古怪了。我花了很多时间来缩小可能性范围,并以一定程度的信心得出结论,这是 MS Access 中的一个错误。
到目前为止,我打印报告的方法是使用docmd.openreport "report"
打开报告。然后我使用docmd.printout
命令来设置页面范围、排序规则等。
有没有办法直接打印报告,并且仍然能够设置页面范围、整理等选项,而无需先进行预览?
谢谢, 杰夫
【问题讨论】:
【参考方案1】:不幸的是,没有办法在代码中完全整齐地做到这一点,但由于引入了 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
对话框看起来像这样:
(来源:dfenton.com)
正如您在上面看到的,我使用 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 属性作为报告名称,然后基于此执行所有操作,包括动态更改报告属性,这是可能的,因为报告在预览模式下打开,但不可见。
例如,我在 Layout 选项组后面有这个 AfterUpdate 事件:
With Reports(Me.Tag)
.Printer.Orientation = Me!optLayout
Me!txtPageTo = .Pages
End With
我更改页面范围编号的原因是因为更改方向很可能会更改页数。与 OnOpen 事件不同,对在打印预览模式下不可见打开的报表的格式属性的更改会立即发生。
我对对话框表单使用我的标准方法,即让“取消”和“继续”按钮将表单的 .Visible 属性设置为 False,这允许调用代码继续。对于取消按钮,我将表单的 .Tag 属性设置为“取消”,并在代码在调用上下文中继续时检查 .Tag 属性(见上文)。
因此,这不如直接在 Printer 对象上设置页面范围那么好,但它可以完成工作。
需要在生产代码中更改的一件事是确保 PrintReport 函数中有一个错误处理程序,以便如果出现问题,可以重新打开 Application.Echo(否则,用户可能会遇到一个空白的屏幕,无法工作)。另一种方法是在调用 DoCmd.SelectObject 方法时让报表出现在屏幕上。但如果我对用户隐藏报表预览,我会想一路走下去。
有关这方面的更多信息,您应该研究对象浏览器中的 .Printer 对象(VBE 中的 F2),MS Knowledge Base article 290293 有助于解释 Application.Printers 集合和 Application.Printer 对象之间的交互以及与特定报告相关联的。我还发现 a little tutorial on the Office site 澄清了一些事情。
【讨论】:
这个答案非常复杂。我可以在 MUCH LESS CODE 中使用 Access 的内置方法做同样的事情,我在这个链接的问题末尾发布的答案中:***.com/questions/19802553/…【参考方案2】:很久以前,我有一个非常困难的案例。我必须做一些现场创作,移动和格式化,这只能通过一种方式完成。我采取了一种大胆的方法,它变成了唯一的方法:我在设计模式下打开隐藏的报表,让 vba 完成它的工作,完成后,报表变为正常且可见以显示和打印。
【讨论】:
呃。这听起来很丑陋。另一方面,它符合正常的 Access 范式! BZZZZT!!!!它绝对不适合任何访问范式。直到 Access 2002 才引入了允许完全控制打印的适当打印机对象。这是因为 VB 和 Windows 打印系统的遗留问题。在引入 MDE 之前,这不是一个问题,因为您可以在设计视图中进行更改,但随着 MDE 使用的增加(在 A95 中首次在幕后引入,在 A97 中首次引入最终用户),这成了一个真正的问题。为什么他们花了这么长时间来修复它,我不能说。 信不信由你,这实际上解决了我的问题。我知道必须在设计模式下打开它是丑陋的,但是嘿,如果它有效,你能说什么? 这是一个糟糕的解决方案,因为如果您决定将前端作为 ACCDE/MDE 分发,它将会中断,因为这些格式的对象不可编辑(这是该格式存在的原因之一) . 很多建议似乎实际上都很好地落入了“你不需要它”(YAGNI) 的废纸篓中。【参考方案3】:一种解决方案是在报表设计中设置打印机选项,保存这些更改并打印它。不利的一面是,除非您进入设计并更改它,否则这会将报告绑定到特定的打印机。
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
【讨论】:
以上是关于使用 VBA 的 MS Access 打印报告的主要内容,如果未能解决你的问题,请参考以下文章
MS Access VBA 并使用 unicode UTF-8 / UTF-16 报告问题
通过 VBA 自动使用查询从 Ms Access 2007 生成报告