PDF Pythonツール tkinter ファイル指定

PythonでPDFファイルにしおりの名前を埋め込む方法

概要

この記事では、Pythonを使用してPDFファイルの各ページにしおりの名前を埋め込む手法を紹介します。この技術を利用することで、PDF文書のナビゲーションが容易になり、特に複数の文書が結合された大きなPDFファイルでその効果を発揮します。各ページを見ただけで、どの内容が記載されているか直ちに把握できるようになります。

使用例

企業で月次報告をPDF形式でまとめる場合、各部署から提出された報告を一つのPDFに結合し、各ページにそのセクションのタイトルまたは元のファイル名を埋め込むことがあります。これにより、閲覧者はページをめくるだけで、各ページの内容がすぐに分かります。

必要なPythonライブラリとインストール方法

このプロジェクトには以下のライブラリが必要です:

  • PyPDF2: PDF読み込みと書き込みを行います。
  • PyPDF4: PDF読み込みと書き込みを行います。
  • ReportLab: PDFにテキストを埋め込むために使用します。

これらのライブラリをインストールするには、次のコマンドを実行します:

pip install pypdf2 pypdf4 reportlab

使用手順

  1. PDFファイル選択: GUIを通じて処理したいPDFファイルを選択します。
  2. 保存先選択: 処理後のPDFファイルを保存するディレクトリを指定します。
  3. 処理開始: プログラムが自動でPDFの各ページにしおりのタイトルを赤字で埋め込みます。
  4. 処理完了: 全ページの処理が完了すると、終了メッセージが表示されます。

注意点

  • PDFファイルにしおりが含まれていない場合、"No Bookmark"と表示されます。
  • プログラムはPython 3環境でのみ動作を保証します。
  • GUIはtkinterを使用しており、他のGUIフレームワークに比べ機能が限られています。
  • 文字は英数字のみで日本語には対応していません。
  • しおりの情報は消えます ※現在消えないように対応中です。

プログラム (ver 1)

下記のコードをメモ帳などに丸々コピーしてPythonファイル(bookmark_embedder.py)にしてください。

import tkinter as tk
from tkinter import filedialog, messagebox
from PyPDF2 import PdfReader, PdfWriter
from reportlab.pdfgen import canvas
from io import BytesIO
import decimal

def add_bookmarks_to_pdf(input_path, output_path, progress_callback):
reader = PdfReader(input_path)
writer = PdfWriter()

# PDFのしおりを取得
outlines = reader.outline
page_count = len(reader.pages)

# ReportLabのCanvasを使用してPDFページを作成し、テキストを追加
for page_number, page in enumerate(reader.pages, start=1):
packet = BytesIO()
can = canvas.Canvas(packet, pagesize=(page.mediabox[2], page.mediabox[3])) # ページサイズに合わせる
if outlines and page_number <= len(outlines):
bookmark_title = outlines[page_number - 1].get('/Title', 'No Bookmark')
else:
bookmark_title = 'No Bookmark'

can.setFont("Helvetica", 12)
can.setFillColorRGB(1, 0, 0) # 赤色
y_position = float(page.mediabox[3]) - 72 # decimal.Decimalをfloatに変換
can.drawString(72, y_position, bookmark_title) # ページの左上にテキストを追加
can.save()

# ReportLabから生成されたPDFを元のページにマージ
packet.seek(0)
new_pdf = PdfReader(packet)
page.merge_page(new_pdf.pages[0])
writer.add_page(page)

# 進捗を更新
progress_callback(page_number, page_count)

# ファイルを保存
with open(output_path, 'wb') as output_pdf:
writer.write(output_pdf)

def select_pdf():
return filedialog.askopenfilename(filetypes=[("PDF files", "*.pdf")])

def save_pdf():
return filedialog.asksaveasfilename(defaultextension=".pdf", filetypes=[("PDF files", "*.pdf")])

def start_processing():
input_path = select_pdf()
if not input_path:
messagebox.showinfo("Info", "PDFファイルが選択されていません。")
return

output_path = save_pdf()
if not output_path:
messagebox.showinfo("Info", "保存先が指定されていません。")
return

progress_label.config(text="処理中...")
add_bookmarks_to_pdf(input_path, output_path, update_progress)
messagebox.showinfo("完了", "処理が完了しました!")

def update_progress(current, total):
progress_label.config(text=f"処理中: {current}/{total} ページ")

root = tk.Tk()
root.title("PDF Bookmark Embedder")

tk.Button(root, text="PDF処理を開始", command=start_processing).pack(pady=20)
progress_label = tk.Label(root, text="進捗状況がここに表示されます")
progress_label.pack(pady=10)

root.mainloop()

あるいは、下のテキストファイルをダウンロードし、「.txt」を「.py」に変えることでそのまま使えます。

プログラム (ver 2)

下記のプログラムでは、文字の大きさを指定できるようにしました。

import tkinter as tk
from tkinter import simpledialog, filedialog, messagebox
from PyPDF4 import PdfFileReader, PdfFileWriter
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from io import BytesIO

def add_bookmarks_to_pdf(input_pdf_path, font_size, output_pdf_path):
    reader = PdfFileReader(open(input_pdf_path, "rb"))
    writer = PdfFileWriter()

    # Extract bookmarks if available
    bookmarks = [b for b in reader.getOutlines() if isinstance(b, dict)]

    # Process each page
    for i, page in enumerate(reader.pages):
        # Create a new PDF to draw the bookmark title
        packet = BytesIO()
        can = canvas.Canvas(packet, pagesize=letter)
        bookmark_title = bookmarks[i]['/Title'] if i < len(bookmarks) else 'No Bookmark'
        can.setFont("Helvetica", font_size)
        can.setFillColorRGB(1, 0, 0)  # Set color to red
        can.drawString(72, 800, bookmark_title)  # Adjust position as needed
        can.save()

        # Merge the new PDF with the current page
        packet.seek(0)
        new_pdf = PdfFileReader(packet)
        page.mergePage(new_pdf.getPage(0))
        writer.addPage(page)

    # Save the new PDF
    with open(output_pdf_path, "wb") as f:
        writer.write(f)

def load_pdf():
    input_pdf_path = filedialog.askopenfilename(title="Select a PDF", filetypes=[("PDF files", "*.pdf")])
    if input_pdf_path:
        font_size = simpledialog.askinteger("Font Size", "Enter the font size:", minvalue=1, maxvalue=72)
        if font_size:
            output_pdf_path = filedialog.asksaveasfilename(title="Save the PDF", filetypes=[("PDF files", "*.pdf")], defaultextension=".pdf")
            if output_pdf_path:
                add_bookmarks_to_pdf(input_pdf_path, font_size, output_pdf_path)
                messagebox.showinfo("Success", "PDF processed and saved successfully.")
            else:
                messagebox.showinfo("Error", "No save path specified.")
        else:
            messagebox.showinfo("Error", "No font size specified.")

root = tk.Tk()
root.title("PDF Bookmark Embedder")

button = tk.Button(root, text="Open PDF", command=load_pdf)
button.pack(pady=20, padx=20)

root.mainloop()

あるいは、下のテキストファイルをダウンロードし、「.txt」を「.py」に変えることでそのまま使えます。

まとめ

Pythonを使ったPDF処理は、報告書や資料の整理に非常に有効です。このガイドを参考に、効率的な文書管理システムを構築することができます。また、このプログラムはカスタマイズが可能で、特定のニーズに合わせて変更を加えることができます。

-PDF, Pythonツール, tkinter, ファイル指定