VBA から PDF の文字情報を取得する方法として、WORD の変換機能を使用する方法があります。
使い方は簡単ですが、処理の途中に確認メッセージ(Warning)が表示される場合もあるので、そのあたりの回避方法を含めてまとめておきます。
1. 基本的なサンプルコード
まずは、シンプルなサンプルコードです。EXCEL VBA と WORD VBA の例を挙げておきます。
確認メッセージ(Warning)への対応は行っていません。
1-1. WORD VBA の場合
① PDF を開くサンプル
WORD から PDF ファイルを開くだけで、自動でテキスト変換をしてくれます。
Sub OpenPdfSample()
Documents.Open "C:\VBA\Sample.pdf" '引数にPDFのフルパスを指定する
End Sub
コードは1行のみで、Documents オブジェクトの Open メソッドの引数に、ファイルのフルパスを指定しているだけです。
スキャンしたイメージ PDF でも OCR でテキスト変換をしてくれます。
② PDF からテキストを取得するサンプル
テキストまで取得するには、次のように書きます。
Sub GetPdfText()
Dim doc As Document 'WORDファイルを格納するオブジェクト変数
Set doc = Documents.Open("C:\VBA\Sample.pdf") 'PDFファイルを開く
Debug.Print doc.Content.Text 'WORDファイルのテキストを取得(出力)
doc.Close False 'ドキュメントを閉じる
End Sub
1-2. EXCEL VBA の場合
① PDF を開くサンプル
EXCEL VBA からだと、Word.Application を呼び出して実行するため、少々コード量が増えます。
Sub OpenPdfFromExcel()
Dim wordApp As Object
Set wordApp = CreateObject("Word.Application") 'Wordアプリケーションを取得
wordApp.Visible = True 'Wordアプリケーションを表示する
wordApp.Documents.Open "C:\VBA\Sample.pdf" 'PDFファイルを開く
Set wordApp = Nothing 'オブジェクトの解放
End Sub
参照設定に Microsoft Word 16.0 Object Library
を追加すると、次のように書けます。
Sub OpenPdfFromExcel()
Dim wordApp As New Word.Application 'Wordアプリケーションを取得
wordApp.Visible = True 'Wordアプリケーションを表示する
wordApp.Documents.Open "C:\VBA\Sample.pdf" 'PDFファイルを開く
Set wordApp = Nothing 'オブジェクトの解放
End Sub
② PDF からテキストを取得するサンプル
テキストまで取得するには、次のように書きます。
Sub GetPdfTextFromExcel()
Dim wordApp As Object: Set wordApp = CreateObject("Word.Application")
wordApp.Visible = True 'Wordアプリケーションを表示する
Dim doc As Object
Set doc = wordApp.Documents.Open("C:\VBA\Sample.pdf") 'PDFファイルを開く
Debug.Print doc.Content.Text 'WORDファイルのテキストを取得(出力)
doc.Close False 'ドキュメントを閉じる(False=保存せずに閉じる)
wordApp.Quit 'Wordアプリケーションを終了する
Set wordApp = Nothing 'オブジェクトの解放
End Sub
wordApp.Visible = True
がないと確認メッセージが表示されずに操作不能となる場合が生じるため、念のため入れておきます(適切な設定をすれば不要となります)。
<参考サイト>
・Excel VBA Wordを操作する主なプロパティとメソッド
1-3. URL を指定する場合
ファイルパスの代わりに、WEB 上の PDF ファイルの URL を指定することもできます。
Sub OpenPdfFromWeb()
Documents.Open "https://www.stat.go.jp/data/jinsui/pdf/202108.pdf"
End Sub
1-4. 表示される Warning(確認メッセージ)
WORD から初めて PDF を開く際に、次のような「PDF から編集可能な Word 文書に変換します。この処理には…」という確認メッセージが出てきます。
自分の PC のみで動作させるのであれば「今後このメッセージは表示しない」をチェックするだけで、以後、メッセージを非表示にすることができます。
しかし、他者に VBA を配布する場合は、このメッセージをあらかじめ表示しないようにしたいところです。
なお、よく使用される次の方法では、確認メッセージを非表示にすることはできません。
<非表示にできない例>
Sub OpenPdfSample()
Application.DisplayAlerts = False
Documents.Open "C:\VBA\Sample.pdf" '確認メッセージは表示される
Application.DisplayAlerts = True
End Sub
非表示にする方法は、以下のようになります。
2. 確認メッセージを非表示にする
確認メッセージを非表示にするかどうかの情報は、Windows のレジストリに記録されています。
このレジストリを VBA から操作することで、確認メッセージの制御をすることが可能となります。
なお、レジストリの書き換えはアプリケーションの動作不良などを起こすなどの危険を伴いますので、自己責任で、影響が把握できている内容のみ操作するようにしてください。
レジストリはWindowsやアプリケーションの設定情報が格納されたファイルであり、設定情報がOSやアプリケーションによって書き込まれ、必要に応じて参照される。ユーザーがレジストリを直接編集することは通常はないうえ、いたずらにいじるとシステムが破壊されてしまう危険性も伴うのでできれば避けた方がよい。(Windows管理者のためのWindows Script Host入門)
2-1. サンプルコード
サンプルコードを書くと次のようになります。
確認メッセージを非表示にするだけで、結構面倒な処理が必要になってしまいます。
<参考サイト>
・Open PDF in Word without Conversion Message
2-1-1. WORD VBA の場合
'警告メッセージなしでPDFからテキストを取得する
Sub GetPdfTextWithoutWarning()
Dim regValue As Long
regValue = GetRegValue("DisableConvertPdfWarning") 'PDF変換に関するレジストリ値を取得
If regValue <= 0 Then Call SetRegValue("DisableConvertPdfWarning", 1) '警告が出る設定であればレジストリ値を[1]に変更
Dim doc As Document 'WORDファイルを格納するオブジェクト変数
Set doc = Documents.Open(FileName:="C:\VBA\Sample.pdf", ConfirmConversions:=False) 'PDFファイルを開く
Debug.Print doc.Content.Text 'WORDファイルのテキストを取得(出力)
doc.Close False 'ドキュメントを閉じる
If regValue <= 0 Then Call SetRegValue("DisableConvertPdfWarning", 0) 'レジストリ値を[0]に戻す
End Sub
'レジストリの値を取得(数値型)
Function GetRegValue(name As String) As Long
Dim wshShell As Object
Dim wordVer As String
Dim regKey As String
Set wshShell = CreateObject("WScript.Shell") 'WshShellオブジェクトを作成
wordVer = Application.Version 'WORDアプリケーションのバージョンを取得([15.0]や[16.0]など)
regKey = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\" & wordVer & "\Word\Options\" 'レジストリキーの格納場所
On Error Resume Next
GetRegValue = wshShell.RegRead(regKey & name) 'RegReadメソッドでレジストリの値を取得
If Err.Number <> 0 Then GetRegValue = -1 'エラーが生じた場合(不存在の場合)は[-1]を返す
On Error GoTo 0
Set wshShell = Nothing 'WshShellオブジェクトの解放
End Function
'レジストリの値を設定(数値型)
Sub SetRegValue(name As String, newValue As Long)
Dim wshShell As Object
Dim wordVer As String
Dim regKey As String
Set wshShell = CreateObject("WScript.Shell")
wordVer = Application.Version
regKey = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\" & wordVer & "\Word\Options\"
wshShell.RegWrite regKey & name, newValue, "REG_DWORD" 'RegWriteメソッドでレジストリを設定
Set wshShell = Nothing
End Sub
2-1-2. EXCEL VBA の場合
'警告メッセージなしでPDFからテキストを取得する
Sub GetPdfTextWithoutWarning()
Dim wordApp As Object: Set wordApp = CreateObject("Word.Application")
wordApp.Visible = True 'Wordアプリケーションを表示する(念のため)
Dim wordVer As String: wordVer = wordApp.Application.Version 'WORDアプリケーションのバージョンを取得([15.0]や[16.0]など)
Dim regValue As Long
regValue = GetRegValue("DisableConvertPdfWarning", wordVer) 'PDF変換に関するレジストリ値を取得
If regValue <= 0 Then Call SetRegValue("DisableConvertPdfWarning", 1, wordVer) '警告が出る設定であればレジストリ値を[1]に変更
Dim doc As Object
Set doc = wordApp.Documents.Open(Filename:="C:\VBA\Sample.pdf", ConfirmConversions:=False) 'PDFファイルを開く
Debug.Print doc.Content.Text 'WORDファイルのテキストを取得(出力)
doc.Close False 'ドキュメントを閉じる(False=保存せずに閉じる)
If regValue <= 0 Then Call SetRegValue("DisableConvertPdfWarning", 0, wordVer) 'レジストリ値を[0]に戻す
wordApp.Quit 'Wordアプリケーションを終了する
Set wordApp = Nothing 'オブジェクトの解放
End Sub
'レジストリの値を取得(数値型)
Function GetRegValue(name As String, wordVer As String) As Long
Dim wshShell As Object
Dim regKey As String
Set wshShell = CreateObject("WScript.Shell") 'WshShellオブジェクトを作成
regKey = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\" & wordVer & "\Word\Options\" 'レジストリキーの格納場所
On Error Resume Next
GetRegValue = wshShell.RegRead(regKey & name) 'RegReadメソッドでレジストリの値を取得
If Err.Number <> 0 Then GetRegValue = -1 'エラーが生じた場合(不存在の場合)は[-1]を返す
On Error GoTo 0
Set wshShell = Nothing 'WshShellオブジェクトの解放
End Function
'レジストリの値を設定(数値型)
Sub SetRegValue(name As String, newValue As Long, wordVer As String)
Dim wshShell As Object
Dim regKey As String
Set wshShell = CreateObject("WScript.Shell")
regKey = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\" & wordVer & "\Word\Options\"
wshShell.RegWrite regKey & name, newValue, "REG_DWORD" 'RegWriteメソッドでレジストリを設定
Set wshShell = Nothing
End Sub
2-2. 簡単な説明
サンプルコードについての簡単な説明を書いておきます。
2-2-1. レジストリについて
コードだけを見てもイメージが湧かないと思うので、レジストリの内容を見ておきます。
こちらのサイトを参考にして、レジストリエディターを開きます。
Word 設定のオプションキーは次の場所に格納されています(参考)。
<Word for Microsoft 365、Word 2019、および Word 2016>
HKEY_CURRENT_USER\Software\Microsoft\Office\16.0\Word\Options
<Word 2013>
HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Word\Options
該当の場所を開くと、次のように WORD 設定に関する名前(キー)、種類、データ(値)などが表示されます。
これらの「名前、種類、データ」が1つの設定情報となっており、エントリ(レジストリ・エントリ)と呼ばれています。
<DisableConvertPdfWarning の設定値>
WORD で PDF を開く際に、確認メッセージを表示するか否かの設定は、DisableConvertPdfWarning
という名前(キー)で設定されています(最初は存在していません)。
データ(値) | 設定内容 |
---|---|
(エントリ不存在) | 確認メッセージを表示する(デフォルト) |
0x00000000 (0) | 確認メッセージを表示する |
0x00000001 (1) | 確認メッセージを表示しない(無効にする) |
2-2-2. WshShell オブジェクトを使用したレジストリ操作
レジストリの値を取得したり操作するには、WshShell オブジェクトを使用します。
今回使用するメソッドは、次のとおりです。
メソッド | 内容 | 構文 |
---|---|---|
RegRead | レジストリの値を取得 | RegRead(エントリのパス) |
RegWrite | レジストリの値を設定 | RegWrite(エントリのパス, 設定値, エントリの種類) |
RegDelete | レジストリの値を削除 | RegDelete(エントリのパス) |
メソッドを使用するには、エントリのパス、エントリの種類の情報が必要になります。
私の環境の場合、DisableConvertPdfWarning
の内容をレジストリエディタから確認すると次のようになっています。
項目 | 内容 |
---|---|
エントリのパス | HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office \16.0\Word\Options\DisableConvertPdfWarning |
エントリの種類 | REG_DWORD |
エントリパスの「16.0」のところは、WORD アプリケーションのバージョンにより異なります。
以下、RegRead メソッド、RegWrite メソッド、RegDelete メソッドを使用するシンプルなサンプルを書いておきます(EXCEL VBA、WORD VBA どちらでも動作します)。
2-2-2-1. DisableConvertPdfWarning のレジストリ値を取得する
レジストリ値を取得するために RegRead メソッドを使用します。
Function GetRegValueOfDisableConvertPdfWarning() As Long
Dim wshShell As Object
Set wshShell = CreateObject("WScript.Shell") 'WshShellオブジェクトを作成
Debug.Print wshShell.RegRead("HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Word\Options\DisableConvertPdfWarning") 'RegReadメソッドでレジストリの値を取得
Set wshShell = Nothing 'WshShellオブジェクトの解放
End Function
なお、指定したエントリが存在しない場合はエラーとなりますので、エラー処理が必要です。
2-2-2-2. DisableConvertPdfWarning のレジストリ値を設定する
レジストリ値を取得するために RegWrite メソッドを使用します。
以下の例は値を「1」にして、確認メッセージを表示しないようにしています。
Sub SetRegValueOfDisableConvertPdfWarning()
Dim wshShell As Object
Set wshShell = CreateObject("WScript.Shell")
wshShell.RegWrite "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Word\Options\DisableConvertPdfWarning", 1, "REG_DWORD" 'RegWriteメソッドでレジストリを設定
Set wshShell = Nothing
End Sub
指定したエントリが存在しない場合は、新しいエントリが作成されます。
2-2-2-3. DisableConvertPdfWarning のエントリを削除する
エントリを削除するために RegDelete メソッドを使用します。
本記事のサンプルコードではエントリ自体を削除するのは控えため、この RegDelete メソッドは使用していません。
Sub DeleteRegOfDisableConvertPdfWarning()
Dim wshShell As Object
Set wshShell = CreateObject("WScript.Shell")
wshShell.RegDelete "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Word\Options\DisableConvertPdfWarning" 'RegDeleteメソッドでレジストリを削除
Set wshShell = Nothing
End Sub
なお、削除対象のエントリが存在しない場合はエラーとなりますので、エラー処理が必要です。
<参考サイト>
・基礎解説 演習方式で身につけるチェック式WSH超入門
・Windows管理者のためのWindows Script Host入門
2-2-3. ファイルの変換ダイアログを非表示にする
WORD から PDF ファイルなどの WORD 形式以外のファイルを開く場合に、「ファイルの変換」ダイアログが表示される場合があります。
デフォルトではこのダイアログは表示されず、ファイルの拡張子から自動的に判定するようになっています。
マクロ使用者の設定環境によって、このダイアログが表示される場合も想定されますので、これも表示しないようにしておく必要があります。
この設定は簡単で、Documents.Open メソッドでファイルを開く際に、ConfirmConversions プロパティの設定を追加するだけで済みます。
Sub OpenPdfSample()
Documents.Open FileName:="C:\VBA\Sample.pdf", ConfirmConversions:=False
End Sub
<ConfirmConversions プロパティの設定値>
設定値 | 内容 |
---|---|
True | ダイアログボックスを表示する |
False | ダイアログボックスを表示しない(デフォルト) |
<参考サイト>
・Documents.Open メソッド (Word)