Access VBAでプリンター一覧の取得と指定したプリンターへの印刷を実装していきます。特に実務では固定のプリンターを使うこともあるでしょうが、プリンターを変更する場合もあるので作っておくと便利です。VBAでのPDF印刷も同期・非同期で触れていきます。
リストへプリンター一覧をセット
Private Sub Form_Load()
'フォーム読み込み時
Dim prt As Printer
'すべてのプリンタを列挙してコンボボックスの値集合ソースに追加
For Each prt In Application.Printers
Me.リスト10.AddItem prt.DeviceName
Next prt
End Sub
フォームロード時にリストにForループでプリンターのデバイス名をセットして表示しています。
ボタン押下でPDF非同期印刷
Private Sub コマンド12_Click()
'[印刷]ボタンクリック時
'プリンタ変数を宣言
Dim prtDefault As Printer
'現在のプリンタ設定を退避
Set prtDefault = Application.Printer 'これがデフォルトプリンタ
'選択されたプリンタの情報を設定
Set Application.Printer = Application.Printers(Me.リスト10.Value)
'印刷するぞ
'シェルオブジェクトの作成
Dim shellObj As Object
Set shellObj = CreateObject("WScript.shell")
Dim exeStm As String
'コマンドラインの文字列を作成する
exeStm = "AcroRd32.exe /t" & " " & "C:\Users\XXXXX\Desktop\test.pdf" & " " & Application.Printer.DeviceName
shellObj.Run (exeStm) '印刷する
'プリンタ設定を元に戻す
Set Application.Printer = prtDefault
Set prtDefault = Nothing
End Sub
この例ではボタン押下でデスクトップのtest.pdfを印刷しています。必要に応じて上記コードのディレクトリ指定のコマンドライン文字列を変更すれば適応範囲が広がると思います。
デフォルトプリンターを一旦保持しておいて、印刷指定のプリンターを選択してから印刷させています。もちろん印刷が終わったらデフォルトプリンターを元に戻します。
AcroRd32.exeはアドビのPDFビュアーをインストールすると自動でインストールされる実行ファイルになりPDFはこちらを使ってVBAから印刷します。なおこの処理は非同期処理のため連続で印刷ボタンを押すと予期しない動作となりますが、test.pdfが小さい場合は問題は発生しません。
非同期・同期とは
今回の印刷の例では以下のように考えるとわかりやすいでしょう。
- 非同期処理(印刷) 印刷コマンドを一気に発行して処理が終了、あとはプリンター任せ。
- 同期処理(印刷) 印刷の一つ一つの終了を待って次の処理に進む。
PDF同期印刷
上のサンプルコードではAcroRd32.exeでの印刷処理は非同期処理となっており、印刷処理としては理に適っています。(いちいち印刷処理の終了を待って次の処理ってのは無駄です)しかし、時としてきちんと印刷処理が完了してから次の処理を行う必要も出てきます。
例えば印刷元ファイルの印刷が完了した時点でファイル名をVBAから変更してxxx(印刷済).xlsに変更するとかよく実務ではやっている事をVBAでできちゃいます。さらにこれらの処理が数百ファイルものエクセルファイルだとしたら同期処理でないと後々問題が発生してしまいます。
AcroRd32.exeでの同期処理
そこでAcroRd32.exeについて検索していると、空のAcroRd32.exeを一つ起動しておき、印刷はそれぞれ追加でAcroRd32.exeをインスタンス化させながら印刷処理すればそれぞれのインスタンス化された実態が印刷終了後に終了してくれるという情報があって「これでできるのかな?」なんて期待をしてみました。
- 印刷コマンドを発行前にAcroRd32.exeを一つからインスタンス化しておく
- shellObj.Run (exeStm), True, True オプションTrue True(二つ目のTrueで同期実行)させる
- AcroRd32.exe /n /t のオプション指定で印刷する
Private Sub ぼたん_Click()
'プリンタ設定
Dim prtDefault As Printer
'現在のプリンタ設定を退避
Set prtDefault = Application.Printer 'これがデフォルトプリンタ
'印刷するぞ
'Shell Objestの作成
Dim shellObj As Object
Set shellObj = CreateObject("WScript.shell")
Dim exeStm As String
'Acrobat Readerの一つ目インスタンスを起動
shellObj.Run "AcroRd32.exe"
'起動するまで長めに待機
Sleep 5000 'Sleep APIは別途Declearしておく
'Acrobat Readerでプリントアウトするコマンドを三つ作っておく。
'/n インスタンスを新規で作成するオプション
'/t 印刷オプション
exeStm = "AcroRd32.exe /n /t" & " " & "C:\Users\xxx\Desktop\test.pdf" & " " & Application.Printer.DeviceName
shellObj.Run (exeStm), True, True '同期処理で印刷
exeStm = "AcroRd32.exe /n /t" & " " & "C:\Users\xxx\Desktop\test2.pdf" & " " & Application.Printer.DeviceName
shellObj.Run (exeStm), True, True '同期処理で印刷
exeStm = "AcroRd32.exe /n /t" & " " & "C:\Users\xxx\Desktop\test3.pdf" & " " & Application.Printer.DeviceName
shellObj.Run (exeStm), True, True '同期処理で印刷
Set prtDefault = Nothing
Set shellObj = Nothing
End Sub
上記のサンプルコードではshellObj.Run “AcroRd32.exe”で空のインスタンス化させておき、shellObj.Run (exeStm), True, Trueで同期処理のオプションを指定しながら、shellObj.runして印刷自体をインスタンス化かせたAcroRd32.exeに担ってもらっています。おそらく同期処理の管理を空でインスタンス化されたオブジェクトが担っています。
myExcel.ActiveWorkbook.PrintOut ActivePrinter:=Me.リスト10
Excelファイルの印刷を行うのであれば上記の様に変更しましょう。
注意点
AcroRd32.exe自体はAdobeが無料で提供しているPDF Readerの実態であるため、仕様がいつ変更になっても文句いえませんので、この記事の情報では使えなくなるということもそのうち起こり得ます。その点はご注意を。
VBScriptでの例
Option Explicit
Dim f, gf, so, ws
dim cmdString
Set so = CreateObject("Scripting.FileSystemObject")
Set gf = so.GetFolder(".")
Set ws =CreateObject("WScript.Shell")
Dim sapi
Set sapi = CreateObject("SAPI.SpVoice")
'AcroRd32.exe一つ起動しておく。
ws.Run "AcroRd32.exe"
WScript.Sleep 5000
'フォルダ内のPDFファイルをそれぞれ/n/tで印刷をループさせる。
For Each f In gf.Files
If LCase(so.GetExtensionName(f.Name)) = "pdf" Then
'上手く印刷が終わるまで同期してくれる。
cmdString = "AcroRd32.exe /n /t " & """" & f.path & """"
ws.Run cmdString,true,true
sapi.Speak "ichimai owattayo"
End If
Next
sapi.Speak "zenbu owattayo"
Set gf = Nothing
Set so = Nothing
Set ws = Nothing
Set sapi = Nothing
'MsgBox("Finished Printing")
こちらの例はVBScriptの例です、簡単にVBScriptのファイルをダブルクリックで印刷できるので実務ツールとして配布ってのも可能でしょう。
この辺りの便利ツールはいざ作ってみると結構ハードルが高いというかやった事ない事が多いので調べながら作ると時間かかってしまいますよね。
まとめ
VBAでのプリンター一覧 デバイス名を取得してリスト管理すれば可能
VBAでのPDF印刷方法 同期処理と非同期処理 AcroRd32.exeのインスタンス化を工夫するのと同期オプションの指定で可能。Excelファイルの印刷はそもそも同期処理なので考慮の必要なし。
参考書籍
個人的には↑このAccess VBA パーフェクトマスターがお勧め。ある程度Accessのフォームとか作れるんだけど「えっとどうするんだったっけ?」って時にぱらぱらみるとネットで検索するよりも楽です。
コメント