
これまで、Pythonの代表的な外部ライブラリであるopenpyxlを使用してPythonからExcelファイルを読み書きする方法については以下のように過去に何回か記載してきました。
通常のExcelファイル(xlsxファイルなど)についてはこれで問題ありませんでした。
ところが今回、Excelファイルの中でも別のファイル形式になるマクロが組み込まれているファイル(xlsmファイル)の読み書きをしようとした時に1つ引っかかったところがあったので備忘録として書き残しておきます。
マクロが組み込まれているファイル(xlsmファイル)の場合にも、そのExcelファイルからの読み込みについては特に問題はなかったのですが、同じファイルに書き込みをしようとした時にそのままではエラーが出てうまくいきませんでした。
以前記載した読み書き方法例は以下のようなものでした。
この例のようにすべてxlsxファイルの場合はこれで問題ありませんでした。
excelreadwrite2.py
import openpyxl
### wb = openpyxl.load_workbook(ファイル名)
wb = openpyxl.load_workbook(r"C:\abc.xlsx")
wb2 = openpyxl.load_workbook(r"C:\abc2.xlsx")
### ws = wb[シート名]
ws = wb["def"]
ws2 = wb2["def2"]
### 辞書型変数dict_text 宣言、初期化(要素としてキー'英語'、'数学'、'国語'を持つ)
dict_text = {"英語":0,"数学":0,"国語":0}
### xの値でループ(xの値を2から最大行番号までループ)
for x in range(2, ws.max_row ):
#abc.xlsxファイルのdefシートから各科目ごとに全員の合計点を計算
dict_text["英語"]= dict_text["英語"] + ws.cell(x, 2).value
dict_text["数学"]= dict_text["数学"] + ws.cell(x, 3).value
dict_text["国語"]= dict_text["国語"] + ws.cell(x, 4).value
#各科目ごとに平均点を求めて、abc2.xlsxファイルのdef2シートの平均点欄へ書込み
ws2.cell(2, 2).value = dict_text["英語"] / (ws.max_row - 1)
ws2.cell(2, 3).value = dict_text["数学"] / (ws.max_row - 1)
ws2.cell(2, 4).value = dict_text["国語"] / (ws.max_row - 1)
wb2.save(r"C:\abc2.xlsx")
ただし、ファイル形式がxlsmファイルとなった場合にはこのままではエラーとなりますので一部変更しなければなりません。
この場合の読み書き方法記載例としては以下のようなものになります。
excelreadwrite3.py
import openpyxl ### wb = openpyxl.load_workbook(ファイル名) wb = openpyxl.load_workbook(r"C:\abc.xlsm") wb2 = openpyxl.load_workbook(r"C:\abc2.xlsm", keep_vba=True) ### ws = wb[シート名] ws = wb["def"] ws2 = wb2["def2"] ### 辞書型変数dict_text 宣言、初期化(要素としてキー'英語'、'数学'、'国語'を持つ) dict_text = {"英語":0,"数学":0,"国語":0} ### xの値でループ(xの値を2から最大行番号までループ) for x in range(2, ws.max_row ): #abc.xlsxファイルのdefシートから各科目ごとに全員の合計点を計算 dict_text["英語"]= dict_text["英語"] + ws.cell(x, 2).value dict_text["数学"]= dict_text["数学"] + ws.cell(x, 3).value dict_text["国語"]= dict_text["国語"] + ws.cell(x, 4).value #各科目ごとに平均点を求めて、abc2.xlsxファイルのdef2シートの平均点欄へ書込み ws2.cell(2, 2).value = dict_text["英語"] / (ws.max_row - 1) ws2.cell(2, 3).value = dict_text["数学"] / (ws.max_row - 1) ws2.cell(2, 4).value = dict_text["国語"] / (ws.max_row - 1) wb2.save(r"C:\abc2.xlsm")
読み込み側のファイルが「abc.xlsm」、そこから処理をして結果を書き込む側のファイルが「abc2.xlsm」とすると、読み込み側のファイルをロードする時は前と同じでも問題ないのですが、書き込み側のファイルのロード時は、
wb2 = openpyxl.load_workbook(r"C:\abc2.xlsm", keep_vba=True)
のように最後に「, keep_vba=True」を追加しなければなりませんでした。
名前の通りかもしれませんが、vbaを保持したまま書き込む場合には、読み込み時にkeep_vbaをTrueにして読み込まなければならないということです。
なかなか一筋縄ではいかないものです。
また、PythonやSeleniumの活用に必要となりそうな内容についてこれまで記載してきた記事を一覧として以下にまとめましたのでよかったらご参照ください。
関連記事:
【selenium 備忘録】ボタンクリックで複数の新規ウインドウを開いた時新規ウインドウをアクティブにできなかった場合の対処方法例 - Django Girls and Boys 備忘録
【python】実行ファイル(EXEファイル)作成手順 - Django Girls and Boys 備忘録
【Python カレントディレクトリ取得】Excelファイル指定を使った簡単な例記載 - Django Girls and Boys 備忘録
【Python】キーボード、キー入力判定方法 - Django Girls and Boys 備忘録
【Python】keyboardライブラリでのキー入力検出に使用可能なキーの種類 - Django Girls and Boys 備忘録
【PythonでのExcelファイル読み書き方法】ファイルオープンしているファイル(アクティブファイル)への書込方法 - Django Girls and Boys 備忘録
【PythonからWeb操作】selenium、各ブラウザ用ドライバーの最新バージョン確認、ダウンロード場所 - Django Girls and Boys 備忘録
【Python Selenium】ブラウザ用ドライバーのダウンロードとインストール - Django Girls and Boys 備忘録
【Python Selenium】ブラウザ用ドライバーのインストール、設定とWebサイトへのアクセス方法 - Django Girls and Boys 備忘録