2022年5月11日水曜日

Pythonでグラフなどのあるシートを同じExcelブック上で名前変更してコピーする方法

PythonでグラフなどのあるExcelシートを同じブック上でコピーしようとしたら色々手間がかかったので備忘録。

最初はopenpyxlを使おうと思ったが、文字や数値などのデータはコピーされるが、グラフや画像はコピーされない。openpyxlが対応していないのだ(2022年5月11日時点 openpyxl 3.0.9)。

で調べたら、こちらのページにExcelマクロを使うやり方が載っていた。
Pythonからpywin32でExcelマクロを実行してマクロでシートをコピーするというやり方。

でも、ならpywin32だけでも出来るんじゃないか?と思って書いたのが以下。

data_path=Excelファイルのファイル・パス
tab_name=コピー元のシートの名前
new_tab_name=コピーしたファイルの新しい名前
として、

import win32com.client

xlApp = win32com.client.Dispatch("Excel.Application")
book = xlApp.Workbooks.Open(data_path)
book.Worksheets(tab_name).Copy(After=book.Worksheets(tab_name))
xlApp.ActiveWorkBook.Worksheets(tab_name).name = new_tab_name
xlApp.ActiveWorkBook.Worksheets(new_tab_name).Move(Before = None, After = book.Worksheets(tab_name))
book.Save()
book.Close()

これを実行すると、
  1. pywin32でexcelファイルを開く。
  2. tab_nameというシートをtab_nameの後ろにコピーしようとするが、一つのブック内に同じシート名では追加できず、また、この時点では名前の変更ができないので、自動的にbook1というブックが作られそこにコピーされる。
  3. book1はアクティブなブックなので、「アクティブなブックにあるtab_nameというシート」を指定し、名前をnew_tab_nameに変更する。
  4. book1のnew_tab_nameというシートを元のブックのtab_nameというシートの後ろに移動する。移動の結果book1はシートが無くなるので消滅する。
  5. 元々のブックをセーブして閉じる
という流れで処理される。
これなら、Excelマクロを使わなくても、グラフや画像のあるシートを同じブック上で別名でコピー出来る。


(ただ、book1は明示的に開いたり閉じたりしてないのでプロセスが裏で残っているのでは?という不安はある。タスクマネージャーで見る分には大丈夫の様なんだけど…。)