※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のコードを記述します。
■手順は以下です。
- Visual Studio Codeを開く
- 【ファイル】→【フォルダーを開く】から対象のフォルダ(エクセルマクロ有効ブックやPDF格納フォルダが格納されているフォルダ)を選択
- 開いたフォルダの右側アイコンから【新しいファイル】を選択
- pythonスクリプトのファイル名を入力(拡張子.pyまで要記述)
- 右側のエディタ部分にコードを記述
手順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を利用しての解法となりました。
両者の長所を理解して、うまく組み合わせていけるとよいですね。