はじめに
PythonでExcelを操作できるopenpyxlを使用して,全行・全列のループ処理時の結合セルの扱いについての注意点,備忘録です.
動作環境
- Python 3.12.0
- openpyxl 3.1.2
openpyxlはpipを使用してインストールできます.
pip install openpyxl
問題点
サンプルとして,下図の表を扱う場合を考えます.
B列の「A/B」欄を全て(B2~B12)"A"に変更したい場合,結合セルを考慮せずに記述すると以下のようになります.
最大行の取り方は「openpyxlでExcelの最終行を取得する際に気を付けること」を参考.
import openpyxl as px
excelFile = r"C:\Book1.xlsx"
wb = px.load_workbook(excelFile)
ws = wb.worksheets[0]
max = ws.max_row
for i in range(2, max+1):
ws.cell(row = i, column = 2).value = "A"
wb.save(excelFile)
wb.close()
上記のスクリプトを実行すると,次のAttributeError
が発生します.
AttributeError: 'MergedCell' object attribute 'value' is read-only
エラーコードを読んでわかる通り,MergedCell(結合セル)型のvalue属性は読み出し専用であって書き込みはできません.
サンプルの表では,B5,6 と B10,11 が結合されており,そこに表示されている値を持っているのは B5 と B10 のセルであり,B6 と B11 ではありません.
セルを結合すると,結合した範囲の左上のセル以外のすべてのセルがワークシートから削除されます.結合されたセルの境界情報を保持するため,結合されたセルの境界セルはNone
の値を持つ結合セル(今回の例ではB6,B11)として作成されます.B列をループで出力すると次のようになります.
2 A
3 A
4 A
5 A
6 None
7 A
8 B
9 B
10 B
11 None
12 B
ここで,ループ処理によって "B6,B11のセルの値を書き換える" というコードが実行された場合,上述の設計上,read-only
なのは自然な動きだと思います.
解決策
結合セルの判定を追加して,AttributeError
を回避します.
import openpyxl as px
excelFile = r"C:\Book1.xlsx"
wb = px.load_workbook(excelFile)
ws = wb.worksheets[0]
max = ws.max_row
for i in range(2, max+1):
typeCell = isinstance(ws.cell(row = i, column = 2), px.cell.cell.MergedCell)
if not typeCell:
ws.cell(row = i, column = 2).value = "A"
wb.save(excelFile)
wb.close()
isinstance
関数でセルがMergedCell型か判定し,typeCell
にはBool値(True / False)が格納されます.
not
演算子を使用することで,条件分岐では書き換え可能なセル(typeCell == False
)のみ,処理を行うことができます.