Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【Python】ReportLabを使ってExcelからPDFを作成するサンプルコードを解説

この記事では、PythonのReportLabとopenpyxlライブラリを使い、Excelの表データからPDFを自動生成する方法を解説します。日本語フォント対応や画像挿入、表のスタイル設定など、実務で役立つPDF作成の基本的な技術を習得できます。システムエンジニアの業務効率化に繋がる知識です。

作成日: 更新日:

開発環境

  • Python version: python 3.10.11

PythonのReportLabとは

ReportLab(レポートラボ)とは、Python言語でPDF文書を生成するためのライブラリです。 このライブラリを使用すると、PDFファイルの中に文字、画像、表といった様々な要素を配置し、独自のPDF文書を作成することが可能になります。

今回は、ReportLabを、Excelファイルを扱うためのライブラリであるopenpyxlと連携させて使用する方法についてご紹介します。具体的には、openpyxlでExcelの表データを読み込み、そのデータをReportLabを使ってPDF形式の表として出力するといった処理が実現できます。このように、複数のライブラリを組み合わせることで、より実用的なシステムを構築することができます。

ReportLabに関するさらに詳しい情報は、以下の公式ドキュメントで確認できます。 公式ドキュメント:https://docs.reportlab.com/

PythonのReportLabの使い方

ReportLabは、Pythonを使ってPDFファイルをプログラムで作成するためのライブラリです。システムエンジニアの仕事では、日報、請求書、レポートなど、様々な文書をPDF形式で出力する場面が多くあります。ReportLabを使えば、これらのPDFファイルをPythonプログラムから自動で生成できるようになります。

PDFは、どの環境でも同じ見た目で表示されるため、ビジネスシーンで広く利用されています。ReportLabを活用することで、定型的なPDFの作成作業を自動化し、効率的に業務を進めることが可能です。

ReportLabとopenpyxlをインストール

ReportLabと、Excelファイルを扱うためのopenpyxlというライブラリをインストールします。これらのライブラリをPythonで使えるようにするには、pipというパッケージ管理ツールを使用します。pipはPythonの便利な機能やライブラリを、インターネットからダウンロードして自分のパソコンに導入するためのコマンドです。

以下のコマンドをターミナルやコマンドプロンプトで実行してください。

1pip install openpyxl reportlab

このコマンドを実行すると、ReportLabとopenpyxlがあなたのPython環境にインストールされ、プログラムから利用できるようになります。これで、ReportLabを使ったPDF作成の準備が完了しました。

PythonのReportLabでExcelからPDFを作成する

次にPythonのReportLabを使って、Excelファイルからデータを読み込み、そのデータを基にPDFを作成する方法を学習していきます。ReportLabは、Pythonで柔軟にPDFを生成できる強力なツールです。実務では、請求書や報告書など、定型フォーマットのPDFを自動生成する場面で非常に役立ちます。

今回使用するファイル

この学習では、以下の2つのファイルを使用します。

  • 集計表.xlsx:売上データの集計表です。1行目には月、A列には会社名が記載されています。
  • confidential_image.png:PDFの右上に挿入する「社外秘」と書かれた画像ファイルです。

この2つのファイルを使って、集計表のデータをPDF形式の表に変換し、書式を整えたり、画像や文字を挿入して、最終的に1つの見やすいPDFファイルを作成します。

PDF作成のサンプルコード

下記はReportLabを使用して集計表.xlsxのデータをPDFの表として描画し、画像とタイトルの文字を挿入して集計表.pdfを作成するサンプルコードです。

1# 必要なライブラリをインポートする
2from openpyxl import load_workbook
3from reportlab.lib.pagesizes import A4, landscape
4from reportlab.pdfgen import canvas
5from reportlab.platypus import Table, TableStyle
6from reportlab.pdfbase import pdfmetrics
7from reportlab.pdfbase.cidfonts import UnicodeCIDFont
8from reportlab.lib.units import mm
9from reportlab.lib.utils import ImageReader
10from reportlab.lib import colors
11import datetime
12
13# ファイルパスを指定
14excel_path = './集計表.xlsx'
15pdf_path = './集計表.pdf'
16confidential_image_path = './confidential_image.png'
17
18# エクセルファイルの読み込み
19wb = load_workbook(excel_path)
20ws = wb.active
21
22# A4サイズのPDFファイルを作成
23pdf = canvas.Canvas(pdf_path, pagesize=landscape(A4))
24
25# エクセルのデータをリストに変換
26data = []
27for row in ws.iter_rows():
28    row_data = []
29    for cell in row:
30        if isinstance(cell.value, datetime.datetime):
31            format_date = datetime.datetime.strftime(cell.value, '%Y年%m月')
32            row_data.append(format_date)
33        else:
34            row_data.append(str(cell.value))
35    data.append(row_data)
36
37# テーブルの作成
38col_widths = [30*mm] + [20*mm] * (len(data[0]) - 1)
39table = Table(data, colWidths=col_widths, rowHeights=7*mm)
40
41# フォントの登録
42pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5'))
43
44# テーブルスタイルの設定(オプション)
45style = TableStyle(
46    [
47        ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
48        ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
49        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
50        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
51        ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
52        ('GRID', (0, 0), (-1, -1), 1, colors.black),
53        ('FONT', (0, 0), (-1, -1), 'HeiseiKakuGo-W5', 9),
54    ]
55)
56
57# テーブルにスタイルを適用
58table.setStyle(style)
59
60# ページのサイズを取得
61width, height = landscape(A4)
62
63# テーブルの描画位置を計算
64table_width, table_height = table.wrapOn(pdf, width, height)
65x = (width - table_width) / 2
66y = (height - table_height) / 2
67
68# テーブルを描画
69table.drawOn(pdf, x, y)
70
71# 画像をPDFに挿入
72confidential_image = ImageReader(confidential_image_path)
73pdf.drawImage(confidential_image, width - 113, height - 35, width=113, height=35, mask='auto')
74
75# 真ん中にテキストを挿入
76pdf.setFont('HeiseiKakuGo-W5', 16)
77pdf.drawString(width / 2, height -20, "集計表")
78
79# PDFファイルを保存
80pdf.save()

作成したファイルは、以下のコマンドで実行できます。

1python excel.py

ライブラリをインポートする

まず、PDF作成に必要な様々な機能を持つライブラリをプログラムで使えるように読み込みます。これを「インポート」と呼びます。

1from openpyxl import load_workbook
2from reportlab.lib.pagesizes import A4, landscape
3from reportlab.pdfgen import canvas
4from reportlab.platypus import Table, TableStyle
5from reportlab.pdfbase import pdfmetrics
6from reportlab.pdfbase.cidfonts import UnicodeCIDFont
7from reportlab.lib.units import mm
8from reportlab.lib.utils import ImageReader
9from reportlab.lib import colors
10import datetime

それぞれのライブラリやモジュールには、以下の役割があります。

  • load_workbook:ExcelファイルをPythonプログラムで読み込むために使用します。
  • A4、landscape:PDFの用紙サイズをA4に設定し、その向きを横向きにするために使用します。
  • canvas:PDFファイル自体を作成し、その上に図形や文字などを描画するための「キャンバス(画用紙)」を用意します。
  • Table、TableStyle:PDF内に表(テーブル)を作成し、その表のデザイン(スタイル)を設定するために使用します。
  • pdfmetrics、UnicodeCIDFont:PDF内で日本語などの特殊なフォントを使用するために、フォントを登録する際に必要です。
  • mm:PDF内で要素の幅や高さなどをミリメートル(mm)単位で指定できるようにします。
  • ImageReader:画像ファイルを読み込み、PDFに挿入できるようにします。
  • colors:PDF内で背景色や文字色などを指定するための色を定義します。
  • datetime:Excelファイルに含まれる日付データを、「2024年04月」のような特定の形式に変換するために使用します。

ExcelファイルとPDFファイルを準備する

次に、使用するExcelファイルの場所を指定し、PDFファイルの「土台」を準備します。

1excel_path = './集計表.xlsx'
2pdf_path = './集計表.pdf'
3confidential_image_path = './confidential_image.png'
4
5wb = load_workbook(excel_path)
6ws = wb.active
7
8pdf = canvas.Canvas(pdf_path, pagesize=landscape(A4))
  • excel_path、pdf_path、confidential_image_path:それぞれExcelファイル、出力するPDFファイル、挿入する画像ファイルの場所(パス)を変数に設定しています。./は、Pythonスクリプトと同じフォルダにあることを意味します。
  • load_workbook(excel_path)で、指定したExcelファイルをPythonで読み込みます。この読み込んだExcelファイルをwb(ワークブックの略)という変数に格納します。
  • ws = wb.activeで、開いたExcelファイルの中で現在アクティブになっているシート(一番手前に表示されているシート)を取得し、ws(ワークシートの略)という変数に格納します。
  • canvas.Canvas(pdf_path, pagesize=landscape(A4))で、新しく集計表.pdfという名前のPDFファイルを作成する準備をします。pagesize=landscape(A4)という設定により、PDFの用紙サイズがA4で、かつ横向きになります。このPDFの描画領域をpdfという変数に格納しています。

ExcelのデータをPDF用のリストに変換する

PDFで表として描画するために、Excelから読み込んだデータをPythonのリスト形式に整えます。

1data = []
2for row in ws.iter_rows():
3    row_data = []
4    for cell in row:
5        if isinstance(cell.value, datetime.datetime):
6            format_date = datetime.datetime.strftime(cell.value, '%Y年%m月')
7            row_data.append(format_date)
8        else:
9            row_data.append(str(cell.value))
10    data.append(row_data)
  • data = []:Excelの全データを格納するための空のリストを作成します。このリストは最終的に「2次元リスト」という、リストの中にさらにリストが入った形になります。
  • for row in ws.iter_rows()::アクティブなシート(ws)から、データを1行ずつ取り出して処理します。
  • row_data = []:各行のデータを格納するための空のリストを、行ごとに初期化します。
  • for cell in row::現在処理している行(row)の中から、セル(マス目)のデータを1つずつ取り出して処理します。
  • if isinstance(cell.value, datetime.datetime)::セルの値(cell.value)がdatetime.datetime型(日付と時刻を表す型)であるかどうかを判定しています。Excelのヘッダー行にある「月」がこの日付型に該当します。
    • もし日付型であれば、datetime.datetime.strftime(cell.value, '%Y年%m月')を使って、「2024年04月」のような「年」と「月」の形式の文字列に変換し、format_dateに格納します。
    • それ以外の場合(会社名や売上数値など)は、str(cell.value)を使って、値がどのような型であっても文字列に変換します。
  • row_data.append(...):変換したセルの値をrow_dataリストの末尾に追加していきます。
  • data.append(row_data):1行分のすべてのセルデータをrow_dataに格納し終えたら、そのrow_dataを全体のデータリストdataの末尾に追加します。これにより、Excelの表が、Pythonで扱える2次元のリスト形式になります。

表を作成する

変換したデータを使って、PDFに描画する表のオブジェクトを作成します。

1col_widths = [30*mm] + [20*mm] * (len(data[0]) - 1)
2table = Table(data, colWidths=col_widths, rowHeights=7*mm)
  • col_widths = [30*mm] + [20*mm] * (len(data[0]) - 1):表の各列の幅を設定するリストを作成しています。
    • 30*mm:最初の列(A列に該当する会社名)の幅を30ミリメートルに設定します。
    • [20*mm] * (len(data[0]) - 1):data[0]はExcelのヘッダー行(1行目)のデータリストです。len(data[0])はそのヘッダー行の列数、つまり表全体の列数を表します。ここから最初の1列(会社名)を除いた残りの列すべてを、幅20ミリメートルに設定しています。これにより、月ごとの売上データ部分の列幅が統一されます。
  • table = Table(data, colWidths=col_widths, rowHeights=7*mm):Tableクラスを使って、実際の表のオブジェクトを作成します。
    • data:先ほどExcelから変換した2次元リストを渡します。これが表の内容になります。
    • colWidths=col_widths:作成した列幅のリストを表に適用します。
    • rowHeights=7*mm:すべての行の高さを7ミリメートルに設定します。

表のスタイルを設定する

PDFに日本語を表示できるようにフォントを登録し、表の色や文字の配置、罫線などのデザイン(スタイル)を細かく設定します。

1pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5'))
2
3style = TableStyle(
4    [
5        ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
6        ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
7        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
8        ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
9        ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
10        ('GRID', (0, 0), (-1, -1), 1, colors.black),
11        ('FONT', (0, 0), (-1, -1), 'HeiseiKakuGo-W5', 9),
12    ]
13)
14
15table.setStyle(style)
  • pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5')):ReportLabのデフォルトフォントでは日本語が正しく表示されないため、日本語フォント「HeiseiKakuGo-W5」(平成角ゴシック)を登録しています。これにより、PDFで日本語が正しく表示されるようになります。
  • style = TableStyle([...]):表のデザインを指定するためのTableStyleオブジェクトを作成します。スタイルは、(設定項目, 開始位置, 終了位置, 値)という形式のタプルを要素とするリストで指定します。
    • 位置は(列のインデックス, 行のインデックス)で指定し、(0, 0)は左上のセル、(-1, -1)は右下のセルを表します。
    • ('BACKGROUND', (0, 0), (-1, 0), colors.grey):ヘッダー行(最初の行全体)の背景色を灰色に設定します。
    • ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke):ヘッダー行の文字色を白っぽい煙色に設定します。
    • ('ALIGN', (0, 0), (-1, -1), 'CENTER'):表全体の文字を左右中央揃えにします。
    • ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'):表全体の文字を上下中央揃えにします。
    • ('BACKGROUND', (0, 1), (-1, -1), colors.beige):データ行(ヘッダー行を除くすべての行)の背景色をベージュに設定します。
    • ('GRID', (0, 0), (-1, -1), 1, colors.black):表全体のすべてのセルに、太さ1ポイントの黒い罫線を引きます。
    • ('FONT', (0, 0), (-1, -1), 'HeiseiKakuGo-W5', 9):表全体のフォントを先ほど登録した「HeiseiKakuGo-W5」にし、サイズを9ポイントに設定します。
  • table.setStyle(style):作成したstyleオブジェクトを、先ほど作成したtableオブジェクトに適用します。

表をPDFの中央に描画する

作成した表をPDFページの中央に配置して描画します。

1width, height = landscape(A4)
2
3table_width, table_height = table.wrapOn(pdf, width, height)
4x = (width - table_width) / 2
5y = (height - table_height) / 2
6
7table.drawOn(pdf, x, y)
  • width, height = landscape(A4):横向きA4ページの幅と高さを取得し、それぞれwidthとheightという変数に格納します。
  • table_width, table_height = table.wrapOn(pdf, width, height):表をPDFに描画する前に、その表が実際にどれくらいの幅と高さを占めるのかを計算します。wrapOnメソッドは、指定されたページサイズ(width, height)内で表を配置した場合の、表自身の幅と高さを返します。
  • x = (width - table_width) / 2:PDFページの左端から、表を描画し始めるX座標(横方向の位置)を計算します。ページの全幅から表の幅を引いた残りが左右の余白の合計なので、それを2で割ることで、左右の余白を均等にして中央に配置するためのX座標が得られます。
  • y = (height - table_height) / 2:同様に、PDFページの下端から、表を描画し始めるY座標(縦方向の位置)を計算します。ReportLabでは、PDFの描画の基準位置は左下になりますので、この計算で表がページの中央に配置されます。
  • table.drawOn(pdf, x, y):計算したxとyの座標に、tableオブジェクトをPDF(pdfキャンバス)に描画します。

画像を挿入する

PDFの右上に「社外秘」の画像を挿入します。

1confidential_image = ImageReader(confidential_image_path)
2pdf.drawImage(confidential_image, width - 113, height - 35, width=113, height=35, mask='auto')
  • confidential_image = ImageReader(confidential_image_path):ImageReaderを使って、指定したパスの画像ファイル(confidential_image.png)を読み込みます。
  • pdf.drawImage(confidential_image, width - 113, height - 35, width=113, height=35, mask='auto'):読み込んだ画像をPDFに描画します。
    • confidential_image:描画する画像オブジェクトです。
    • width - 113:画像の左下を配置するX座標です。ページの全幅から画像の幅(113ポイント)を引くことで、画像がページの右端に接するように配置されます。
    • height - 35:画像の左下を配置するY座標です。ページの全高から画像の高さ(35ポイント)を引くことで、画像がページの上端に接するように配置されます。
    • width=113, height=35:描画する画像の幅と高さを指定します。
    • mask='auto':PNG画像などに含まれる透過情報が自動的に適用され、背景が透明な状態で画像が描画されます。

文字を挿入する

PDFの上部中央に「集計表」というタイトル文字を挿入します。

1pdf.setFont('HeiseiKakuGo-W5', 16)
2pdf.drawString(width / 2, height -20, "集計表")
  • pdf.setFont('HeiseiKakuGo-W5', 16):これから描画する文字のフォントを、事前に登録した「HeiseiKakuGo-W5」に設定し、サイズを16ポイントにします。
  • pdf.drawString(width / 2, height -20, "集計表"):指定した座標に文字列を描画します。
    • width / 2:X座標はページの横幅を2で割った位置で、ページの左右中央を表します。
    • height - 20:Y座標はページの高さから20ポイント引いた位置で、ページの上部から少し下がった場所になります。
    • "集計表":実際に描画される文字列です。

PDFファイルを保存する

最後に、作成したPDFの内容をファイルとして保存します。

1pdf.save()
  • pdf.save():これまでのすべての描画命令を元に、最終的なPDFファイルをpdf_pathで指定した集計表.pdfという名前で保存します。

この一連の処理が完了すると、集計表.pdfが作成され、書式が設定された表と、右上の画像、上部の「集計表」というタイトル文字が描画されていることが確認できます。

おわりに

この記事では、PythonのReportLabとopenpyxlライブラリを連携させ、Excelの表データからPDFを自動生成する基本的な方法を学ぶことができました。ReportLabのcanvasでPDFの土台を作り、openpyxlで読み込んだExcelデータをTableとしてPDFに描画する一連の流れを解説しました。また、TableStyleで表のデザインを整えたり、UnicodeCIDFontで日本語フォントに対応させたり、ImageReaderで画像を挿入したりする実用的なテクニックも習得できたかと思います。これらの知識は、システムエンジニアとして請求書や報告書といった定型的なPDF文書の作成作業を自動化し、日々の業務効率を大きく向上させることにつながるでしょう。

関連コンテンツ

関連IT用語