不幸的是,没有办法在代码中完全整齐地做到这一点,但由于引入了 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 澄清了一些事情。