none
【Access VBA】DoCmd.PrintOutの挙動 RRS feed

  • 質問

  • 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
        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 '現在のプリンタ設定を退避

                For papers = 0 To 2

                   Reports.item(REPORT_LIST).Printer = application.Printers(printername)
                   Reports.item(REPORT_LIST).Printer.PaperSize = papercode
                   Reports.item(REPORT_LIST).Controls("用途") = aryUsage(papers)
                   DoCmd.PrintOut acPrintAll 
                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


    2021年7月25日 4:54

すべての返信

  • こんにちは。

    回答でなくて申し訳有りません。以下いかがでしょうか?

    Reports.item(REPORT_LIST).Printer = application.Printers(printername)

    を、「For papers = 0 To 2」の手前(つまりループの外)に出しても同じでしょうか?

    また、ブレークポイントを設定し、F5で実行すると期待した動作になる、ということですが、このプロシージャ自体をF8でステップ実行した場合はいかがでしょうか?


    2021年7月26日 2:17
  • 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を実行することで、レポートがアクティブになるのかもしれません。

    2021年7月26日 10:48