ACCESS2003 Aアクロバットでの印刷方法

このQ&Aのポイント
  • アクセスから2種類のドキュメントを連続してプリントアウトする方法について相談です。
  • 商品図面と顧客リストを順番通りにプリントアウトする方法がわかりません。
  • ネットで調べた結果、『WaitForSingleObject』関数を利用する方法があるようですが、難しいため助言を求めています。
回答を見る
  • ベストアンサー

ACCESS2003 Aアクロバットを介しての印刷

実はアクセスから2種類のドキュメントを連続してプリントアウトしたいと思っています。 ひとつは商品図面(PDF)でもうひとつはその商品の顧客リストです。かつ現場で間違わないように必ず(1)商品図面→(2)顧客リストの順番で出力する事が必須となります。 しかし(1)はAcrobatを介しての出力で(2)はアクセスからのダイレクト出力の為か、VB上での順番とは逆に実際には(2)→(1)の順番となってしまいます。 必ず(1)→(2)の出力順となるような方法はありませんでしょうか? ネットで調べたところ『WaitForSingleObject』なる関数があるようですが、素人の私ではこれが使えるのかどうか難しくて判りません。 下記がモジュールの内容です。宜しくアドバイスお願いします。 '**** (1)選択肢から選んだ商品図pdfを印刷する **** pass1 = "C:\商品図面\" & rstTable!図番 & ".pdf" & "" name1 = Dir(pass1) Dim objShell As New Shell32.Shell Dim objShellDP As Shell32.IShellDispatch2 Set objShellDP = objShell Call objShellDP.ShellExecute(pass1, , , "print", vbNormalFocus) Set objShellDP = Nothing Set objShell = Nothing '**** (2)該当する商品の顧客リストを印刷する **** DoCmd.OpenReport "R_顧客リスト", acViewNormal, "", "", acNormal '****

質問者が選んだベストアンサー

  • ベストアンサー
  • nicotinism
  • ベストアンサー率70% (1019/1452)
回答No.4

WaitForSingleObject は呼び出し元がフリーズしたように感じるので 別解です。 Option Explicit Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 'http://www.wmifun.net/library/win32_printjob.html Function WaitPrintIn(ByVal DocName As String) As Boolean   Dim strComputer As String   Dim objWMIService As Object   Dim colPrintJobs As Object   Dim objPrintJob As Object   strComputer = "."   Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")      Set colPrintJobs = objWMIService.ExecQuery _     ("SELECT * FROM Win32_PrintJob WHERE Document = '" & DocName & "'")   If colPrintJobs.Count > 0 Then     WaitPrintIn = True   End If End Function Function WaitPrintOut(ByVal DocName As String) As Boolean   Dim strComputer As String   Dim objWMIService As Object   Dim colPrintJobs As Object   Dim objPrintJob As Object   strComputer = "."   Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")      Set colPrintJobs = objWMIService.ExecQuery _     ("SELECT * FROM Win32_PrintJob WHERE Document = '" & DocName & "'")   If colPrintJobs.Count = 0 Then     WaitPrintOut = True   End If End Function Sub こまんど()   Dim Pass1 As String   Dim oFs As Object   Dim oShell As Object   Dim sName As String   Set oFs = CreateObject("Scripting.FilesystemObject")   Set oShell = CreateObject("Shell.Application")   Pass1 = "C:\商品図面\" & rstTable!図番 & ".pdf"   sName = oFs.getFilename(Pass1)   Call oShell.ShellExecute(Pass1, , , "print", vbNormalFocus)   Do Until WaitPrintIn(sName) = True '印刷処理に取り掛かるまで待機     Sleep 500     DoEvents   Loop   Do Until WaitPrintOut(sName) = True '印刷が終わるまで待機     Sleep 500     DoEvents   Loop   MsgBox ""   'DoCmd.OpenReport "R_顧客リスト", acViewNormal, "", "", acNormal   'もしかしたら↑の一行だけをサブモジュールにして呼び出した方が良いかも   '途中省略   Set oFs = Nothing: Set oShell = Nothing   MsgBox "おしまい" End Sub ※試したわけではない(紙とインクがもったいない・・)ので結果は不明です。 とりあえず、お試しあれ。 投稿用にインデントの代わりに全角スペースを使っています。 なお、こちら(Windows7 AcroRD32 Ver10.1.1)では印刷終了後には アクロリーダーは自動的に閉じました。

Nick925
質問者

お礼

出来ました!完璧なシーケンスで複数種類のドキュメントが順番どおり出力されました。 感謝感激です。何とお礼を言ってよいやら... 本当に有難うございました。

その他の回答 (3)

  • nicotinism
  • ベストアンサー率70% (1019/1452)
回答No.3

これで良いのかな?よく分からんけど (^^ゞ Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _                            ByVal dwMilliseconds As Long) As Long Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _                        ByVal bInheritHandle As Long, _                        ByVal dwProcessId As Long) As Long Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long '--- Win32 API 定数の宣言 --- Global Const PROCESS_ALL_ACCESS As Long = &H1F0FFF Global Const INFINITE As Long = &HFFFF Sub WaitRun()   Dim TaskId As Long     'タスクID   Dim hProc As Variant   'プロセスハンドル   ' 外部プログラムの実行   TaskId = Shell("C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe /p " & "E:\PDF\20111111120222.pdf", 2)   ' プロセスハンドルの取得   hProc = OpenProcess(PROCESS_ALL_ACCESS, False, TaskId)   ' プロセスのオープン   If OpenProcess(PROCESS_ALL_ACCESS, False, TaskId) <> vbNull Then     ' プロセスのシグナル待ち     Call WaitForSingleObject(hProc, INFINITE)     ' プロセスクローズ     CloseHandle hProc   End If beep: beep MsgBox "" End Sub ネタ元はこちらです。丸写しです・・・ http://www.moug.net/tech/exvba/0150034.html

Nick925
質問者

お礼

私もあれからネットで探したモジュールのサンプルを改造して色々試してみました。外部プログラムでの作業が終了するまでルーチンを待機させる為には"WaitForSingleObject"関数が有効というところまではわかりましたが、外部プログラムそのものをマニュアルで閉じないと待機解除にならず、それでは担当者がPCに付きっ切りになってしまいます。 出来たら印刷終了を以ってプログラムが自動的に閉じられ、ルーチンも自動的に再開できないかと虫の良い事を考えています。 もう少し苦しんでみます。有難うございました。

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.2

Yahoo知恵袋でも答えたのですが、結局 > Call objShellDP.ShellExecute(pass1, , , "print", vbNormalFocus) が非同期処理になっているために、Adobe Readerの起動を待たずに > DoCmd.OpenReport "R_顧客リスト", acViewNormal, "", "", acNormal を実行してしまいます。 あちらの回答のようにプロセスIDを元に待つようにすれば、とりあえずは回避できるように思いますが、Adobe Readerの仕様上、印刷がが終了してもプログラムのプロセスは自動終了しません。ユーザーにAdobe Readerの終了を行ってもうら必要があると思いますが、それは構いませんか?

Nick925
質問者

お礼

有難うございます。実は金曜日までに仕上げるつもりで焦っていたのでYahoo!にも並行で質問させていただきました。こちらで併せて御礼申し上げます。 今回実は出力しようと思っている書類はACCESSからのダイレクト出力が2種類、Accrobat経由が2種類ありpdfは選択する商品によって枚数も多種多様です。 その4種類を順番に出力し且つ予め選択しておいた複数の商品を上から順番にひとつのルーチンでバッチ処理したいと考えています。 従って全ての出力が完了するまで、途中でマニュアル操作を加えるのは出来る限り避けたいと思っています。(都合の良い話で申し訳ありません) 先ほどネットで検索していたら"Shell"と"WaitForSingleObject"を組み合わせる事でシェルで実行したプロセスが完了するまでアプリの実行を待機できるとの記事を読みました。 "ShellExecute"を"Shell"に換えてAcrobat.exeの場所を特定する事でpdfのプリント中はVBを待機状態とし、その終了を以ってアプリの待機も解除するという様なことは無理でしょうか?

  • chieffish
  • ベストアンサー率44% (1149/2554)
回答No.1

顧客リストもPDFにして図面と結合したら?

Nick925
質問者

お礼

有難うございます。PDF図面はマスターで内容変更はありませんが、顧客リストは瞬間瞬間に変わってゆくデータベースですので毎回PDF化をするとしてもかなり負荷と時間のかかるルーチンになると思われます。 出来たら顧客リストは現行のままデータベースから直に出力処理したいと思っていますが、上手く行かない場合の代替案として検討させていただきます。

関連するQ&A

  • objIE  2個目のサイズが適用されません。

    VBAです。 Dim objShell As Object Dim objIE As New InternetExplorer Const READYSTATE_COMPLETE As Long = 4 Sub test1() Set objShell = CreateObject("Shell.Application") objIE.Visible = True objIE.Top = 0 objIE.Left = 0 objIE.Width = 100 objIE.Height = 100 objIE.navigate "http://www.goo.ne.jp/" objIE.Navigate2 "http://www.goo.ne.jp/", 2048 Set objIE = Nothing Set objShell = Nothing Set objShell = CreateObject("Shell.Application") objIE.Visible = True objIE.navigate "http://www.goo.ne.jp/" objIE.Navigate2 "http://www.goo.ne.jp/", 2048 'できない objIE.Top = 20 objIE.Left = 20 objIE.Width = 100 objIE.Height = 100 Set objIE = Nothing Set objShell = Nothing End Sub のように二つのブラウザを立ち上げて サイズを変えたいのですが 2個目のサイズが適用されません。 エラーにもなりません。 なぜでしょうか?

  • VBAでIE操作をするサンプル

    VBAでIE操作をするサンプルをネットでいくつか見ているのですが Sub Sample1() Dim objShell As Object Dim objIE As New InternetExplorer Set objShell = CreateObject("Shell.Application") objIE.Visible = True objIE.Navigate "http://www.yahoo.co.jp/" Set objIE = Nothing Set objShell = Nothing End Sub Sub Sample2() Dim objIE As InternetExplorer Set objIE = CreateObject("InternetExplorer.application") objIE.Visible = True objIE.Navigate "http://www.yahoo.co.jp/" Set objIE = Nothing End Sub ではどちらを使った方がいいのでしょうか? 圧倒的にSample2の方がネットでは多いのですが Sample1のやり方もあることを知りました。 Sample1の方法でブラウザを開くメリットはあるのでしょうか?

  • 削除が実行されない

    以下のvbsを実行しても rmdir が実行されません どうしたらよいでしょうか Dim objShell Dim wExec Dim strResult Set objShell = CreateObject("WScript.Shell") objShell.CurrentDirectory = "C:\Users\xxx\Desktop\test" objShell.Exec ("cmd /c dir 201406* /b/ad/s >> ログ.txt") Set wExec = objShell.Exec ("cmd /c for /R %d in (201406*) do rmdir /S /Q ""%d""") Set wExec = Nothing Set objShell = Nothing

  • VBのコードが理解できません 解説いただけないでしょうか?

    Dim ObjIE As Object Dim ObjShell As Object Dim ObjWindow As Object Dim WinExist As Boolean WinExist = False Set ObjShell = CreateObject("Shell.Application") For Each ObjWindow In ObjShell.Windows If TypeName(ObjWindow.Document) = "HTMLDocument" Then  WinExist = True  Set ObjIE = ObjWindow End If Next Set ObjShell = Nothing If Not WinExist = True Then Set ObjIE = CreateObject("InternetExplorer.Application") End If ObjIE.Navigate "http://nantokakantoka.html" ObjIE.Visible = True このコードを解説いただけないでしょうか? 特に WinExist For Each ObjWindow In ObjShell.Windows If TypeName(ObjWindow.Document) = "HTMLDocument" Then が何をしているのか分からないんです。

  • ipconfig /all を環境変数へ代入方法

    http://d.hatena.ne.jp/necoyama3/20081218/1229604217 にて、ipconfigコマンドを実行して標準出力を取得する方法があり、下記VBSで きちんと動くのですが、 ------------------------------- Dim objShell Dim wExec Dim sCmd Set objShell = CreateObject("WScript.Shell") ' コマンド生成 sCmd = "ipconfig" ' コマンド実行 Set wExec = objShell.Exec("%ComSpec% /c " & sCmd) Do While wExec.Status = 0 Loop Result = wExec.StdOut.ReadAll MsgBox Result Set wExec = Nothing Set objShell = Nothing ----------------------------------- sCmdを下記に差し替えると、動かなくなります。 sCmd = "ipconfig /all" もしくは sCmd = "systeminfo" これらコマンドに差し替えてもVBSを動かす方法は ありますでしょうか。 直接、コマンドラインで ipconfig /all や systeminfoを入力する場合は きちんと出力されます。

  • VBAでWebに値を入力

    VBAでWebに値を入力する操作を考えています。 エクセルシートのA1に入っている値をWeb上に入力する操作なのですが、 以下のコードを実行すると「AllLog.keyword.Value = t」の部分でエラーになります。 googleではkeywordのところを「q」、yahooではkeywordのところを「p」にすれば問題ないのですが、 神奈川中央交通のページではエラーになってしまいます。 なぜですか?? Sub google() Dim objIE As InternetExplorer '参照設定:Microsoft Shell Controls and Automation Dim objShell As Shell Dim WinFlg As Boolean Dim objWin As Object Dim AllLog As Object On Error GoTo EndProcess Set objShell = New Shell For Each objWin In objShell.Windows If TypeName(objWin) = "IWebBrowser2" Then WinFlg = True Set objIE = objWin Exit For End If Next Set objShell = Nothing If WinFlg = False Then MsgBox "IEオブジェクトが取得できません", vbCritical Exit Sub End If EndProcess: If Err() > 0 Then MsgBox Err.Description End If With objIE Set AllLog = .Document.all t = Cells(1, 1) AllLog.keyword.Value = t End With Set objIE = Nothing End Sub

  • エクセルVBAで、IEからコピーするには

    エクセル2000,win2000,IE6です。 次のような、コードを書きました。 Sub t03ccc() Dim objIE As Object 'IE オブジェクト参照用 Dim objShell As Object 'Shell オブジェクト参照用 Dim objWindow As Object 'Window オブジェクト参照用 Set objShell = CreateObject("Shell.Application") For Each objWindow In objShell.Windows '起動中のタイトルを探して。 If Left(objWindow.document.Title, 7) = "Office系" Then Set objIE = objWindow 'オブジェクトを代入 Msg = "Office系" Exit For End If Next If Msg <> "Office系" Then MsgBox "・・・スクリーニング結果一覧・・・がありません" Exit Sub End If objIE.ExecWB 17, 0 'OLECMDID_SELECTALL = 17 全てを選択 objIE.ExecWB 12, 0 'OLECMDID_COPY = 12 コピー Sheets("Sheet3").Select Rows("1:200").ClearContents Range("A1").Select ActiveSheet.Paste '''' objIE.Quit Set objIE = Nothing Set objShell = Nothing Set objWindow = Nothing End Sub これで、エクセルとIEしか開いてないときは巧くいくのですが、 エクスプローラーを同時に開くと実行時エラー438が出ます。 よろしくお願いします。

  • エクセルのデータからフォルダを作成

    エクセル選択・読み込み→フォルダ作成先指定・処理 →作成した空のフォルダを表示 という手順のプログラムです。 コモンダイアログで選んだエクセルのデータを元に、 新しいフォルダを作成したいと思っています。 エクセルには番号(一列目)、氏名(二列目)などが入っており 一人分の情報が一行目に、二人目の情報が二行目・・・という風に一行ずつに入っています。 指定した作成先に、そのエクセルで読み込んだ人数分だけ 空のフォルダを作成し、なおかつ一列目に入っていた番号を フォルダ名にしたいのですが、どうすればいいでしょうか。 途中まで作ってみましたが後が続きません。 よろしくお願いします。 Private Const BIF_RETURNONLYFSDIRS As Long = &H1 Dim objShell As New Shell Dim objFolder As Folder Private Sub Command1_Click() Set objShell = New Shell Set objFolder = objShell.BrowseForFolder(Me.hWnd, "フォルダを選択してください", BIF_RETURNONLYFSDIRS) If objFolder Is Nothing Then MsgBox "ファイルを開く作業をキャンセルします" Else End If Set objShell = Nothing End Sub

  • ACCESSのCSV出力に関して

    教えて下さい。 ACCESSであるテーブルのデータをCSV出力しようとして、以下のような記述をしました。 結果、問題なく出力されましたが、データだけでなく、項目も出力しようと考えています。 その際にはどのような記述をすれば良いでしょうか? 初歩的な質問で申し訳ありません。 教えて下さい。 《内容》 Dim cnn As ADODB.Connection Dim rst As ADODB.Recordset Dim stSQL As String Dim stTBL As String Dim myWSH As Object 'WScript Dim myDesktopPath As String Dim stPath As String 'フルパス Dim objFSO As Object 'FileSystemObject Dim fsoTS As Object 'TextStream Dim tmp As Variant 'データ Dim re As Variant 'データ件数 Dim stDocName As String Const ForAppending = 8 stTBL = "t_合算" 'テーブル名 '開始メッセージ stDocName = "「" & stTBL & ".CSV」 ファイルをデスクトップに作成します" If MsgBox(stDocName, vbYesNo) = vbNo Then Exit Sub 'デスクトップパス取得 Set myWSH = CreateObject("WScript.Shell") myDesktopPath = myWSH.SpecialFolders("Desktop") Set myWSH = Nothing 'フルパス stPath = myDesktopPath & "\" & stTBL & ".CSV" '読み取り専用でセット Set cnn = CurrentProject.Connection stSQL = "SELECT * FROM " & stTBL Set rst = cnn.Execute(stSQL) If rst.EOF Then stDocName = "出力するデータがありませんでした" Else '文字列データ格納 (全データ出力、カンマ区切り) tmp = rst.GetString(adClipString, , ",", vbNewLine) '出力 Set objFSO = CreateObject("Scripting.FileSystemObject") With objFSO If .FileExists(stPath) Then '既存ファイル削除 Call .DeleteFile(stPath) End If Set fsoTS = .OpenTextFile(stPath, ForAppending, True) '文字列一括書き出し fsoTS.WriteLine tmp re = fsoTS.Line - 2 End With Set fsoTS = Nothing: Set objFSO = Nothing stDocName = re & " 件の CSVデータを出力しました。" End If MsgBox stDocName, vbOKOnly

  • VBSでとある条件の時に処理をやらずに終了させる方法

    VBSでとある条件の時に処理をやらずに終了させる方法で悩んでいます。 Dim ObjIE Dim ObjShell Dim ObjWindow Dim WinExist WinExist = False Set ObjShell = CreateObject("Shell.Application") For Each ObjWindow In ObjShell.Windows If TypeName(ObjWindow.Document) = "HTMLDocument" Then WinExist = True Set ObjIE = ObjWindow End If Next Set ObjShell = Nothing If Not WinExist = True Then Set ObjIE = CreateObject("InternetExplorer.Application") End If ・ ・ ・ ・ 例えばこのように起動しているIEを探します そこでもしYahoo!JAPANが起動していたら以降の処理をやらずに終わらせたいのですが・・・ どのような記述にすればよいでしょうか?