VBAを使ったPDFからEXCELへの読み込み方法!

※21/01/01に、よりわかりやすくなるよう更新した箇所があります。■という記号を文頭に置きましたので、テキスト検索等でご利用ください。

PDFファイルからEXCELに内容(テキスト)を読み込みたいことってありますよね。

PDFファイルを開いて、範囲を選択して、コピーして、EXCELに戻ってペースト。

こういう作業は少しのファイル数ならがんばれますが、数十、数百というファイルを対象にするには大変です。

本記事では、「VBAを使ってPDFからEXCELへテキストを読み込む方法」について解説します。

1.PDFからEXCELへの直接読み込みはできる?

こんにちは。エクセルマン・ブリーダーのしもむぎ(@re_znd13)です。

PDFって一度作ってしまえばレイアウトが崩れないので便利ですよね。基本的には編集もしにくいのでネット上に公開するときにはPDFが主流になっています。

このPDFから内容を取り出したいな、と思ったことのある方は経験済みかもしれませんが、実はPDFから他のファイルへの変換はかなり大変です。

それをもとに編集したい、となるとEXCELに持っていきたいのですが、専用の変換ソフトなどを使わずに直接読み込みは可能なんでしょうか?

答えは「できない」です。

私も何度かトライをしているのですが、いったんテキストファイルにする・xmlファイルにするなどと、間接的にしかすることができないようです。

テキストファイルやxmlファイルへの変換には、いくつか方法があります。

Acrobatの編集ソフトを契約して、その機能を使うのがオーソドックスなのかもしれませんが、有償なのでちょっとなぁという方もいますよね。

そこで、今回は無償で利用できるpython(パイソン)を用いてPDFファイルをテキストファイルに変換し、テキストファイルをEXCELに読み込む方法について見ていきます。

最終的にはEXCELからの操作だけで内容(テキスト)を読み込みするような状態を作っていきますよ。

■下の画像は今回扱うファイルやフォルダの構成です。

■任意のフォルダ内に、エクセルマクロ有効ブックとPythonのスクリプト、PDF格納フォルダを用意します。

エクセルマクロ有効ブックには、下のようなワークシートを作成します。

A1セルに対象のフォルダのパスを入力してVBAを実行すると、A列2行目以降にPDFファイルをリストアップします。

■対象のフォルダパスは¥(半角のYENマーク)で閉じておきましょう。

B列2行目以降にはA列のファイルに対応したパスを入力させ、C列2行目以降にはA列のPDFをテキストファイル(txt)にするときのパスを入力させます。

ここまでの情報をもとにpythonでPDF→txtへ変換します。

VBAに戻り、テキストファイルの内容を読み込み、D列2行目以降に入力する、という流れになります。

2.テキストファイルからEXCELへの読み込み方法(VBA)

VBAで、任意のテキストファイルから内容をEXCELに読み込む方法から見てみましょう。

ソースコードを紹介しますね。

まずは対象のフォルダパスをもとに、その中のPDFファイルを抽出します。

nameという変数が、PDFひとつひとつのファイル名です。

たくさんのファイルを扱うことを想定して、ループを組んでいます。

このファイル名を取得できなくなるまでDo whileでループさせています。

操作としては、1列目、つまりA列にファイル名、2列目(B列)にPDFのファイルパス、3列目(C列)にtxtのファイルパスを入力させます。

テキストファイルは、PDFと同名になるようにしています。

Sub フォルダ内のpdf名とパス取得()
Dim Path As String
Dim name As String
Dim row As Long

    Path = ActiveSheet.Cells(1, 1).Value
    name = Dir(Path & "*.pdf")
    row = 2
    Do While name <> ""
        Cells(row, 1) = name
        Cells(row, 2) = Path & name
        Cells(row, 3) = Path & Replace(name, ".pdf", ".txt")
        row = row + 1
        name = Dir()
    Loop
End Sub

次にテキストファイルができたあとの処理です。テキストファイルの作成はpythonで行うので、次節にて説明します。

row=2というのが、EXCELのワークシートの2行目をスタートとしていることを示します。

その行の3列目、つまりC列が空白になるまで、Do Whileでループさせます。

操作としては、C列のパスをLOADしてContentという変数に格納、それを4列目、つまりD列に与えるということをしています。

Sub テキストファイルの中身を取得()
Dim fso As Object
Dim tpath As String
Dim Content As String
Dim row As Long
Set fso = CreateObject("Scripting.FileSystemObject")
    
    row = 2
    Do While Cells(row, 3) <> ""
        tpath = Cells(row, 3)
        With CreateObject("ADODB.Stream")
            .Charset = "UTF-8"
            .Open
            .LoadFromFile tpath
            Content = .ReadText
            .Close
        End With
        Cells(row, 4) = Content
        row = row + 1
    Loop
End Sub

3.PDFからテキストファイルへの変換方法(python)

pythonではPDFからテキストファイルを作成します。

pythonを使うための準備が必要なので、そちらから見ていきましょう。

3.1 pythonのインストール

pythonのインスールプログラムをダウンロードしましょう。こちらにアクセスしてください。

Downloadsをクリックし、OSを選んだら、Python 3.●.●をクリックするとダウンロードができます。

pythonは2系、3系で互換性がないようなので、3.●.●を選択してくださいね。

ダウンロードしたプログラムを起動してインストールを行います。

インストール時には、【Add Python 3.● to PATH】にチェックをつけることをオススメします。

3.2 エディタのインストール

次にエディタをインストールします。ここではVisual Studio Codeというエディタをインストールします。

このエディタはMicrosoftが提供している無償のツールで、オススメです。

こちらからインストールプログラムをダウンロードしましょう。

ここではサイトがOSを判別してくれます。

安定版(Stable Build)のダウンロードボタンが表示されますので、そちらをクリックしてダウンロードしてください。

インストールプログラムを実行してインストールをします。

特に設定を変える必要はないかと思います。

3.3 Visual Studio Codeの機能拡張

Visual Studio Codeは英語仕様なので、日本語仕様にしてしまいましょう。

最左のアイコン群から、一番下のExtensionsをクリックします。

検索バーが表示されるのでJapaneseと入力します。

すると、Microsoftの日本語化パックが見つかると思います。

Installという緑のボタンをクリックしてインストールをします。

拡張機能として、もうひとつ大事なものがあります。

Extensionsの検索バーから、今度はpythonと検索してください。

こちらもMicrosoftが提供しているものが見つかると思いますので、インストールをしてください。

3.4 外部ライブラリのインストール

pythonにはインストール時に付いてくる標準ライブラリと別に、外部ライブラリがあります。

使いたい機能を持つ外部ライブラリをインストールしていくことができるんですね。

ここでは、xlwingsというライブラリをインストールします。

このライブラリは、pythonでEXCELを扱ったり、逆にVBAでpythonのコードを呼び出して実行したりするのに必要です。

Visual Studio Codeを開くと、右下にターミナルと呼ばれるウィンドウがあると思います。

そちらに、「pip install xlwings」と打ち込んでエンター。これでインストールが始まります。Successfully~~というメッセージが表示されたら成功です。

これと同様にして、pdfminer.sixという外部ライブラリもインストールします。

このライブラリには、PDFからテキストを読み込みするのに必要な機能が揃っています。

ターミナルにて、「pip install pdfminer.six」と打ち込んでエンターを押し、Successfully~~のメッセージが表示されたらOKです。

3.5 VBAへのxlwings.basのインポート

VBAでpythonのコードを実行するには、もう少し設定が必要です。

VBAのエディタを開いて、ファイル→ファイルのインポートをクリックしてください。

C:\●●●\Python\Lib\site-packages\xlwingsというフォルダにxlwings.basというファイルがありますので、それを選択して開くをクリックします。

●●●の部分はそれぞれかと思いますが、デフォルト設定であれば、Users\(ユーザー名)\AppData\Local\Programs\となるかと思います。

VBAのエディタで標準モジュールの下にxlwingsというのが追加されたらOKです。

3.6 pythonのコードを記述する

いよいよpythonのコードを記述します。

■手順は以下です。

  1. Visual Studio Codeを開く
  2. 【ファイル】→【フォルダーを開く】から対象のフォルダ(エクセルマクロ有効ブックやPDF格納フォルダが格納されているフォルダ)を選択
  3. 開いたフォルダの右側アイコンから【新しいファイル】を選択
  4. pythonスクリプトのファイル名を入力(拡張子.pyまで要記述)
  5. 右側のエディタ部分にコードを記述

手順5.において、pythonでは、使用するライブラリをインポートするところから記述する必要があります。

ここではxlwingsとpdfminer.sixですね。

その下のdef myPDF2TXT(row):というのは、myPDF2TXTという関数を定義します、という意味です。

他のコード(今回はVBA)から呼び出せるようにするわけですね。

input_path、output_pathの行は、VBAと似た記述なので、わかりやすいかと思います。

これはxlwingsの方の機能で、引数として渡したrowという値を使って、開いているEXCELファイルのセルの値を取得しています。

一章で示した完成イメージでいうところの、PDFのファイルパスをインプット、テキストファイルパスをアウトプットとしています。

import xlwings as xw
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage

def myPDF2TXT(row):
    input_path = xw.Range((row,2)).value
    output_path = xw.Range((row,3)).value

    manager = PDFResourceManager()

    with open(output_path, "wb") as output:
        with open(input_path, 'rb') as input:
            with TextConverter(manager, output, codec='utf-8', laparams=LAParams()) as conv:
                interpreter = PDFPageInterpreter(manager, conv)
                for page in PDFPage.get_pages(input):
                    interpreter.process_page(page)

4.PDFからEXCELへの読み込み(VBA+python)

ここまでの内容を、ドッキングさせてみます。

まずはVBA側のコードから。

■このVBAのコードは第1章で示した全体図でいうところの、エクセルマクロ有効ブック(画像ではpdf2xl.xlsmというファイル)内に記述する内容です。

モジュールごとに記述して、一番上の呼び出し()で順番に呼び出していくようにしました。

初期化()というのは、フォルダパス以外のセルをクリアするために追加しています。

繰り返し実行するためです。

テキストファイル生成()というのが、pythonのコードを呼び出すモジュールになります。

Sub 呼び出し()
    Call 初期化
    Call フォルダ内のpdf名とパス取得
    Call テキストファイル生成
    Call テキストファイルの中身を取得
End Sub

Sub 初期化()
    Range("A2: Z25").ClearContents
End Sub

Sub フォルダ内のpdf名とパス取得()
Dim Path As String
Dim name As String
Dim row As Long

    Path = ActiveSheet.Cells(1, 1).Value
    name = Dir(Path & "*.pdf")
    row = 2
    Do While name <> ""
        Cells(row, 1) = name
        Cells(row, 2) = Path & name
        Cells(row, 3) = Path & Replace(name, ".pdf", ".txt")
        row = row + 1
        name = Dir()
    Loop
End Sub

Sub テキストファイル生成()
    'pythonのコードを呼び出して実行します
Dim row As Long
Dim pypath As String

    row = 2
    Do While Cells(row, 1) <> ""
        pypath = "import p2t; p2t.myPDF2TXT(" & row & ")"
        Call RunPython(pypath)
        row = row + 1
    Loop
End Sub

Sub テキストファイルの中身を取得()
Dim fso As Object
Dim tpath As String
Dim Content As String
Dim row As Long
Set fso = CreateObject("Scripting.FileSystemObject")
    
    row = 2
    Do While Cells(row, 1) <> ""
        tpath = Cells(row, 3)
        With CreateObject("ADODB.Stream")
            .Charset = "UTF-8"
            .Open
            .LoadFromFile tpath
            Content = .ReadText
            .Close
        End With
        Cells(row, 4) = Content
        row = row + 1
    Loop
End Sub

次にpython側のコードです。

■このpython側のコードは第1章で示した全体図でいうところの、pythonスクリプト(画像ではp2t.pyというファイル)内に記述する内容です。

こちらは3.6節と変わりありません。

VBA側のテキストファイル生成()が呼び出すのがこちらになります。

特にpythonスクリプト(pyファイル)の場所を記述していませんが、同一フォルダに格納してあれば呼び出せるようになっています。

import xlwings as xw
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage

def myPDF2TXT(row):
    input_path = xw.Range((row,2)).value
    output_path = xw.Range((row,3)).value

    manager = PDFResourceManager()

    with open(output_path, "wb") as output:
        with open(input_path, 'rb') as input:
            with TextConverter(manager, output, codec='utf-8', laparams=LAParams()) as conv:
                interpreter = PDFPageInterpreter(manager, conv)
                for page in PDFPage.get_pages(input):
                    interpreter.process_page(page)

5.まとめ

本記事では、 「VBAを使ってPDFからEXCELへテキストを読み込む方法」について解説しました。

かなり長くなってしまいましたが、いかがでしたか?

今回は、エクセル部では初の、pythonを利用しての解法となりました。

両者の長所を理解して、うまく組み合わせていけるとよいですね。

4 件のコメント

  • この記事にある「python側のコード」というのは、どこにどんなファイル名で記述すればいいのですか?

    • ナガイテルヒサさん
      シモムギです。コメントありがとうございます。
      python側のコードはVisual Studio Codeで拡張子が.pyのファイルを作成して、その中に記述する必要があります。
      記事内ではp2t.pyというファイル名になっていますが、ファイル名は任意でOKです(記事内のコードをコピペしていただいた場合でも影響ありません)。
      いただいたコメントをもとに、よりわかりやすくなるよう記事を更新しました。
      更新箇所には■という記号を文頭に置いていますので、テキスト検索等ご利用いただき、記事を再度お読みいただけますと幸いです。

  • Traceback (most recent call last):
    File “”, line 1, in
    AttributeError: module ‘p2t’ has no attribute ‘myPDF2TXT’

    実行すると上のようなエラーが出てきて動いてくれません。どうしたらよいでしょうか?

    • トグラムさん
      シモムギです。コメントありがとうございます。
      返信が遅くなってしまいすみませんでした。
      エラーの件ですが、「p2tにmyPDF2TXTがありません」というような意味のエラーとなりますので、p2t.pyの記述でモジュールの定義部分がmyPDF2TXTとなっているかご確認いただけますか?
      例えば、myPDFTXT(2が抜けている)などのようにスペルミスがある場合には以下のようなエラーが再現しております。
      File ““, line 1, in
      AttributeError: module ‘p2t’ has no attribute ‘myPDF2TXT’

  • コメントを残す

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