【VBA】PDF を WORD に変換してテキストを取得する（確認メッセージを表示しない）

VBA から PDF の文字情報を取得する方法として、WORD の変換機能を使用する方法があります。
使い方は簡単ですが、処理の途中に確認メッセージ（Warning）が表示される場合もあるので、そのあたりの回避方法を含めてまとめておきます。

# 1. 基本的なサンプルコード

まずは、シンプルなサンプルコードです。EXCEL VBA と WORD VBA の例を挙げておきます。
確認メッセージ（Warning）への対応は行っていません。

## 1-1. WORD VBA の場合

**① PDF を開くサンプル**
WORD から PDF ファイルを開くだけで、自動でテキスト変換をしてくれます。

```vb:WORD&#x20;VBA（PDFファイルを開くのみ）
Sub OpenPdfSample()
    Documents.Open "C:\VBA\Sample.pdf" '引数にPDFのフルパスを指定する
End Sub
```
コードは１行のみで、[Documents](https://docs.microsoft.com/ja-jp/office/vba/api/word.documents) オブジェクトの [Open](https://docs.microsoft.com/ja-jp/office/vba/api/word.documents.open) メソッドの引数に、ファイルのフルパスを指定しているだけです。
スキャンしたイメージ PDF でも OCR でテキスト変換をしてくれます。

**② PDF からテキストを取得するサンプル**
テキストまで取得するには、次のように書きます。

```vb:WORD&#x20;VBA（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 を呼び出して実行するため、少々コード量が増えます。

```vb:EXCEL&#x20;VBA（参照設定をしない場合）
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` を追加すると、次のように書けます。

```vb:EXCEL&#x20;VBA（参照設定をした場合）
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 からテキストを取得するサンプル**
テキストまで取得するには、次のように書きます。

```vb:EXCEL&#x20;VBA（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を操作する主なプロパティとメソッド](https://kosapi.com/post-3986/)

## 1-3. URL を指定する場合
ファイルパスの代わりに、WEB 上の PDF ファイルの URL を指定することもできます。

```vb:WORD&#x20;VBA（URLを指定）
Sub OpenPdfFromWeb()
    Documents.Open "https://www.stat.go.jp/data/jinsui/pdf/202108.pdf"
End Sub
```

## 1-4. 表示される Warning（確認メッセージ）

WORD から初めて PDF を開く際に、次のような「<font color="#8b0000">PDF から編集可能な Word 文書に変換します。この処理には…</font>」という確認メッセージが出てきます。
![2021-08-20 010702.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551412/3def1250-5813-7c83-1e83-33740eb09c45.png)
自分の PC のみで動作させるのであれば「<font color="#8b0000">今後このメッセージは表示しない</font>」をチェックするだけで、以後、メッセージを非表示にすることができます。

しかし、他者に VBA を配布する場合は、このメッセージをあらかじめ表示しないようにしたいところです。

なお、よく使用される次の方法では、確認メッセージを非表示にすることはできません。

＜**非表示にできない例**＞

```vb:WORD&#x20;VBA（非表示にできない例）
Sub OpenPdfSample()
    Application.DisplayAlerts = False
    Documents.Open "C:\VBA\Sample.pdf" '確認メッセージは表示される
    Application.DisplayAlerts = True
End Sub
```

非表示にする方法は、以下のようになります。

# 2. 確認メッセージを非表示にする

確認メッセージを非表示にするかどうかの情報は、Windows の[レジストリ](https://ja.wikipedia.org/wiki/%E3%83%AC%E3%82%B8%E3%82%B9%E3%83%88%E3%83%AA)に記録されています。
このレジストリを VBA から操作することで、確認メッセージの制御をすることが可能となります。

なお、<font color="red">レジストリの書き換えはアプリケーションの動作不良などを起こすなどの危険を伴います</font>ので、自己責任で、影響が把握できている内容のみ操作するようにしてください。

>レジストリはWindowsやアプリケーションの設定情報が格納されたファイルであり、設定情報がOSやアプリケーションによって書き込まれ、必要に応じて参照される。ユーザーがレジストリを直接編集することは通常はないうえ、いたずらにいじるとシステムが破壊されてしまう危険性も伴うのでできれば避けた方がよい。（[Windows管理者のためのWindows Script Host入門](https://atmarkit.itmedia.co.jp/ait/articles/0407/08/news101.html)）

## 2-1. サンプルコード

サンプルコードを書くと次のようになります。
確認メッセージを非表示にするだけで、結構面倒な処理が必要になってしまいます。

＜参考サイト＞
・[Open PDF in Word without Conversion Message](https://social.msdn.microsoft.com/Forums/en-US/57f49b29-58cf-45e5-97cc-985fdd9a8c17/open-pdf-in-word-without-conversion-message?forum=isvvba)

### 2-1-1. WORD VBA の場合

```vb:WORD&#x20;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 の場合

```vb
'警告メッセージなしで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. レジストリについて

コードだけを見てもイメージが湧かないと思うので、レジストリの内容を見ておきます。
[こちらのサイト](https://support.microsoft.com/ja-jp/windows/windows-10-%E3%81%A7%E3%83%AC%E3%82%B8%E3%82%B9%E3%83%88%E3%83%AA-%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%83%BC%E3%82%92%E9%96%8B%E3%81%8F%E6%96%B9%E6%B3%95-deab38e6-91d6-e0aa-4b7c-8878d9e07b11)を参考にして、レジストリエディターを開きます。
![2021-08-21 171712.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551412/f12d4322-73d6-0740-cf63-6ff74e720fad.png)
Word 設定のオプションキーは次の場所に格納されています（[参考](https://support.microsoft.com/ja-jp/office/office-%e3%82%a2%e3%83%97%e3%83%aa%e3%82%b1%e3%83%bc%e3%82%b7%e3%83%a7%e3%83%b3%e3%82%92%e4%bf%ae%e5%be%a9%e3%81%99%e3%82%8b-7821d4b6-7c1d-4205-aa0e-a6b40c5bb88b?ui=ja-JP&rs=ja-JP&ad=JP)）。

```:オプションキー
＜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 設定に関する名前（キー）、種類、データ（値）などが表示されます。
これらの「名前、種類、データ」が１つの設定情報となっており、エントリ（レジストリ・エントリ）と呼ばれています。
![2021-08-21 172916.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551412/5d5be1d7-39ea-7eb5-de14-2784818f761c.png)
＜**DisableConvertPdfWarning の設定値**＞
WORD で PDF を開く際に、確認メッセージを表示するか否かの設定は、`DisableConvertPdfWarning` という名前（キー）で設定されています（最初は存在していません）。

|データ（値）|設定内容|
|---|---|
|（エントリ不存在）|確認メッセージを表示する（デフォルト）|
|0x00000000 (0)|確認メッセージを表示する|
|0x00000001 (1)|確認メッセージを表示しない（無効にする）|

### 2-2-2. WshShell オブジェクトを使用したレジストリ操作

レジストリの値を取得したり操作するには、[WshShell オブジェクト](https://atmarkit.itmedia.co.jp/ait/articles/0407/08/news101.html)を使用します。
今回使用するメソッドは、次のとおりです。

|メソッド|内容|構文|
|---|---|---|
|RegRead|レジストリの値を取得|RegRead(エントリのパス)|
|RegWrite|レジストリの値を設定|RegWrite(エントリのパス, 設定値, エントリの種類)|
|RegDelete|レジストリの値を削除|RegDelete(エントリのパス)|

メソッドを使用するには、エントリのパス、エントリの種類の情報が必要になります。
私の環境の場合、`DisableConvertPdfWarning` の内容をレジストリエディタから確認すると次のようになっています。

|項目|内容|
|---|---|
|エントリのパス|HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office<br>\16.0\Word\Options\DisableConvertPdfWarning|
|エントリの種類|REG_DWORD|

エントリパスの「16.0」のところは、WORD アプリケーションのバージョンにより異なります。
以下、RegRead メソッド、RegWrite メソッド、RegDelete メソッドを使用するシンプルなサンプルを書いておきます（EXCEL VBA、WORD VBA どちらでも動作します）。

#### 2-2-2-1. DisableConvertPdfWarning のレジストリ値を取得する

レジストリ値を取得するために RegRead メソッドを使用します。

```vb:DisableConvertPdfWarningの値を取得
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」にして、確認メッセージを表示しないようにしています。

```vb:DisableConvertPdfWarningの値を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 メソッドは使用していません。

```vb:DisableConvertPdfWarningのエントリを削除
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超入門](https://atmarkit.itmedia.co.jp/ait/articles/0711/28/news140.html)
・[Windows管理者のためのWindows Script Host入門](https://atmarkit.itmedia.co.jp/ait/articles/0407/08/news101.html)

### 2-2-3. ファイルの変換ダイアログを非表示にする

WORD から PDF ファイルなどの WORD 形式以外のファイルを開く場合に、「ファイルの変換」ダイアログが表示される場合があります。
![2021-08-21 203341.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551412/ea2e24be-133b-eda3-9880-358789918ccc.png)
デフォルトではこのダイアログは表示されず、ファイルの拡張子から自動的に判定するようになっています。

マクロ使用者の設定環境によって、このダイアログが表示される場合も想定されますので、これも表示しないようにしておく必要があります。

この設定は簡単で、[Documents.Open メソッド](https://docs.microsoft.com/ja-jp/office/vba/api/word.documents.open)でファイルを開く際に、[ConfirmConversions プロパティ](https://docs.microsoft.com/ja-jp/office/vba/api/word.options.confirmconversions)の設定を追加するだけで済みます。

```vb:ファイルの変換ダイアログを非表示にする
Sub OpenPdfSample()
    Documents.Open FileName:="C:\VBA\Sample.pdf", ConfirmConversions:=False
End Sub
```
＜**ConfirmConversions プロパティの設定値**＞

|設定値|内容|
|---|---|
|True|ダイアログボックスを表示する|
|False|ダイアログボックスを表示しない（デフォルト）|

＜参考サイト＞
・[Documents.Open メソッド (Word)](https://docs.microsoft.com/ja-jp/office/vba/api/word.documents.open)