LoginSignup
3
3

More than 1 year has passed since last update.

Pythonを使ってOffice文書をPDF変換してみた

Last updated at Posted at 2022-07-25

はじめに

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

検証環境

  • Ubuntu 20.04 LTS

検証シナリオ

ExcelファイルをPDF変換してみます。

  • sofficeコマンド実行時のオプション機能
    • user_profile: sofficeユーザプロファイルパスを指定
      • 指定しない場合、デフォルトのユーザプロファイルが使用される
    • timeout: subprocess.run()のタイムアウトを設ける
      • 処理遅延した場合、終了させるため

サンプルコード

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変換してみました。
ご参考になればなによりです。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3