はじめに
Pythonを使ってOffice文書をPDF変換してみました。
※ [LibreOfficeのsofficeコマンドでOffice文書をPDF変換してみた]も合わせてご参照ください。
やりたいこと
Pythonを使って、Office文書をPDFに変換したい。
解決方法
Pythonのsubprocessモジュールを用いて、sofficeコマンドを実行する。
前提知識: LibreOfficeのユーザプロファイル
- ユーザーに関連するすべてのデータを格納するフォルダ
- 拡張機能やカスタム辞書、テンプレートなど
- LibreOfficeをアンインストールやアップデートしても削除されない
- カスタマイズした内容は保存される
- デフォルトの格納場所
- Windows:
%APPDATA%\libreoffice\4\user
- Linux:
/home/<ユーザー名>/.config/libreoffice/4/user
- macOS:
~/Library/Application Support/LibreOffice/4/user
- Windows:
検証環境
- Ubuntu 20.04 LTS
検証シナリオ
ExcelファイルをPDF変換してみます。
- sofficeコマンド実行時のオプション機能
- user_profile: sofficeユーザプロファイルパスを指定
- 指定しない場合、デフォルトのユーザプロファイルが使用される
- timeout: subprocess.run()のタイムアウトを設ける
- 処理遅延した場合、終了させるため
- user_profile: sofficeユーザプロファイルパスを指定
サンプルコード
soffice.py
import os
import subprocess
import shutil
import glob
default_user_profile = os.environ['HOME'] + "/.config/libreoffice/4/user"
class PdfConverter:
def __init__(self,
file_in:str,
file_out:str,
timeout_sec:int=30,
user_profile:str=None):
self.file_in = file_in # 変換対象のOffice文書
self.file_out = file_out # 変換されたPDF文書の格納ディレクトリ
self.timeout_sec = timeout_sec # 変換のタイムアウトリミット
# デフォルトのユーザプロファイルから、新しいユーザプロファイルを作成
self.user_profile = user_profile
if self.user_profile:
if not os.path.exists(self.user_profile):
shutil.copytree(default_user_profile, self.user_profile)
def __enter__(self):
return self
def __exit__(self):
self.stop()
def start(self):
args = [
'soffice',
'--headless',
'--convert-to',
'pdf',
self.file_in,
'--outdir',
self.file_out,
]
if self.user_profile:
args.append('-env:UserInstallation=file://%s' % self.user_profile)
stdout_str = ""
stderr_str = ""
rc = 0
try:
# PDF変換実行、タイムアウトになったらsofficeプロセスを終了させる
ret = subprocess.run(args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
timeout=self.timeout_sec,
check=True,
text=True)
rc = ret.returncode
stdout_str = ret.stdout
stderr_str = ret.stderr
except subprocess.CalledProcessError as cpe:
rc = -1
stdout_str = cpe.stdout
stderr_str = cpe.stderr
except subprocess.TimeoutExpired as te:
rc = -2
stdout_str = te.stdout
stderr_str = te.stderr
finally:
if stdout_str:
print(stdout_str)
if stderr_str:
print(stderr_str)
self.stop()
return rc
def stop(self):
# タイムアウト時に生成される一時ファイルを削除
tmp_files = self.file_out + '/*.tmp'
for f in glob.glob(tmp_files):
os.remove(f)
print('soffice finished')
if __name__ == "__main__":
pc = PdfConverter('test1.xlsx', './output')
# pc = PdfConverter('test1.xlsx', './output', user_profile='/tmp/user_profile')
pc.start()
実行結果
$ python soffice.py
$ ls output
test1.pdf
PDF変換に成功し、outputディレクトリにファイル生成されました。
おわりに
Pythonで、Office文書をPDF変換してみました。
ご参考になればなによりです。