Pythonで複数のエクセルシートを自動印刷!
※この記事は、すでに閉じた私の別ブログ「ブラック企業の文系サラリーマンがPythonを駆使して定時退社」に以前掲載していたものを転載したものです。
マクロなら簡単だけど、Pythonだと「Python、エクセル、印刷」と検索してもいまいち、ずばり!な答えが見つからなかったので、サンプルコードを載せます。
これさえできれば、今後の事務仕事でどんなタイプの仕事をすることになっても、役立つはずです。
ポイントは
・ws.active=シート番号
・ws.sheet_view.tabSelected = False
アクティブなシートを明示して、タブを選択する。
これさえできればOK。
【以下、サンプルコード】
# OSの機能を使うためのライブラリ import os.path import time import win32api import win32print # エクセルを扱うためのライブラリをインポート import openpyxl # exeファイルに引数を設定する import argparse # 1. argparseをインポート #職場のほかの人にexe化したものを渡すときは、別途バッチファイルを作って渡すと #便利かと思うので書いています。 #バッチファイルの実行時に、引数を渡すため、オブジェクトを作る parser = argparse.ArgumentParser(description='このプログラムの説明(なくてもOK)') # 2. パーサを作る # parser.add_argumentで受け取る引数を追加していく # 必須の引数を追加(バッチ実行するフォルダのパスを渡す引数) parser.add_argument('current_dir', help='この引数の説明(バッチファイルを実行したフォルダを渡す)') # 引数を解析 以後、args.current_dirで入力した引数を引用できる args = parser.parse_args() # 実行したファイルがあるフォルダに読み込みたいエクセルを置き # そのファイルパスを作成 conf_dir_path = os.getcwd() conf_file_path = os.path.join(args.current_dir, 'test.xlsx') # 印刷する関数 win32api.ShellExecuteを使用して # 通常使うプリンターから出力する def PrintOut(): win32api.ShellExecute( 0, "print", conf_file_path, "/c:""%s" % win32print.GetDefaultPrinter(), ".", 0 ) # エクセルを開く wb = openpyxl.load_workbook(conf_file_path) # 一度、すべてのシートをtablesectedをFalseにして # アクティブなシートは0番目であると、明示する # そうしないと、前回保存した際のシートが選択されたままになってしまい # 意図しないシートが印刷されてしまいます # すべてのシート名を取得 wsall = wb.sheetnames # for文ですべてのシートtablesectedプロパティをFalseにして # どのシートも選択してない状態をつくる for s in wsall: #各シートをfor文で渡して ws = wb[s] #それらについて、すべてtablesectedプロパティをFalseにする ws.sheet_view.tabSelected = False # ここで一旦保存し、閉じて、どのシートも選択してない状態が完成 wb.save(conf_file_path) wb.close() # そして再び開く wb = openpyxl.load_workbook(conf_file_path) #これで、0番目=一番左のシートが選択された状態で開く。 # for文やif文で印刷したいワークーを指定する # ベタ打ちでもなんでもOK # 以下は、3番目と4番目シートを印刷する場合のfor文 for i in range(2,4): #ワークシートを番号で指定(一番左が0) ws = wb.worksheets[i] #今のシートがアクティブであると明示する。これ重要 wb.active = i #tabselrectedプロパティをTrueにして、選択状態を維持する ws.sheet_view.tabSelected = True #選択した状態で一度保存する。 #保存しないと、保存前の選択状態で印刷されてしまうので注意 wb.save(conf_file_path) #上で定義したプリントアウト関数を実行 PrintOut() #ワークブックを閉じる wb.close() print('実行されました') time.sleep(1)
【使うライブラリ】
・openpyxl
注意点:一番左のシートインデックス番号はゼロとなるので注意
ちなみにxlrdの場合は一番左のシートが1になります。
【初心者がはまるポイント】
エクセルを自分で操作するときに複数シートを選択する際は
シートのタブをctrlを押しながら複数クリックすると思います。
その動作をopenpyxlで実現するにはどうするか、という視点が大事で、
その手動での感覚と、pythonのコード感覚にズレがあるので、うまくいかない。
・ws.sheet_view.tabSelected = False
をいったんすべてのシートで実行して
なにもシートが選択されていない状態を作る。
通常、エクセルを開いた時にはすでに何かしらのシートが選択されています。
その状態からスタートすると、プログラマーの意図しないシートが最初から選択されているので、
「意図しないシートが勝手に印刷されるよー>< ぴえん」
という状態になってしまいます。
ですので、このワンステップが重要。
・ws.active=シート番号
でいまアクティブにしているシートを明示する
マウスをつかって、何かしらのシートを選択した状態がこれです。
シートを選択しただけで、まだ何もしてません。
・ws.sheet_view.tabSelected = True
任意のタブを選択する
CTRLを押しながら、シートのタブをクリックした状態がこれです。
これを印刷したいシートすべてに実行した状態が
「複数シートをctrlを押しつつクリックして選択した状態」
というわけです。
・win32api.ShellExecute(0,"print",conf_file_path,"/c:""%s" %win32print.GetDefaultPrinter(),".",0)
のwin32apiを使って、印刷します。
残念ながら、openpyxlにはws.print()というコードはないので、
こうするしかありません。