【Python】Excel を PDF に変換する(Alpine Linux + LibreOffice )
最近は、全くブログを更新できておらず、反省しなければと思っている今日この頃。お陰様で、下書きは溜まりに溜まっているので、整理しながら順次公開していきたいと思う。
今回は、Docker の Alpine Linux 上で、Excel ファイルを PDF に変換する処理を実装したので、その実装方法を紹介する。
Excel ファイルを PDF に変換する方法
Excel ファイルを PDF に変換するには、まず Excel ファイルを開く必要がある。そこで、必要になるのが Excel ファイルを開くことができるソフトウェアである。実行環境が、Windows であり、Microsoft の Excel が入っているのであれば、 win32com
というモジュールを使うことで、pythonから Excel ファイルを操作することができる。ただし、このモジュールはデフォルトで入っていないので、pip でインストールする必要がある。
$ pip install pywin32
以下のコードで、Excel ファイル全体を PDF に変換することができる。
import win32com.client # win32com ライブラリを読み込み excel = win32com.client.Dsipatch("Excel.Application") # Excelを起動 book = excel.Workbooks.Open("input_file.xlsx") # Excelでファイルを読み込み book.ExportAsFixedFormat(0, "output_file.pdf") # PDF形式で保存 excel.Quit() # Excelを終了
ただし、今回は Docker の Alpine Linux を想定しており、このモジュールを使うことができない。
そこで今回は、オープンソースソフトウェアである LibreOffice を使って、Excel ファイルを PDF に変換することとした。 ja.libreoffice.org
Excel と同様の表計算ソフトウェアとして、「Calc」が存在するので、それを使うこととする。LibreOffice は様々な機能をコマンドラインから起動できるので、とても便利である。 --headless
オプションを指定することで、LibreOffice の GUI を表示せずに機能を利用することができる。Excel ファイルを PDF に変換するコマンドは以下の通りである。
LibreOffice:version 6.4.4.2
$ libreoffice --headless --nologo --nofirststartwizard --convert-to pdf --outdir <output_path> <input_file.xlsx>
上記で設定しているオプションは以下の通りである。
- headless:ヘッドレスモード(GUIを表示しないモード)
- nologo:スプラッシュ画面(起動画面)を表示しない
- nofirststartwizard:初回起動ウィザードを起動しない
- convert-to [拡張子]:[フィルタ]:[エンコード]:変換ファイルと形式を指定する
- outdir [出力先]:ファイルの出力先を指定する(出力ファイル名は設定できない。拡張子が変わるのみ。)
Dockerfile
参考までに作成した Dockerfile は以下の通りである。(Djangoのアプリケーションを開発していた Docker に、LibreOffice を追加しているので、実際には最小構成ではない。build-rundepsで不要な物が含まれていると思われる。)
|- Dockerfile |- requirements.txt |- fonts/
FROM python:3.9-alpine3.12 ENV PYTHONUNBUFFERED 1 RUN apk update \ && apk add --no-cache --virtual .build-rundeps \ linux-headers \ build-base \ mariadb-connector-c-dev \ libxml2-dev \ libxslt-dev \ && apk add --upgrade --no-cache --virtual .libreoffice-rundeps \ libreoffice \ libreoffice-base \ libreoffice-lang-ja \ font-noto-cjk RUN mkdir /code WORKDIR /code ADD ./requirements.txt /code/ RUN pip3 install -r requirements.txt ADD . /code/ RUN mkdir -p /usr/share/fonts/ COPY fonts/ /usr/share/fonts/ RUN fc-cache -fv EXPOSE 8000
日本語のフォントがない場合に、PDF に変換した際に、文字化けを起こすので、日本語のフォントをインストールする必要がある。 font-noto-cjk
で最低限のフォント(noto)をインストールしているが、Excel内で指定しているフォントが使いたかったので、ローカルからコンテナ(/usr/share/fonts/)にフォントをコピーしている。
Pythonからの変換コマンドの実行(subprocess)
Pythonから他のアプリを起動する場合などには、標準ライブラリである subprocess を用いるのが一番簡単である。
import subprocess subprocess.run(["実行コマンド"], shell=True)
先ほど示した、Excel ファイルを PDF に変換するコマンドは、以下のようにして実行できるようにした。
def convertExcelToPdf(file_name, path): cmd = [] cmd.append("libreoffice") cmd.append("--headless") cmd.append("--nologo") cmd.append("--nofirststartwizard") cmd.append("--convert-to") cmd.append("pdf") cmd.append("--outdir") cmd.append(path) cmd.append(file_name) subprocess.run(" ".join(cmd), shell=True)
(なぜか配列指定では、libreofficeのコマンドが適切に実行されなかったので、スペースを間に入れた文字列結合でコマンドが実行されるようにした。)
まとめ
LibreOffice というめちゃくちゃ便利なオープンソフトウェアのお陰様で、今回も Excel ファイルを PDF に変換することができた。本当に感謝である。LibreOffice は初めて使ってみたが、今後も様々な場面で使っていきたい。
ただ、Excel のヘッダーに画像を挿入していたが、それがなぜか消えている問題が先ほど発覚した。シートに挿入している画像はきちんと表示されているので、Excel のヘッダーの設定がうまく読み込まれていない可能性が高い。試行錯誤したが表示されなかったので、もし知見がある方がいたら、是非とも教えて欲しい。
それでは、ステキな開発ライフを。