質問者
【Access VBA】DoCmd.PrintOutの挙動

質問
-
Access 2016のVBAで顧客管理プログラムを作成しています。
顧客リストを印刷するために、430個ほどのテキストボックスを配置したレポートフォームを用意しました(1ページに25人分)。
必要な情報を、テキストボックスに設定し、印刷をします。
ただし、宛先が3か所あり、宛先以外の情報は同じため、宛先だけを書き換えて(テキストボックスへの設定)、3枚印刷しようとしています。
パソコンの「通常使うプリンター」は「Microsft Print To PDF」に設定していますが、印刷は実プリンターです(紙で欲しいから)。
宛先は配列aryUsage()に格納されています。
下記コードのように、3回ループで処理しようとしました。
1枚目は実プリンターに出力(印刷)されますが、2枚目と3枚目は、PCの「通常使うプリンター」であるPDFのダイアログが表示されます。
(ダイアログの[キャンセル]を押せば処理は中断できる)
ループ内のどこか、あるいはループにしないで同じコードを3回書いて、そのどこかにブレークポイントを設定して一時停止させ、そのまま「F5」で続行すると実プリンターに出力されます。
タイミングの関係かと思い、DoCmd.PrintOutの前後に1秒または2秒のSleep機能を入れてみましたが、改善されません。
どうすれば、実プリンターで3枚印刷できるのでしょうか?
なお、レポートフォーム名は「REPORT_LIST」として定義しています。
'1ページを印刷(True:キャンセル、False:印刷)
Private Function PrintDoc() As Boolean
For papers = 0 To 2
Dim prtDefault As Printer
Dim printername As String
Dim papercode As Long
Dim papers As Long
On Error GoTo Err_Print
PrintDoc = False
printername = targetprinter.printername'他所にある構造体
If ("" = printername) Then
MsgBox "印刷するプリンターが設定されていません。", vbExclamation, "印刷"
Else
papercode = targetprinter.papercode
If (0 < papercode) Then
Set prtDefault = application.Printer '現在のプリンタ設定を退避
Reports.item(REPORT_LIST).Printer = application.Printers(printername)
Set application.Printer = prtDefault 'プリンタ設定を復帰
Reports.item(REPORT_LIST).Printer.PaperSize = papercode
Reports.item(REPORT_LIST).Controls("用途") = aryUsage(papers)
DoCmd.PrintOut acPrintAll
Next
End If
End If
Exit_Print:
Exit Function
Err_Print:
PrintDoc = True
If (2212 = Err.number Or 2501 = Err.number) Then '2212:PDF時、2501:実機
MsgBox "印刷はキャンセルされました。", vbOKOnly + vbInformation, "印刷"
Else
If (VbMsgBoxResult.vbCancel = MsgBox("コード:" + Str(Err.number) + vbCrLf + "詳細:" + Err.Description, vbExclamation, ”印刷”)) Then
GoTo Exit_Print
End If
End If
Resume Exit_Print
End Function
すべての返信
-
hex309さん、反応(でいいのかな)ありがとうございます。
ループの外に出しても同じです。
また、F8でも期待した動作をします。
自己レスですが、許容範囲内で解決しました。
ほぼ1日、悪戦苦闘というか試行錯誤した結果、論理的に正しいのかどうかわかりませんが、期待する動作ができるようになりました。コードは以下です。
宛先を変更する前に、再度レポートを開くとうまくいきました。
DoCmd.OpenReport REPORT_LIST, acViewReport
を追加しました。acViewReportはacViewPreviewでもいいです。
ただし、レポートのページ設定のプリンターをどう設定しているかにより、デフォルトプリンターの退避/復帰はなくても動作する場合があります。
また、
Private Const rptPapers As Long = 3
です。
Private Function PrintDoc() As Boolean
Dim prtDefault As Printer
Dim printername As String
Dim papername As String
Dim papercode As Long
Dim papers As Long
On Error GoTo Err_Print
PrintDoc = False
printername = targetprinter.printername
If ("" = printername) Then
MsgBox "印刷するプリンターが設定されていません。", vbExclamation, "印刷"
Else
papercode = targetprinter.papercode
If (0 < papercode) Then
Set prtDefault = application.Printer '現在のプリンタ設定を退避
Reports.item(REPORT_LIST).Printer = application.Printers(printername)
Reports.item(REPORT_LIST).Printer.PaperSize = papercode
For papers = 0 To rptPapers - 1
'すでに開いている記入済みのレポートを、ここで再度開くことにより、3枚共が指定のプリンターに出力される。
'なぜ?
DoCmd.OpenReport REPORT_LIST, acViewReport
Reports.item(REPORT_LIST).Controls("用途") = aryUsage(papers)
DoCmd.PrintOut 'デフォルトプリンタに直接印刷
Next
Set application.Printer = prtDefault 'プリンタ設定を復帰
End If
End If
Exit_Print:
Exit Function
Err_Print:
PrintDoc = True
If (2212 = Err.number Or 2501 = Err.number) Then '2212:PDF時、2501:実機
MsgBox "印刷はキャンセルされました。", vbOKOnly + vbInformation, "印刷"
Else
If (VbMsgBoxResult.vbCancel = MsgBox("コード:" + Str(Err.number) + vbCrLf + "詳細:" + Err.Description, vbExclamation, "印刷")) Then
GoTo Exit_Print
End If
End If
Resume Exit_Print
End Function
この追加したDoCmd.OpenReportの対するCloseはしていません。(Closeすると改めて開いたときに、テキストボックスがカラになるので)
呼び出し側で、開いた状態でテキストボックスに値を設定し、1ページになったらこのPrintDocで印刷をする。呼び出し側に戻ったら、レポートを閉じて、改めて開くことによりテキストボックスがカラになるので、次のページのデータを設定する。という流れです(つまり、Close→Openという操作で、テキストボックスのクリアをしている)。
あっ、今思ったのですが、PrintOutメソッドはアクティブなオブジェクトを印刷するということのようなので、OpenReportを実行することで、レポートがアクティブになるのかもしれません。