- ベストアンサー
プリンタが通信可能か調査する
EXCELのVBAで、シートを自動印刷するような処理を作成したのですが、 実際に印刷をかける前にプリンタと通信可能、ケーブルが接続されている・ プリンタの電源が入っているなどのチェックをかける処理を入れたいのですが どのことは可能なのでしょうか?
- みんなの回答 (1)
- 専門家の回答
質問者が選んだベストアンサー
APIを使えば、できなくなないのですが、結構 難しいです。難しい割に、あまり使えません。 というのは、ステータスを聞きにいっても、プリンタ に問い合わせを行うわけでなく、現在のプリント マネージャの知っている状態で答えが返ってくる ためで、あたりまえですが、紙がきれていても、 エラーが発生してなければ、エラーとはなりません。 という訳ですが、一応プログラムをつけておきます。 はっきりいって、テスト不足です。実際にお使いに なる場合は、チェックをしてからにしてください。 Option Explicit ' プリンタアクセス権を定義する構造体の宣言 Private Type PRINTER_DEFAULTS pDatatype As Long pDevMode As Long DesiredAccess As Long End Type ' 標準的な権利を要求することを示す定数の宣言 Private Const STANDARD_RIGHTS_REQUIRED = &HF0000 ' プリンタアクセス権の管理者権限を示す定数の宣言 Private Const PRINTER_ACCESS_ADMINISTER = &H4& ' プリンタアクセス権のユーザー権限を示す定数の宣言 Private Const PRINTER_ACCESS_USE = &H8& ' プリンタアクセス権すべての権限を示す定数の宣言 Private Const PRINTER_ALL_ACCESS = _ (STANDARD_RIGHTS_REQUIRED Or _ PRINTER_ACCESS_ADMINISTER Or _ PRINTER_ACCESS_USE) ' プリンタのオブジェクトハンドルを取得する関数の宣言 Private Declare Function OpenPrinter Lib "WINSPOOL.DRV" _ Alias "OpenPrinterA" _ (ByVal pPrinterName As String, _ phPrinter As Long, _ pDefault As Any) As Long ' 詳細なプリンタ情報を定義する構造体の宣言 Private Type PRINTER_INFO_2 pServerName As Long pPrinterName As Long pShareName As Long pPortName As Long pDriverName As Long pComment As Long pLocation As Long pDevMode As Long pSepFile As Long pPrintProcessor As Long pDatatype As Long pParameters As Long pSecurityDescriptor As Long Attributes As Long Priority As Long DefaultPriority As Long StartTime As Long UntilTime As Long Status As Long cJobs As Long AveragePPM As Long End Type ' プリンタの詳細な情報を取得する関数の宣言 Private Declare Function GetPrinter Lib "WINSPOOL.DRV" _ Alias "GetPrinterA" _ (ByVal hPrinter As Long, _ ByVal Level As Long, _ pPrinter As Any, _ ByVal cbBuf As Long, _ pcbNeeded As Long) As Long ' 日付と時刻を定義する構造体の宣言 Private Type SYSTEMTIME wYear As Integer wMonth As Integer wDayOfWeek As Integer wDay As Integer wHour As Integer wMinute As Integer wSecond As Integer wMilliseconds As Integer End Type ' 印刷ジョブ情報を定義する構造体の宣言 Private Type JOB_INFO_1 JobId As Long pPrinterName As Long pMachineName As Long pUserName As Long pDocument As Long pDatatype As Long pStatus As Long Status As Long Priority As Long Position As Long TotalPages As Long PagesPrinted As Long Submitted As SYSTEMTIME End Type ' 一時停止を示す定数の宣言 Private Const JOB_STATUS_PAUSED = &H1 ' エラーを示す定数の宣言 Private Const JOB_STATUS_ERROR = &H2 ' 削除中を示す定数の宣言 Private Const JOB_STATUS_DELETING = &H4 ' スプールを示す定数の宣言 Private Const JOB_STATUS_SPOOLING = &H8 ' 印刷中を示す定数の宣言 Private Const JOB_STATUS_PRINTING = &H10 ' オフラインを示す定数の宣言 Private Const JOB_STATUS_OFFLINE = &H20 ' 用紙切れを示す定数の宣言 Private Const JOB_STATUS_PAPEROUT = &H40 ' 完了を示す定数の宣言 Private Const JOB_STATUS_PRINTED = &H80 ' 削除を示す定数の宣言 Private Const JOB_STATUS_DELETED = &H100 ' ドライバエラーを示す定数の宣言 Private Const JOB_STATUS_BLOCKED_DEVQ = &H200 ' 機器不良を示す定数の宣言 Private Const JOB_STATUS_USER_INTERVENTION = &H400 ' 再起動中を示す定数の宣言 Private Const JOB_STATUS_RESTART = &H800 ' プリンタの印刷ジョブを列挙する関数の宣言 Private Declare Function EnumJobs Lib "WINSPOOL.DRV" _ Alias "EnumJobsA" _ (ByVal hPrinter As Long, _ ByVal FirstJob As Long, _ ByVal NoJobs As Long, _ ByVal Level As Long, _ pJob As Any, _ ByVal cdBuf As Long, _ pcbNeeded As Long, _ pcReturned As Long) As Long ' ある位置から別の位置にメモリブロックを移動する関数の宣言 Private Declare Sub MoveMemory Lib "kernel32.dll" _ Alias "RtlMoveMemory" _ (Destination As Any, _ Source As Any, _ ByVal length As Long) ' 文字列をバッファにコピーする関数の宣言 Private Declare Function lstrcpy Lib "kernel32.dll" _ Alias "lstrcpyA" _ (lpString1 As Any, _ lpString2 As Any) As Long ' プリンタのオブジェクトハンドルを破棄する関数の宣言 Private Declare Function ClosePrinter Lib "WINSPOOL.DRV" _ (ByVal hPrinter As Long) As Long Private Const PRINTER_STATUS_BUSY = &H200 Private Const PRINTER_STATUS_DOOR_OPEN = &H400000 Private Const PRINTER_STATUS_ERROR = &H2 Private Const PRINTER_STATUS_INITIALIZING = &H8000 Private Const PRINTER_STATUS_IO_ACTIVE = &H100 Private Const PRINTER_STATUS_MANUAL_FEED = &H20 Private Const PRINTER_STATUS_NO_TONER = &H40000 Private Const PRINTER_STATUS_NOT_AVAILABLE = &H1000 Private Const PRINTER_STATUS_OFFLINE = &H80 Private Const PRINTER_STATUS_OUT_OF_MEMORY = &H200000 Private Const PRINTER_STATUS_OUTPUT_BIN_FULL = &H800 Private Const PRINTER_STATUS_PAGE_PUNT = &H80000 Private Const PRINTER_STATUS_PAPER_JAM = &H8 Private Const PRINTER_STATUS_PAPER_OUT = &H10 Private Const PRINTER_STATUS_PAPER_PROBLEM = &H40 Private Const PRINTER_STATUS_PAUSED = &H1 Private Const PRINTER_STATUS_PENDING_DELETION = &H4 Private Const PRINTER_STATUS_PRINTING = &H400 Private Const PRINTER_STATUS_PROCESSING = &H4000 Private Const PRINTER_STATUS_TONER_LOW = &H20000 Private Const PRINTER_STATUS_USER_INTERVENTION = &H100000 Private Const PRINTER_STATUS_WAITING = &H2000 Private Const PRINTER_STATUS_WARMING_UP = &H10000 Private Sub GetPrintStatus() If IsPrinterError() Then MsgBox "エラーです。" Else MsgBox "プリンタは正常です。" End If End Sub ' ' プリンタにエラーが発生しているとTrueを返す関数 ' Function IsPrinterError() As Boolean Dim strPrinterDeviceName As String Dim udtPrinterDefaults As PRINTER_DEFAULTS Dim lngPrinterHandle As Long Dim lngJobInfo1FirstJob As Long Dim lngJobInfo1EnumerateJob As Long Dim lngJobInfo1Level As Long Dim lngJobInfo1Needed As Long Dim lngJobInfo1Returned As Long Dim bytJobInfo1Buffer() As Byte Dim udtJobInfo1() As JOB_INFO_1 Dim lngJobInfo1Count As Long Dim lngWin32apiResultCode As Long Dim lngPrinterInfo2Level As Long Dim lngPrinterInfo2Needed As Long Dim bytPrinterInfo2Buffer() As Byte Dim udtPrinterInfo2 As PRINTER_INFO_2 Dim sPrinterName As String IsPrinterError = False ' プリンタ名を指定 ' VBの場合は、Printer.DeviceNameでOK ' strPrinterDeviceName = _ ' Printer.DeviceName sPrinterName = Application.ActivePrinter If InStr(sPrinterName, " on ") > 0 Then sPrinterName = Left(sPrinterName, InStr(sPrinterName, " on ") - 1) End If If InStr(sPrinterName, " の ") > 0 Then sPrinterName = Left(sPrinterName, InStr(sPrinterName, " の ") - 1) End If strPrinterDeviceName = _ sPrinterName ' プリンタアクセス権を指定 With udtPrinterDefaults .DesiredAccess = PRINTER_ALL_ACCESS End With ' プリンタのオブジェクトハンドルを取得 lngWin32apiResultCode = _ OpenPrinter(strPrinterDeviceName, _ lngPrinterHandle, _ udtPrinterDefaults) ' 構造体のレベルを指定 lngPrinterInfo2Level = 2 ' バッファに必要なサイズを取得 lngWin32apiResultCode = _ GetPrinter(lngPrinterHandle, _ lngPrinterInfo2Level, _ ByVal vbNullString, _ 0, _ lngPrinterInfo2Needed) ' バッファを確保 ReDim _ bytPrinterInfo2Buffer _ (lngPrinterInfo2Needed - 1) ' 詳細なプリンタ情報を取得 lngWin32apiResultCode = _ GetPrinter(lngPrinterHandle, _ lngPrinterInfo2Level, _ bytPrinterInfo2Buffer(0), _ lngPrinterInfo2Needed, _ lngPrinterInfo2Needed) ' 取得した詳細なプリンタ情報を構造体へ移動 MoveMemory _ udtPrinterInfo2, _ bytPrinterInfo2Buffer(0), _ Len(udtPrinterInfo2) 'プリンタのステータスの取得 If udtPrinterInfo2.Status And _ (PRINTER_STATUS_ERROR Or _ PRINTER_STATUS_PAPER_JAM Or _ PRINTER_STATUS_PAPER_OUT Or _ PRINTER_STATUS_PAPER_PROBLEM Or _ PRINTER_STATUS_OUTPUT_BIN_FULL Or _ PRINTER_STATUS_NOT_AVAILABLE Or _ PRINTER_STATUS_NO_TONER Or _ PRINTER_STATUS_OUT_OF_MEMORY Or _ PRINTER_STATUS_OFFLINE Or _ PRINTER_STATUS_DOOR_OPEN) <> 0 Then MsgBox "プリンタステータス=" & Hex$(udtPrinterInfo2.Status) IsPrinterError = True GoTo TerminateEnumJobs End If ' 最初に列挙する印刷ジョブを指定 lngJobInfo1FirstJob = 0 ' 列挙する印刷ジョブの総数を指定 lngJobInfo1EnumerateJob = 99 ' 構造体のレベルを指定 lngJobInfo1Level = 1 ' バッファに必要なサイズを取得 lngWin32apiResultCode = _ EnumJobs(lngPrinterHandle, _ lngJobInfo1FirstJob, _ lngJobInfo1EnumerateJob, _ lngJobInfo1Level, _ ByVal vbNullString, _ 0, _ lngJobInfo1Needed, _ lngJobInfo1Returned) ' 印刷ジョブが取得できないときは If lngJobInfo1Needed <= 0 Then IsPrinterError = False ' 取得できないときの終了処理へ分岐 GoTo TerminateEnumJobs End If ' バッファを確保 ReDim _ bytJobInfo1Buffer _ (lngJobInfo1Needed - 1) ' 印刷ジョブ情報を取得 lngWin32apiResultCode = _ EnumJobs(lngPrinterHandle, _ lngJobInfo1FirstJob, _ lngJobInfo1EnumerateJob, _ lngJobInfo1Level, _ bytJobInfo1Buffer(0), _ lngJobInfo1Needed, _ lngJobInfo1Needed, _ lngJobInfo1Returned) ' 取得した印刷ジョブ情報の構造体を確保 ReDim _ udtJobInfo1 _ (lngJobInfo1Returned - 1) ' 取得した印刷ジョブ情報を構造体へ移動 MoveMemory _ udtJobInfo1(0), _ bytJobInfo1Buffer(0), _ Len(udtJobInfo1(0)) * lngJobInfo1Returned ' バッファに印刷ジョブ情報がある間は For lngJobInfo1Count = 0 To lngJobInfo1Returned - 1 ' 状態を表示 If udtJobInfo1 _ (lngJobInfo1Count).Status And _ JOB_STATUS_PRINTING Then If udtJobInfo1 _ (lngJobInfo1Count).Status And _ (JOB_STATUS_ERROR Or _ JOB_STATUS_OFFLINE Or _ JOB_STATUS_PAPEROUT Or _ JOB_STATUS_BLOCKED_DEVQ) Then MsgBox "プリンタジョブステータス=" & Hex$(udtJobInfo1(lngJobInfo1Count).Status) IsPrinterError = True Exit For End If End If Next TerminateEnumJobs: ' プリンタオブジェクトをクローズ lngWin32apiResultCode = _ ClosePrinter(lngPrinterHandle) End Function