外部ライブラリ xlwings を使うと、PythonからExcelを操作できるプログラムを簡単に作成することができます。
Excelファイルの印刷を自動化する方法にはVBAマクロを実装するものもありますが、Pythonでも同じことを実現可能です。
- 印刷(プリンター)の実行
- PDFに変換
- 印刷範囲の調整
高機能なPythonのファイル抽出機能と組み合わせると、条件にあったExcelファイルを自動で編集、範囲を設定して印刷する流れを自動化できます。
ページの最後では、特定のファイル名のExcelを自動で一括印刷するコードを例示しています。ぜひ参考にしてみてください。
結論
印刷の実行(ネイティブAPI利用)
sheet.api.PrintOut(From=1, To=1, Copies=1, ActivePrinter='NATIVE PRINTER NAME')
PDFに変換
ワークブック全体のPDFを生成
wb.to_pdf()
シート単位でPDFを生成
sheet.to_pdf()
印刷範囲の設定
sheet.page_setup.print_area = '$A$2:$H$40'
印刷範囲のクリア
sheet.page_setup.print_area = None
実行環境
Microsoft Office Excel 2019
> python --version
Python 3.9.4
> pip freeze
xlwings==0.24.9
今回使用したサンプルデータ
総務省 人口推計 各月1日現在人口 (年齢、男女別人口)
統計局ホームページ/人口推計
印刷(プリンター)の実行
現在のところ xlwings のPython APIにはプリンター印刷機能がありません。
そこで、Excelインスタンスに直接アクセスするオブジェクトを取得して(VBAと同じように)印刷を実行します。
xlwings は本質的にはpywin32のプロセス間通信のラッパーなので、sheet.api
でExcelのオブジェクトを取得できます。
印刷を行うのは Sheet.PrintOut()
メソッドです。
PrintOut(From, To, Copies, Preview, ActivePrinter,...)
From | 印刷を開始するページの番号。None(デフォルト)なら最初のページから印刷 |
To | 印刷を終了するページの番号。None(デフォルト)なら最後のページまで印刷 |
Copies | 印刷部数。 None(デフォルト)なら1 部。 |
Preview | True ときは印刷プレビューを表示 |
ActivePrinter | プリンター名を指定。プリンター一覧に表示されている名前でOK |
その他のパラメータはドキュメント参照。
Workbook.PrintOut メソッド (Excel) | Microsoft Docs
wb: Book = xw.books.open('./data/population.xlsx')
sheet: Sheet = wb.sheets[0]
sheet.api.PrintOut(From=1, To=1, Copies=1, ActivePrinter='Canon XX9999')
注意ポイント
xlwings はあらかじめExcelを起動しておく必要があります。空のワークブックを新規作成するなどしてから実行してください。
PDFに変換
ExcelシートをPDFとして出力する機能はPython APIで提供されており、簡単に実装可能。xlwings バージョン 0.22.3から追加された機能です。
PDF変換を行うには Book.to_pdf()
または Sheet.to_pdf()
を呼び出します。
ブック単位で印刷する場合
Book.to_pdf(path=None, include=None, exclude=None, exclude_start_string='#', show=False)
path | PDFファイルのパス。Noneの場合はブックと同じ名前で同じディレクトリに保存される |
include | 変換に含めるシートを指定。シート番号(1から始まる)またはシート名のリストで指定 |
exclude | 変換から除くシートを指定。シート番号(1から始まる)またはシート名のリストで指定 |
exclude_start_string | 除外するシートの接頭辞を文字列で指定(この文字列から始まる名前を持つシートは変換対象外となる) |
show | 作成後にPDFビューアで開くならTrueを渡す |
シート単位で印刷する場合
Sheet.to_pdf(path=None, show=False)
path | PDFファイルの保存パス。Noneの場合はシートと同じ名前で同じディレクトリに保存される |
show | 作成後にPDFビューアで開くならTrueを渡す |
標準機能で使用できるパラメータのみ。より詳しくはドキュメント参照。
Python API - xlwings Documentation
# ワークブック全体、複数シートを指定してPDFを生成
wb.to_pdf(show=True)
# シート単位でPDFを生成
sheet.to_pdf(show=True)
印刷範囲の設定
xlwings.main.PageSetup
クラスのインスタンス(Book.PageSetup
からアクセス)が持つ print_area
メンバにセル範囲を設定するだけです。
ここでは統計局の人口統計(2021年9月)をサンプルとして設定してみます。
サンプルファイルに既に設定されている印刷範囲を取得します。
p_area = sheet.page_setup.print_area
print(p_area)
# $A$1:$M$56
この印刷範囲で印刷(PDF変換)した結果
印刷範囲を改めて設定します。
sheet.page_setup.print_area = '$A$4:$F$34'
sheet.to_pdf(path='population_details.pdf', show=True)
この印刷範囲で印刷(PDF変換)した結果
印刷範囲のクリア
同様にNone
を設定すると、印刷範囲をクリアできます。
sheet.page_setup.print_area = None
実際に印刷(PDF変換)すると印刷範囲がクリアされていることが確認できます。
複数のExcelブックの印刷範囲を設定して印刷
上述の方法を活用し複数Excelブックを連続印刷するサンプルコードを作成してみます。
まずは、特定のディレクトリ(フォルダ)にある、特定の名前を持つExcelファイルを抽出します。
ファイル名による抽出には標準パッケージの glob を使用します。この例では名前が 05k2-
から始まる、拡張子 .xlsx
のファイルをリストで取得します。
# 特定のファイル名を持つExcelを取得
import glob
work_dir = './data/population'
files_target = glob.glob(f'{work_dir}/05k2-*.xlsx')
print(files_target)
# ['./data/population\\05k2-1_202101.xlsx', './data/population\\05k2-1_202102.xlsx', './data/population\\05k2-1_202103.xlsx', './data/population\\05k2-1_202104.xlsx', './data/population\\05k2-1_202105.xlsx', './data/population\\05k2-1_202106.xlsx', './data/population\\05k2-1_202107.xlsx', './data/population\\05k2-1_202108.xlsx', './data/population\\05k2-1_202109.xlsx']
for構文のループを使って、先ほど取得したファイルリスト files_target
の全ファイルを印刷します。
なお、xw.books.open(path_to_file)
で正しくファイルパスを認識させるために、Windowsでは バックスラッシュ \
を スラッシュ/
に置換しています。
印刷前には印刷範囲の設定も行っています。PageSetup.print_area
パラメータにセル範囲を渡して設定できます。
forループの中では、最後に必ずBook.close()
を読んでワークブックを閉じます(印刷が終わってもExcelブックが開いたまま蓄積されてしまうため)。
import os
# ファイルごとに印刷範囲設定、印刷
for fp in files_target:
# (Windowsのみ)ファイルパスの修正
fp = fp.replace('\\', '/')
# (解説用)現在処理しているファイル名
fname = os.path.basename(fp)
print(f"処理中: {fname}")
wb: Book = xw.books.open(fp)
sheet: Sheet = wb.sheets[0]
sheet.page_setup.print_area = '$A$4:$F$34'
# 印刷する場合
# sheet.api.PrintOut(From=1, To=1, Copies=1, ActivePrinter='Canon ZZ9999 series')
# PDF変換する場合
sheet.to_pdf(path=f'{work_dir}/{fname}', show=False)
wb.close()
さらにカスタマイズする方法
サンプルコードでは印刷するExcelファイル名、印刷範囲を決め打ちで指定していますが、関数化したり起動時パラメータで指定できるようにすると、作業ごとに柔軟に変更できるでしょう。
また、今回は印刷範囲は固定で指定しています。ですがxlwingsには強力なrange範囲の拡張機能が備わっているので、ファイルごと(またはテーブルごとに)印刷範囲を柔軟に変えることも可能です。Rangeの詳しい使用方法はドキュメントを参照。
今回参考にしたページ・資料
Python API - xlwings Documentation