Acrobat OLEのエラーを防ぐVBAロジック

TOP > *      [...]


Good Smile Racing -Wonder Festival 2015 [Summer] (Makuhari, Chiba, Japan)

概要

AcrobatのOLE操作時に以下のエラーを出してしまう事が有ります。

  1. PDFファイルを開いたままで終了してしまった。
    • 原因:ロジックのミス
  2. 処理は全て終わったのにメモリ上からAcrobatプロセスが消えない。
    • 原因1:ロジックのミスで、処理途中のAcrobat OLEオブジェトが残ってしまった
    • 原因2:VBAのCallByName関数でAcrobatのOLEを使用した
    • 原因3:PCのスペックによる。メモリからプロセスが消えるのに数秒は掛かる場合がある。
  3. エラーメッセージ「・・オブジェクトを作成できません。」が出る
    • 原因:不明。メモリ上にプロセスが存在しないからと予測している。

この対処方法です。これ以外にエラーを減らす部分も紹介します。

基本ロジック(1)

Acrobat OLEのエラーに対処したVBAロジックの基本です。【x】の部分を見て下さい。後で理由を説明します。

001 Option Explicit
002
003 ' 【0】この位置での宣言は非推奨
004 'Private gobjAcroApp As New Acrobat.AcroApp
005 'Private gobjAcroAVDoc As New Acrobat.AcroAVDoc
006 'Private gobjAFormApp As New AFORMAUTLib.AFormApp
007 'Private gobjAFormFields As AFORMAUTLib.Fields
008
009 '***************************************************
010 ' Main
011 '***************************************************
012 Sub Main()
013 '【1】Acrobatプロセスの強制終了:事前
014 Call TerminateAcrobat
015
016 Dim i As Long
017 Dim sPDF(2) As String
018
019 sPDF(0) = "D:\A.PDF"
020 sPDF(1) = "D:\B.PDF"
021 sPDF(2) = "D:\C.PDF"
022
023 For i = 0 To UBound(sPDF)
024 Call Loop_Syori(sPDF(i))
025 Next i
026
027 '【2】Acrobatプロセスの強制終了:最後※非推奨
028 ' Call TerminateAcrobat
029 End Sub
030 '***************************************************
031 ' PDFの処理 ループで呼ばれる
032 '***************************************************
033 Sub Loop_Syori(sPDF As String)
034 Dim bRet As Boolean
035
036 '【3】 Acrobat OLE 変数の宣言
037 Dim objAcroApp As New Acrobat.AcroApp
038 Dim objAcroAVDoc As New Acrobat.AcroAVDoc
039 Dim objAFormApp As New AFORMAUTLib.AFormApp
040 Dim objAFormFields As AFORMAUTLib.Fields
041
042 '【4】 Acrobatプロセスをメモリに乗せる
043 objAcroApp.CloseAllDocs '開いたPDFを全て閉じる
044 objAcroApp.Hide '稀に表示されるので隠す
045
046 'PDFの各種処理
047 bRet = objAcroAVDoc.Open(sPDF, "")
048 '
049 '
050 '
051 '続行不可能なエラーが発生「Goto Err_Skip:」
052 '
053 '
054 '
055 '閉じる
056 bRet = objAcroAVDoc.Close(False)
057
058 '【5】 エラー時のスキップ先
059 Err_Skip:
060 On Error Resume Next 'これ以降は強制実行
061
062 '【6】 Acrobatアプリケーションの終了
063 objAcroApp.Hide
064 objAcroApp.Exit
065
066 '【7】 オブジェクトの開放
067 Set objAFormApp = Nothing
068 Set objAFormFields = Nothing
069 Set objAcroAVDoc = Nothing
070 Set objAcroApp = Nothing
071 End Sub
072 '***************************************************
073 ' メモリ上に残っているAcrobatプロセスを強制終了する。
074 '***************************************************
075 Private Sub TerminateAcrobat()
076 Dim items As Object
077 Dim item As Object
078 Set items = CreateObject("WbemScripting.SWbemLocator") _
079 .ConnectServer.ExecQuery( _
080 "Select * From Win32_Process " & _
081 "Where Name = 'Acrobat.exe'")
082 If items.Count > 0 Then
083 For Each item In items
084 item.Terminate
085 Next
086 End If
087 End Sub

「On Error ・・」と「bRet:終了コードの確認」も必要と思われるところには入れて下さい。

【0】 モジュールレベルでの変数宣言

Option Explicit

' 【0】この位置での宣言は非推奨。
'Private gobjAcroApp As New Acrobat.AcroApp
'Private gobjAcroAVDoc As New Acrobat.AcroAVDoc
'Private gobjAFormApp As New AFORMAUTLib.AFormApp
'Private gobjAFormFields As AFORMAUTLib.Fields

モジュールレベルでAcrobat OLEのオブジェクト変数の宣言は高速処理につながる様に見えます。しかし、実際は不可解なトラブルが多発します。詳細は省略。Sub 又は Function 内での宣言にして下さい。

引数での使用には問題ないです。

【1】Acrobatプロセスの強制終了:事前

Call TerminateAcrobat

AFormAutオブジェクト使用時は、開始処理で事前に1回だけ実行する必要が有ります。これはAcrobatプロセスがメモリ上に残っている場合に強制終了させる処理です。詳細は以下を御覧ください。

AFormAutオブジェクト未使用時は不要です。

【2】Acrobatプロセスの強制終了:最後

Call TerminateAcrobat

コールバック関数(CallByName)内でAcrobat OLEオブジェクトを使用するとAcrobatプロセスが終了しない現象が出ています。使用は非推奨です。理由は以下を御覧ください。

【3】Acrobat OLE 変数の宣言

Dim objAcroApp As New Acrobat.AcroApp
Dim objAcroAVDoc As New Acrobat.AcroAVDoc
Dim objAFormApp As New AFORMAUTLib.AFormApp
Dim objAFormFields As AFORMAUTLib.Fields

上記のように「・・As Acrobat.Xxxxxx」の宣言を使用していると、以下のようなピリオドの後に入力候補を表示する事ができます。可能な限りのエラーを減らせます。

ピリオドの後の入力候補

ネット上の古いサンプルを見ると以下のような宣言を見かけます。

Dim objAcroApp As Object
Dim objAcroAVDoc As Object
Set objAcroApp = CreateObject("AcroExch.App")
Set objAcroAVDoc = CreateObject("AcroExch.AVDoc")

「・・As Object」の使用は可能な限り減らしましょう。

【4】開いたままのPDFファイルを閉じる

objAcroApp.CloseAllDocs

何らかなプログラムの異常終了、又はプログラムミスやエラーによる中断で、PDFファイルが開いたままになった状態を解消します。全ての開いたPDFファイルを CloseAllDocs で閉じます。

それと稀に「オブジェクトを作成できません」と言う不可解な実行エラーが出る場合が有ります。CloseAllDocsを事前に実行するとかなり回避できる事が確認されています。多分、Acrobat OLEプロセスのメモリへのロードが遅い時に発生するのではないかと、勝手に予測しています。(勘

CloseAllDocsを無条件に実行しても、この位置では特に悪さはしないと思っているので入れて下さい。

objAcroApp.Hide

稀にですが、ロジックミス等でAcrobat本体が画面上に表示されることが有ります。それを Hide で隠します。この方が処理速度も上がります。おまけのロジックです。

【5】続行不可能なエラー後の処理

途中でランタイムエラー以外の続行不可能なエラーが発生しても、これ以降の処理【6】と【7】は強制実行「On Error Resume Next」します。こうすることで開発性の向上とAcrobatプロセスの未終了をかなり防げます。

CloseAllDocs も追加して無条件実行すれば更にイイです。

【6】Acrobatアプリケーションの終了

objAcroApp.Hide
objAcroApp.Exit

Acrobat OLEの処理が済んだら、Acrobat OLEを終了します。 HideExit は順番も固定です。以下も御覧ください。

【7】オブジェクトの開放

Set objAFormApp = Nothing
Set objAFormFields = Nothing
Set objAcroAVDoc = Nothing
Set objAcroApp = Nothing

Acrobat OLEを終了する時の約束事です。全てのAcrobat OLEオブジェクトをNothingする必要が有ります。以下も御覧ください。

Nothingをせずに、次の操作の処理で使いまわそうとすると思わぬトラブルに遭遇します。必ず最後はメモリから消す為の操作(命令)が必要です。ループ中の処理(Sub Loop_Syori)の連続処理で実際はメモリから消えなくてもです。

基本ロジック(2)

Acrobat OLEの操作に慣れたら、以下の形も可能です。1~2割は処理速度を上げれます。

001 Option Explicit
002
003 '***************************************************
004 ' Main & PDFの処理
005 '***************************************************
006 Sub Main()
007 Dim bRet As Boolean
008
009 '【1】Acrobatプロセスの強制終了:事前
010 Call TerminateAcrobat
011
012 '【3】 Acrobat OLE 変数の宣言
013 Dim objAcroApp As New Acrobat.AcroApp
014 Dim objAcroAVDoc As New Acrobat.AcroAVDoc
015 Dim objAFormApp As New AFORMAUTLib.AFormApp
016 Dim objAFormFields As AFORMAUTLib.Fields
017
018 '【4】 Acrobatプロセスをメモリに乗せる
019 objAcroApp.CloseAllDocs '開いたPDFを全て閉じる
020 objAcroApp.Hide '稀に表示されるので隠す
021
022 Dim i As Long
023 Dim sPDF(2) As String
024
025 sPDF(0) = "D:\A.PDF"
026 sPDF(1) = "D:\B.PDF"
027 sPDF(2) = "D:\C.PDF"
028
029 For i = 0 To UBound(sPDF)
030 'PDFの各種処理
031 bRet = objAcroAVDoc.Open(sPDF(i), "")
032 '
033 '
034 '
035 '続行不可能なエラーが発生「Goto Err_Skip:」
036 '
037 '
038 '
039 '閉じる
040 bRet = objAcroAVDoc.Close(False)
041 Next i
042
043 '【5】 エラー時のスキップ先
044 Err_Skip:
045 On Error Resume Next 'これ以降は強制実行
046
047 '【6】 Acrobatアプリケーションの終了
048 objAcroApp.Hide
049 objAcroApp.Exit
050
051 '【7】 オブジェクトの開放
052 Set objAFormApp = Nothing
053 Set objAFormFields = Nothing
054 Set objAcroAVDoc = Nothing
055 Set objAcroApp = Nothing
056
057 '【2】Acrobatプロセスの強制終了:最後※非推奨
058 ' Call TerminateAcrobat
059 End Sub
060 '***************************************************
061 ' メモリ上に残っているAcrobatプロセスを強制終了する。
062 '***************************************************
063 Private Sub TerminateAcrobat()
064 Dim items As Object
065 Dim item As Object
066 Set items = CreateObject("WbemScripting.SWbemLocator") _
067 .ConnectServer.ExecQuery( _
068 "Select * From Win32_Process " & _
069 "Where Name = 'Acrobat.exe'")
070 If items.Count > 0 Then
071 For Each item In items
072 item.Terminate
073 Next
074 End If
075 End Sub

ループ内でのエラー処理は忘れないで下さい。

経験上、 基本ロジック(1) をお勧めします。理由は

  1. テストとデバッグがしやすい
  2. 再利用がしやすい

Acrobat プロセスの監視

テスト中はタスクマネージャーを起動して、処理が終了したらタスクマネージャーから消えることを確認して下さい。

タスクマネージャーでAcrobatプロセスを監視

メモリに残っていると次の処理で予期せぬ結果になります。その場合は上記で「Adobe Acrobat」プロセスの「タスクの終了」を実行して下さい。

備考

  • 全て経験上の内容です。メーカー公式的な部分は無いです。
  • 宣言の New ではメモリ上にAcrobat プロセスはロードされません。Acrobat OLEのメソッドの実行時に初めてロードされます。

< TOPへ >

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


★ 文章での質問は難しいですよネ。でも、早く解決して、家に帰りたい。


SAMURAI Plugin

コメントをする時は出来れば以下もお願いします。

  • OS名 バージョン
  • Acrobat バージョン
  • ツール(Excel等) バージョン
コメントにサンプルコードを入れる時はコードを全て全角文字列にしてください。コチラで半角に戻します。それでもエラーが回避できない時はコメント下さい。個別に対処します。



お仕事で当サイトを見ている方へ
考え込んだら、ご質問下さい。
一緒に解決策を考えましょう。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください