はじめに
Acrobatアプリケーションを OLE(IAC) 経由で操作するには大きく2つのやり方が存在します。
- Acrobatアプリケーションを画面に表示して操作する。
タスクバーにも表示されます。 - Acrobatアプリケーションを画面に表示しないで操作する。
タスクバーにも表示されません。
上記の2つをプログラミングから見ると「Show」メソッドを使用したのが上記1で、使用しなかったのが上記2です。
処理の関係上で「Show」メソッドを使用しなければいけない事も当然あります。
注:「Show」メソッドを使用しなくても「OpenAVDoc」メソッドのようにPDFドキュメントを画面に表示する命令によって、Acrobatアプリケーションが画面表示されてしまう事も有ります。
問題点
さて、ここで問題点が発生します。
上記の1番目の画面に表示して操作する場合です。
その問題点とは、
- メモリにAcrobatアプリケーションのプロセスが残る場合が有る。
事です。
なぜ、これが問題点かと言うと、OSの再起動が無い限りメモリ上に存在するからです。
次回にAcrobatアプリケーションを起動すると、前回の状態を維持した状態で起動(※正確には起動では無い。)するという事です。
つまり通常のアプリケーションの初期起動状態ではありません。
気をつけないと、とんでもない結果になってしまいます。
実際に何度もその状態に遭遇しました。システムエラー等にも遭遇します。
サンプル
これに対する対処方法です。
以下のサンプルでobjAcroAppオブジェクトの扱いに注目して下さい。
001 Sub AcroExch_App_Exit()
002
003 'Acrobatオブジェクトの定義&作成
004 'Acrobat 4,5,6の時
005 ' Dim objAcroApp As Acrobat.CAcroApp
006 ' Dim objAcroPDDoc As Acrobat.CAcroPDDoc
007 ' Set objAcroApp = CreateObject("AcroExch.App")
008 ' Set objAcroPDDoc = CreateObject("AcroExch.PDDoc")
009
010 'Acrobat 7,8,9の時
011 Dim objAcroApp As New Acrobat.AcroApp
012 Dim objAcroPDDoc As New Acrobat.AcroPDDoc
013
014 '以降はAcrobat全て共通
015 Dim lRet As Long '戻り値
016 Const CON_PDF_FILE = "C:\work\Test01.pdf"
017
018 'Acrobatを起動表示する
019 lRet = objAcroApp.Show
020 lRet = objAcroPDDoc.Open(CON_PDF_FILE)
021 '・・・・
022
023 'アプリケーションの終了
024 lRet = objAcroApp.Hide
025 lRet = objAcroApp.Exit
026
027 'オブジェクトの強制開放
028 Set objAcroPDDoc = Nothing
029 Set objAcroApp = Nothing
030
031 End Sub
Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
上記のサンプルでobjAcroAppオブジェクトの扱いに注目して下さい。
しかし、このサンプルには汎用性と安全性がありません。
理由はPDFドキュメントが画面表示された時に、そのPDFドキュメントを閉じ忘れると、同様にメモリ上にAcrobatアプリケーション・プロセスが残ってしまうからです。
そこで以下のサンプルを提案します。
001 Sub AcroExch_App_Exit()
002
003 'Acrobatオブジェクトの定義&作成
004 'Acrobat 4,5,6の時
005 ' Dim objAcroApp As Acrobat.CAcroApp
006 ' Dim objAcroPDDoc As Acrobat.CAcroPDDoc
007 ' Set objAcroApp = CreateObject("AcroExch.App")
008 ' Set objAcroPDDoc = CreateObject("AcroExch.PDDoc")
009
010 'Acrobat 7,8,9の時
011 Dim objAcroApp As New Acrobat.AcroApp
012 Dim objAcroPDDoc As New Acrobat.AcroPDDoc
013
014 '以降はAcrobat全て共通
015 Dim lRet As Long '戻り値
016 Const CON_PDF_FILE = "C:\work\Test01.pdf"
017
018 'Acrobatを起動表示する
019 lRet = objAcroApp.Show
020 lRet = objAcroPDDoc.Open(CON_PDF_FILE)
021 'PDFドキュメントを画面表示する
022 objAcroPDDoc.OpenAVDoc CON_PDF_FILE
023
024 '・・・・
025
026 '開いているPDFドキュメントを全て閉じる
027 lRet = objAcroApp.CloseAllDocs
028 'アプリケーションの終了
029 lRet = objAcroApp.Hide
030 lRet = objAcroApp.Exit
031
032 'オブジェクトの強制開放
033 Set objAcroPDDoc = Nothing
034 Set objAcroApp = Nothing
035
036 End Sub
Highlight:プログラミング言語のソースコードを構文で色分け (GUI編)
約束
そこで、約束事です。
- Acrobatアプリケーションを画面表示する、しない、に関わらずPDFドキュメントを使用したら、必ず以下のメソッドを最後に実行する。
lRet = objAcroApp.CloseAllDocs <-このメソッドは状況により変わる可能性があります。
lRet = objAcroApp.Hide
lRet = objAcroApp.Exit
Set objAcroAPP = Nothing - 上記「Hide」、「Exit」メソッドの順番を変えては駄目です。
順番を変えるとアプリケーションはメモリから消えません。 - 安全性の為に最後に「Set objAcroAPP = Nothing」を入れて、アプリケーション・オブジェクトを強制終了させています。
しかし、実際は「Hide」、「Exit」メソッドを事前実行していないと無意味になります。
プロセスの監視
とにかくテストでは必ずタスクマネージャーを立ち上げてAcrobatアプリケーション・プロセスが終了する事を確認して下さい。
< TOPへ >
管理人さん、お世話になります。
連結した複数のPDFが入ったフォルダを選択し、
そのPDFを1頁ずつ分割する。というvbaを作成しました。
連結したPDFは600~100位あります。
環境ですが
windows7 64ビット acrobat Pro8.1.0では、PDFの分割にかかる時間は10分以内です。
ところが、
xp sp2 acrobat Pro7.1.0では、PDFの分割に数時間かかってしまいます。
下記が、PDF分割時のコードです。
Dim objAcroApp As New Acrobat.AcroApp
Dim objAcroPDDoc As New Acrobat.AcroPDDoc
'Acrobatを起動表示する
lRet = objAcroApp.Show
'PDFファイルを開いて表示する
lRet = objAcroPDDoc.Open(Path & pdf_Name)
'頁の指定により分岐
If (pdfNumPage = 0) Then
'最初のページ以外削除する
lRet = objAcroPDDoc.DeletePages(1, pdfTotalPage - 1)
ElseIf (pdfNumPage + 1 = pdfTotalPage) Then
'最後のページ以外削除する
lRet = objAcroPDDoc.DeletePages(0, pdfNumPage - 1)
Else
b_pageFlg = True
'最初から指定-1頁ページ削除する
lRet = objAcroPDDoc.DeletePages(0, pdfNumPage - 1)
'別名でPDFファイルを保存する(変更した所だけ)
lRet = objAcroPDDoc.Save (&H0, "")
'Acrobatを起動表示する
lRet2 = objAcroApp.Show
'PDFファイルを開いて表示する
lRet2 = objAcroPDDoc.Open(pdf_Path & pdf_Name)
'3頁以上の場合
If (pdfTotalPage >= 3) Then
'pdfページ数取得
i_tmpPdfNumPage = getNumPage(pdf_Path & pdf_Name)
'最初のページ以外削除する
lRet2 = objAcroPDDoc.DeletePages(1, i_tmpPdfNumPage - 1)
End If
End If
If (b_pageFlg) Then
'別名でPDFファイルを保存する(変更した所だけ)
lRet2 = objAcroPDDoc.Save _
(&H0, _
"")
Else
'別名でPDFファイルを保存する(変更した所だけ)
lRet = objAcroPDDoc.Save _
(&H0, _
"")
End If
'PDFドキュメントを閉じる
lRet = objAcroApp.CloseAllDocs
'PDFドキュメントを閉じる
lRet2 = objAcroApp.CloseAllDocs
'PDFファイルを閉じる
lRet = objAcroPDDoc.Close
lRet2 = objAcroPDDoc.Close
'アプリケーションの終了
lRet = objAcroApp.Hide
lRet = objAcroApp.Exit
lRet2 = objAcroApp.Hide
lRet2 = objAcroApp.Exit
としておりますが、xp環境での処理が遅くなる原因があるのでしょうか。
因みにこの場合は各PDFごとにnewしていますが、1回のnewを使いまわす方法でも試してみましたが、同じようにxp環境で処理が遅くなってしまいました。
何かよい方法がありましたら、よろしくお願い致します。
お世話になります。
すみません、先程のコードですが、最後に下記があります。
'オブジェクトを強制開放する
Set objAcroPDDoc = Nothing
Set objAcroApp = Nothing
よろしくお願い致します。
てつこさん。初めまして。
サンプルロジックと質問内容に疑問があるので、
事前に再確認をさせて下さい。
1)一つのフォルダにPDFファイルが600以上存在する
2)各PDFファイルを1頁単位で別名でファイル保存する
3)Win7 64Bit版 は速く処理するが、WinXP 32Bit版では10倍以上も遅くなる
※メモリやCPUスペックは各OS共に十分有ると仮定する
それと
4)かなり焦っている?
理由:コメントのサンプルロジックが少し荒い(汗
なお、現在検証&検討中です。
管理人さん
コメントありがとうございます。
1)~3) そうです。
4)すみません、、焦っていました...
下記にコードを直しました。
Dim objAcroApp As New Acrobat.AcroApp
Dim objAcroPDDoc As New Acrobat.AcroPDDoc
'Acrobatを起動表示する
lRet = objAcroApp.Show
PDFファイルを開いて表示する
lRet = objAcroPDDoc.Open(Path & pdf_Name)
'頁の指定により分岐
If (pdfNumPage = 0) Then
'最初のページ以外削除する
lRet = objAcroPDDoc.DeletePages(1, pdfTotalPage - 1)
ElseIf (pdfNumPage + 1 = pdfTotalPage) Then
'最後のページ以外削除する
lRet = objAcroPDDoc.DeletePages(0, pdfNumPage - 1)
Else
b_pageFlg = True
'最初から指定-1頁ページ削除する
lRet = objAcroPDDoc.DeletePages(0, pdfNumPage - 1)
'別名でPDFファイルを保存する(変更した所だけ)
lRet = objAcroPDDoc.Save(&H0, "")
'Acrobatを起動表示する
lRet2 = objAcroApp.Show
'PDFファイルを開いて表示する
lRet2 = objAcroPDDoc.Open(pdf_Path & pdf_Name)
'3頁以上の場合
If (pdfTotalPage >= 3) Then
'pdfページ数取得
i_tmpPdfNumPage = getNumPage(pdf_Path & pdf_Name)
'最初のページ以外削除する
lRet2 = objAcroPDDoc.DeletePages(1, i_tmpPdfNumPage - 1)
End If
End If
If (b_pageFlg) Then
'別名でPDFファイルを保存する(変更した所だけ)
lRet2 = objAcroPDDoc.Save(&H0, "")
Else
'別名でPDFファイルを保存する(変更した所だけ)
lRet = objAcroPDDoc.Save(&H0, "")
End If
'PDFドキュメントを閉じる
lRet = objAcroApp.CloseAllDocs
'PDFドキュメントを閉じる
lRet2 = objAcroApp.CloseAllDocs
'PDFファイルを閉じる
lRet = objAcroPDDoc.Close
lRet2 = objAcroPDDoc.Close
'アプリケーションの終了
lRet = objAcroApp.Hide
lRet = objAcroApp.Exit
lRet2 = objAcroApp.Hide
lRet2 = objAcroApp.Exit
'オブジェクトを強制開放する
Set objAcroPDDoc = Nothing
Set objAcroApp = Nothing
お手数をお掛けして申し訳ありません。
よろしくお願い致します。
管理人さん
お世話になります。
PDFの分割で処理が遅い件に関しての追記ですが、
最初の数百ファイルでの分割はスムーズに処理されます。
しかし、ある時点を過ぎると分割の処理速度がスローダウンします。
それに、「ある時点」というのが、その時によって違います。
よろしくお願い致します。
Deleteメソッドは時間が掛かるので以下を提案します。
本当は開始時間+現在処理中の件数+ページ番号等をフォーム上(又はExcelのシート)のキャプションに表示しておくと安心して処理を観察できますが、返答の時間の関係上、省きました。
ご検討下さい。
以下はテスト用サンプルです。
※ \ は¥に置き換えて下さい。
Option Explicit
'Private objAcroApp As Acrobat.AcroApp
Private objAcroPDDoc As Acrobat.AcroPDDoc
Private strPutPath As String '出力先フォルダ
Sub test11()
On Error GoTo ERR_test11:
If vbOK <> MsgBox("処理を開始しても良いですか?", _
vbOKCancel + vbQuestion, "確認") Then Exit Sub
Dim strPDFFile(5000) As String
Dim lRet As Long
Dim i As Long
Dim strStart As String
strStart = Now()
'出力先フォルダ
strPutPath = "E:\Adobe PDF\PDF_Test\"
'入力PDFファイル
For i = LBound(strPDFFile) To UBound(strPDFFile) - 1
strPDFFile(i) = vbNullString
Next i
strPDFFile(0) = "E:\Adobe PDF\PDF_Test\test01.pdf" '2頁
strPDFFile(1) = "E:\Adobe PDF\PDF_Test\test02.pdf" '1頁
strPDFFile(2) = "E:\Adobe PDF\PDF_Test\test_NEW.pdf" '3頁
' Set objAcroApp = CreateObject("AcroExch.App")
Set objAcroPDDoc = CreateObject("AcroExch.PDDoc")
' 'Acrobatを起動表示する ★画面表示不要
' lRet = objAcroApp.Show
For i = LBound(strPDFFile) To UBound(strPDFFile) - 1
If strPDFFile(i) = vbNullString Then Exit For
lRet = subPut1Page(strPDFFile(i))
Next i
' 'アプリケーションの終了 ★画面表示している時のみ必要
' lRet = objAcroApp.Hide
' lRet = objAcroApp.Exit
'オブジェクトを強制開放する
Set objAcroPDDoc = Nothing
' Set objAcroApp = Nothing
MsgBox "処理は完了しました" & vbCrLf & vbCrLf & _
strStart & " - " & Now(), vbOKOnly, "完了"
Exit Sub
ERR_test11:
MsgBox "ERROR NO:" & Err.Number & vbCrLf & _
Err.Description, "実行のプログラムエラー"
End Sub
Private Function subPut1Page(ByVal strFile As String) As Boolean
Dim AcroPDDocNew As New Acrobat.AcroPDDoc
Dim lRet As Long
Dim pdfTotalPage As Long
Dim pdfNumPage As Long
Dim strPutFile As String
'初期化
subPut1Page = False
'PDFファイルを開く
lRet = objAcroPDDoc.Open(strFile)
'PDF頁数を取得(1~
pdfTotalPage = objAcroPDDoc.GetNumPages
For pdfNumPage = 0 To pdfTotalPage - 1
'空のPDFファイルを作成する
lRet = AcroPDDocNew.Create()
'最初の1頁目のみ挿入(追加)する
'注意:第5引数のFalseは固定。Trueだと全頁追加される
lRet = AcroPDDocNew.InsertPages(-1, _
objAcroPDDoc, 0, 1, False)
' Debug.Print AcroPDDocNew.GetNumPages
'別名でPDFファイルを保存する
strPutFile = Left(strFile, Len(strFile) - 4) & _
"-" & Format(pdfNumPage + 1, "0000") & ".pdf"
'注意:第1引数&H0だと保存出来ない
' lRet = AcroPDDocNew.Save(&H0, strPutFile)
lRet = AcroPDDocNew.Save(1, strPutFile)
lRet = AcroPDDocNew.Close
Set AcroPDDocNew = Nothing
If objAcroPDDoc.GetNumPages = 1 Then Exit For
'出力した1頁を削除する
'注意:InsertPagesメソッドの不具合対策
lRet = objAcroPDDoc.DeletePages(0, 0)
Next pdfNumPage
' 'PDFドキュメントを閉じる
' lRet = objAcroApp.CloseAllDocs
'PDFファイルを閉じる
lRet = objAcroPDDoc.Close
subPut1Page = True
End Function
どうですかね?
使えそうですか。
管理人さん
コメントありがとうございます。
XP環境で試してみました所、処理速度の改善が
見られました。
ありがとうございました!!
良かったです。
早く帰宅し、連休を楽しんで下さい。v(^_^)
<技術メモ>
処理速度が遅くなった原因。以下は全て推測。
・Win7 64BitはXPに比べて処理速度が5倍は期待できる。つまりXPでは5倍以上も時間が掛かる。
・Deleteメソッドを多用するとシステム(OS)に負荷が掛かり、その為にOSのCPU負荷が増大した可能性が考えられる。。
・初期のDeleteメソッドを使ったロジックは次第にメモリを多用し、スワップファイルを使うようになった可能性が考えられる。 <-この可能性が一番高い。
以上。
管理人さん お世話になります。
先日、教えて頂いた方法で、早くなるはなったのですが、
分割後のPDFがバージョン1.6になってしまうのが、
問題となっています。
分割前のPDFは1.3なのですが、1.3で分割する方法は
ないのでしょうか。
それと、希望としては
バージョンが1.3でプリフライトの
PDF/X-1a:2001 に準拠している事が希望です。
管理人さん
お世話になります。
先日教えていただいたコードで、処理速度は改善したのですが、
分割前のPDFのバージョンは1.3だったのですが、
分割すると1.6になってしまいます。
これを1.3にすることはできないのでしょうか?
また、プリフライトがPDF/X-1a:2001に準拠するように
することはできるのでしょうか?
てつこさん。
Windows7とWindowsXPにインストールしてあるAcrobatのバージョンを教えて下さい。
管理人さんお世話になります。
windows7 Acrobat professional 8.1.0
windowsXP Acrobat professional 7.1.0
です。
因みに、windows7の時も、windowsXPの時も、
バージョンが1.6になり、プリフライトがPDF/X-1a:2001に準拠しなく
なってしまい、困っています。
どうぞ、よろしくお願い致します。
てつこさん。
調査前ですが、既に判っている事だけ伝えておきます。
・PDF仕様を1.6にするのは多分ロジックを変更する事で可能かと思われます。
0ページPDFを既存のPDFで事前に作成し、それに1頁ずつ追加して
保存する時に不要な頁を削除する。
少し処理時間は増えますが、これなら確実だと思われます。
※テストしてみないと最終結論は出せない。
・保存PDFのプリフライトをPDF/X-1a:2001にするのはOLEだけでは出来ません。
但し、逃げ手はあるかも知れません。
Acrobatはこの手の情報や以前設定した情報をレジストリにAcrobat終了時に
書き込んでいます。
そこでデフォルトのAcrobatからPDF/X-1a:2001で保存する時のレジストリの変化を
比較します。
レジストリは
[HKEY_CURRENT_USER¥Software¥Adobe¥Adobe Acrobat¥8.0」
[HKEY_CURRENT_USER¥Software¥Adobe¥Adobe Acrobat¥7.0」
下で管理しているはずです。
これをVBAからWindowsAPIを操作して変更すれば出来るのではないかと
予想しています。
※これもテストしてみないと判らない。
・それとWin7でのテスト環境は直ぐには出来ないのでてつこさんにお願いしたいです。
以上、連絡だけ先にしておきます。
管理人さん
ご教授ありがとうございます。
私はwindows7の環境で試してみたいと思います。
どうぞ、よろしくお願い致します。
スイマセン。
やっぱ、出来ませ~ん。(汗
と土曜までは頑張ったのですが、つまづきました。
一晩寝て、視点を変えてやり方をじっくり検討した結果、
何とか出来る所までこぎつけました。v(^_^)
少し運用でカバーしなければならないところは有るかもしれませんが、
・Acrobat関連のレジストリの強制変更
・デフォルト・プリンタの強制変更
・OLEの印刷メソッドでPDF/X-1a:2001に変更したPDFを再作成
と、ここまで出来たのですが、
1頁単位にPDFを分割し、しかも処理時間を考慮するまでは出来ず・・。
今日はここまでで、申し訳ない。時間切れです。
明日は子供が風邪で熱を出しているので医者に連れて行かないといけない。
途中まででも何らかの形でサイトにアップする予定です。
コメントでは説明出来ない箇所が多々ある事と、PDF/X-1a:2001変換に関しては以前にも質問を受けていたので、それも含めてサンプルをサイトアップします。
お急ぎだと思いますがお待ち下さい。(疲
管理人さん
お手数をお掛けしまして、申し訳ありません。
遅くまで、どうもありがとうございます。
どうぞ、宜しくお願い致します
「VBAでPDFファイルをPDF/X-1a:2001形式に変換出力」
http://pdf-file.nnn2.com/?p=733
を見てください。
それと以下も見て下さい。
・Acrobat使用時のレジストリ変化を取得する方法
http://pdf-file.nnn2.com/?p=729
・regeditのインポート、エクスポートのコマンドライン
http://w3w.nnn2.com/?p=654
・レジストリエディタをコマンドライン操作でレジストリの特定のキーや値を削除する方法
http://w3w.nnn2.com/?p=656
復元ポイントを取ってからテストをして下さい。
ダウンロードファイルに含まれる以下のファイルはOS毎に作り直す必要があります。
・PDF-X変更-解除.reg.txt
・PDF-X変更-設定.reg.txt
理由はパソコン単位にSID(ユーザー識別番号)が異なるからです。
上記のファイルではそのSIDを使っています。
今後は
「VBAでPDFファイルをPDF/X-1a:2001形式に変換出力」
http://pdf-file.nnn2.com/?p=733
頁に全て反映させる予定です。
処理時間はメッチャ掛かります。
よって印刷部分のロジックに関しては見直す必要があります。
取り急ぎ、作業途中ですがアップしました。
管理人さん
お忙しい所、ありがとうございます。
試してみたいと思います。
試す前に、ロジックと各説明の意味を理解しないと
使えなく、トラブルに遭遇しますから気をつけて下さい。
くどいようですが、復元ポイントを忘れずに取ってください。
※既に(2版)高速?バージョンの思案中・・
※思案仕様:
1)最初に全頁でPDF/Xファイルを作る。
2)それを別名コピーして、OLEで開き不要な頁を削除&最適化保存。
3)上記「2)」を頁単位に繰り返す。
コーディング方法によればこっちの方が速いかもしれない。
明日以降の心だ。
てつこさんへ。
連絡のみ。
1)処理速度を4分の1程度にするロジックを考えました。
再度見直したら明日にでも
「VBAでPDFファイルをPDF/X-1a:2001形式に変換出力」
http://pdf-file.nnn2.com/?p=733
に更新版(2版)をアップします。
2)突然ですが、PDF/X-1a:2001にしたにも関わらずデフォルトの
PDFバージョン1.3にならずに元のPDFと同じバージョンになる現象が
出ています。新しいロジックが問題あるのか調査中です。
なお現在サイトにアップしている初版は問題無くPDFバージョン1.3に
なります。
管理人さん
ありがとうございます。
処理速度が速くなると、大変助かります。
よろしくお願い致します。
遅くなりました。 ※まだ見てるかな?
PDF仕様1.3の件は解決しました。
(WinXP + Acrobat v7.1.4環境で確認)
「VBAでPDFファイルをPDF/X-1a:2001形式に変換出力(2版)」
http://pdf-file.nnn2.com/?p=733
更新しましたので確認下さい。
なお、1頁のPDFファイルのサイズが大きくなります。
最適化はされていません。
最適化をするとPDF仕様がインストールされているAcrobatの
バージョンに適応されてしまいます。
その代わり処理速度は初版より10倍近く高速になっています。
後はレジストリの変更をWindowsAPIでするのが理想ですが、
これは力仕事なので、お任せします。(風邪引いた!
管理人さん
お忙しい所対応いただき、ありがとうございます。
試してみます。
風邪お大事にしてください。
少しは世間の役に立てたかな。
※今日は風邪でダウン。閉店です。