概要
PDFファイルからテーブルデータを抽出し、Excel形式に変換することは、多くのビジネスやデータ分析の現場で必要とされています。Pythonを使えば、これを簡単に実現することができます。本記事では、Pythonライブラリを使ってPDFからテーブルデータを抽出し、罫線付きのExcelファイルに変換する方法をご紹介します。
使用例
作成されたExcelファイルは、以下のような場面で活用できます:
データ分析 :抽出されたデータをExcelで編集し、グラフやピボットテーブルを作成する。
レポート作成 :定期的に更新されるPDFレポートからデータを抽出し、Excelで統合管理する。
データマイグレーション :旧システムからのデータをPDF形式で受け取り、新システムにExcel形式で移行する。
必要なPythonライブラリとインストール方法
このプログラムを実行するためには、以下のPythonライブラリが必要です:
PyMuPDF(fitz)
camelot-py
openpyxl
tkinterdnd2
PyPDF2(2.10.5) ※3.0.0ではエラーが出ます。
これらのライブラリをインストールするためには、以下のコマンドを使用します:
pip install PyPDF2==2.10.5 camelot-py[cv] openpyxl tkinterdnd2 pymupdf
Copy
使用手順
必要なライブラリをインストールします。ターミナルまたはコマンドプロンプトを開き、上記のコマンドを入力してインストールを行ってください。
下記のプログラムコードをコピーし、メモ帳などのテキストエディタに貼り付けます。その後、ファイル名をpdf_to_excel.py
として保存します。
pdf_to_excel.py
を実行します。ダブルクリックするか、ターミナルまたはコマンドプロンプトでpython pdf_to_excel.py
と入力して実行します。
GUIが表示されるので、PDFファイルをドラッグ&ドロップするか、「Browse」ボタンを使用してPDFファイルを選択します。
出力先フォルダを指定し、「Convert」ボタンをクリックして変換を開始します。
変換が成功すると、指定したフォルダに罫線付きのExcelファイルが保存されます。
注意点
必要なライブラリのバージョン :指定されたバージョンのライブラリを使用してください。特に、PyPDF2のバージョン2.10.5を使用する必要があります。
PDFの内容 :PDF内のテーブルレイアウトが複雑な場合、正しく抽出できないことがあります。その場合は、PDFの内容を確認し、手動で修正してください。
フォント :日本語文字が含まれる場合、フォントの問題で文字が正しく表示されないことがあります。その場合は、フォントを変更するか、手動で修正してください。
プログラム
下記のコードをメモ帳などに丸々コピーして、pythonファイル(pdf_to_excel.py)
にしてください。
import fitz # PyMuPDF import openpyxl as px from openpyxl.styles import Border, Side import tkinter as tk from tkinterdnd2 import TkinterDnD, DND_FILES from tkinter import filedialog from tkinter import messagebox from tkinter import ttk import os import camelot class PDFtoExcelConverter: def __init__(self, root): self.root = root self.root.title("PDF to Excel Converter") self.source_file_path = "" self.destination_folder_path = "" self.source_label = ttk.Label(root, text="Select PDF File:") self.source_label.grid(row=0, column=0, padx=5, pady=5, sticky="w") self.source_entry = ttk.Entry(root, width=50) self.source_entry.grid(row=0, column=1, padx=5, pady=5, sticky="ew") self.source_button = ttk.Button(root, text="Browse", command=self.select_source_file) self.source_button.grid(row=0, column=2, padx=5, pady=5) self.destination_label = ttk.Label(root, text="Select Destination Folder:") self.destination_label.grid(row=1, column=0, padx=5, pady=5, sticky="w") self.destination_entry = ttk.Entry(root, width=50) self.destination_entry.grid(row=1, column=1, padx=5, pady=5, sticky="ew") self.destination_button = ttk.Button(root, text="Browse", command=self.select_destination_folder) self.destination_button.grid(row=1, column=2, padx=5, pady=5) self.convert_button = ttk.Button(root, text="Convert", command=self.convert_pdf_to_excel) self.convert_button.grid(row=2, column=1, padx=5, pady=5) self.progress_label = ttk.Label(root, text="") self.progress_label.grid(row=3, column=0, columnspan=3, padx=5, pady=5) self.dnd_label = ttk.Label(root, text="Drag and Drop PDF File Here:") self.dnd_label.grid(row=4, column=0, columnspan=3, padx=5, pady=5) self.dnd_frame = ttk.Frame(root, relief="sunken", width=50, height=100) self.dnd_frame.grid(row=5, column=0, columnspan=3, padx=5, pady=5, sticky="ew") self.dnd_frame.drop_target_register(DND_FILES) self.dnd_frame.dnd_bind('<<Drop>>', self.on_drop) def select_source_file(self): self.source_file_path = filedialog.askopenfilename(filetypes=[("PDF Files", "*.pdf")]) self.source_entry.delete(0, tk.END) self.source_entry.insert(0, self.source_file_path) def select_destination_folder(self): self.destination_folder_path = filedialog.askdirectory() self.destination_entry.delete(0, tk.END) self.destination_entry.insert(0, self.destination_folder_path) def on_drop(self, event): self.source_file_path = event.data.strip('{}') self.source_entry.delete(0, tk.END) self.source_entry.insert(0, self.source_file_path) def convert_pdf_to_excel(self): if not self.source_file_path: messagebox.showerror("Error", "Please select a PDF file.") return if not self.destination_folder_path: messagebox.showerror("Error", "Please select a destination folder.") return try: # PDFを読み込んでしおりを取得 pdf_document = fitz.open(self.source_file_path) writer = px.Workbook() writer.remove(writer.active) # デフォルトで作成される最初のシートを削除 bookmarks = self.get_bookmarks(pdf_document) for page_num in range(len(pdf_document)): tables = camelot.read_pdf(self.source_file_path, flavor='stream', pages=str(page_num + 1)) if tables: sheet_name = bookmarks.get(page_num, f"{page_num + 1:03d}") if len(sheet_name) > 30: sheet_name = f"{sheet_name[:10]}…{sheet_name[-10:]}-{page_num + 1:03d}" sheet = writer.create_sheet(title=sheet_name) # テーブルの罫線のスタイルを設定 thin_border = Border( left=Side(style='thin'), right=Side(style='thin'), top=Side(style='thin'), bottom=Side(style='thin') ) # ページのテーブルをシートに書き込む for table_idx, table in enumerate(tables): for row_idx, row in enumerate(table.df.values): for col_idx, value in enumerate(row): cell = sheet.cell(row=row_idx + 1, column=col_idx + 1) cell.value = value cell.border = thin_border # 罫線を適用 # 出力先フォルダにExcelファイルを保存 output_file_path = os.path.join(self.destination_folder_path, os.path.splitext(os.path.basename(self.source_file_path))[0] + ".xlsx") writer.save(output_file_path) self.progress_label.config(text="Conversion successful!") except Exception as e: error_message = f"Error: {str(e)}" print(error_message) self.progress_label.config(text=error_message) def get_bookmarks(self, pdf_document): toc = pdf_document.get_toc() bookmarks = {} for item in toc: level, title, page_num = item bookmarks[page_num - 1] = title return bookmarks root = TkinterDnD.Tk() app = PDFtoExcelConverter(root) root.mainloop()
Copy
あるいは、下のテキストファイルをダウンロードし、「.txt」を「.py」に変えることでそのまま使えます。
まとめ
本記事では、Pythonを使用してPDFファイルをExcelファイルに変換する方法を紹介しました。このプログラムを利用することで、PDF内のテーブルデータを簡単に抽出し、Excel形式に変換できます。ビジネスやデータ分析の現場での活用をぜひお試しください。