openpyxl
バージョンごとの大きな変更2.3.5 | Apr 12, 2016 |
2.4.0 | Sep 15, 2016 |
2.5.0 | Jan 24, 2018 | セルのコピーができるようになった |
2.6.0 | Feb 7, 2019 | readでチャートを読み込むようになった(編集はできない)/ sharedStrings.xmlの生成を行わなくなった |
2.6.4 | Sep 25, 2019 | bug fixes |
3.0.0 | Sep 26, 2019 | Py2終了、Py3のみ対応 |
3.0.3 | Jan 11, 2020 | bug fixes |
はまったこと
2.3.5 => 2.4.1にしたらStyle周りのAPIが変わっていてスタイルが壊れた
2.3.5ではセルのコピーができない。2.5.0 以降にあげればできる
2.6.x 以降で sharedStrings.xml
が生成されなくなって困ったので、2.5.14にバージョンダウンした
Excelの行挿入でスタイルが壊れる
openpyxlで行を挿入すると、セル結合の状態、行の高さ、計算式は、元々の行番号に適用されるため、ずれる
Excelでは通常、追加してずれた行にスタイルも追従して適用される
pythondef hogehoge(worksheet, start_idx: int, add_row_count: int):
# 行追加の開始行から、追加する行数分だけ追加する
worksheet.insert_rows(idx=start_idx, amount=add_row_count)
# 追加した行にスタイルを適用する
_copy_styles(worksheet=worksheet, add_row_count=add_row_count)
# このあと、セル結合、行の高さなどを修正する必要がある
# 43行目の高さを14ピクセルにし、 (43 + 追加行 - 2)行目の高さを4ピクセルにする
# レイアウトの関係から、43行目だけ高さが短いので、移動先の高さを変更する
worksheet.row_dimensions[43].height = 14.25
worksheet.row_dimensions[43 + add_row_count].height = 4.5
def _copy_styles(worksheet, add_row_count: int):
""" セルのスタイルをコピーする
:param worksheet: Worksheetオブジェクト
:param add_row_count: 追加した行数
"""
org_cells = worksheet['A35:R35'] # 行追加の直前の行のスタイルを適用する
start_row_no = 36 # 行追加の開始行
for org_cell in org_cells[0]:
# 更新対象の列を取得
column = org_cell.column
# 列単位でスタイルを適用
for i in range(add_row_count):
row_no = start_row_no + i
# スタイルを適用する
new_cell = worksheet.cell(row=row_no, column=column)
new_cell.font = org_cell.font.copy()
new_cell.border = org_cell.border.copy()
new_cell.fill = org_cell.fill.copy()
new_cell.number_format = org_cell.number_format
new_cell.protection = org_cell.protection.copy()
new_cell.alignment = org_cell.alignment.copy()
Excelのセルのスタイルを複製する
pythondef get_style(cell: openpyxl.cell.Cell) -> openpyxl.styles.Style:
"""セルのスタイルをまとめて返す
cell.styleはUserWarningになる。
:param cell: 対象のセルオブジェクト
:return: スタイルオブジェクト
"""
ret = {
"font": cell.font.copy(),
"fill": cell.fill.copy(),
"border": cell.border.copy(),
"alignment": cell.alignment.copy(),
"number_format": cell.number_format,
"protection": cell.protection.copy(),
}
return ret
def copy_cell(dst_cell: openpyxl.cell.Cell, src_cell: openpyxl.cell.Cell):
"""セルの値とスタイルをコピーする
:param dst_cell: コピー先のセルオブジェクト
:param src_cell: コピー元のセルオブジェクト
"""
dst_cell.value = src_cell.value
st = get_style(src_cell)
dst_cell.font = st.get("font", None)
dst_cell.fill = st.get("fill", None)
dst_cell.border = st.get("border", None)
dst_cell.alignment = st.get("alignment", None)
dst_cell.number_format = st.get("number_format", None)
dst_cell.protection = st.get("protection", None)
return dst_cell
Excelのセル結合でExcelファイルが壊れる
openpyxl (2.6.4)
セル結合で、結合対象セルの一部が既に別のセルと結合されている場合に発生
エラーにならずファイルも作成されますが、MS Excel で開くと破損ファイルになる
Excelの印刷領域設定
python
# 印刷領域を設定
worksheet.print_area = "A1:S{}".format(default_max_row + add_row_count)
# 1ページにする
worksheet.sheet_properties.pageSetUpPr = PageSetupProperties(fitToPage=True, autoPageBreaks=False)
Excel上でマクロ記録を行って修正するプロパティを見つけ、openpyxlの公式で探した
Excelの画像が消える1
Pillowが環境にインストールされていないと、画像が消える
pythonimport openpyxl
o = openpyxl.open('sample.xlsx')
o.save('foo.xlsx')
このコードをPillowあり、なし、環境で実行しすると以下の結果になる
Pillowなし環境: 画像が消えた、警告等は表示されない
Pillowあり環境: 画像が維持された
Excelの画像が消える2
wmf(ウインドウズメタファイル)形式の画像は、消える
Excel上で画像を右クリックして、メニューに「図の編集」が表示されるものが wmf形式
対処方法としては、wmf形式 の画像を通常の画像に置き換える
Excelの画像が消える3
元のExcelにshapes, drawingsが含まれていると、全てのshapeや画像が消える
画像が巻き添えで消えてしまうのが悲しい
shapes, drawingsが一つでもあると、以下のメッセージが表示される
UserWarning: DrawingML support is incomplete and limited to charts and images only. Shapes and drawings will be lost.
対処方法としては、shapes, drawingsを使わない