あらきけいすけのメモ帳

あらきけいすけの雑記帳2

openpyxl を用いて結合セルの結合を解除し、データを各セルにばらまく

かなり苦労したのでメモ*1。このPythonコードの実行速度は下のVBAコードより圧倒的に速い。

#-*- coding: shift_jis -*-
import openpyxl

#元データのシート
wb = openpyxl.load_workbook('testIn.xlsx',data_only=True)
ws = wb['Sheet1']

#結合したセルの Range データを文字情報化して、バッファする
listMerged=[]
for rng in ws.merged_cells:
  listMerged.append(str(rng))

#セルの結合を解除し、左上の値を代入する
for strRng in listMerged:
  leftTop = (strRng.split(':'))[0]
  ws.unmerge_cells(strRng)
  for row in ws[strRng]:
    for cell in row:
      cell.value = ws[leftTop].value

#結果を保存する
wb.save(filename='testOut.xlsx')

ほぼ同じ動作の Excel VBA マクロ

Sub cellUnmergeDataSpread(r As Range)
    '
    ' 入力の r で決まる Range 内の結合セルデータを調べて、
    ' セルの結合を全部解除して、結合してた全てのセルにデータをばらまく
    '
    Dim o As Object, r0 As Range, v, i, j

    '[セル番号=>データの入ったセルのセル番号]の辞書の作成
    Set o = CreateObject("Scripting.Dictionary")
    For i = 1 To r.Rows.Count
        For j = 1 To r.Columns.Count
            Set r0 = r.Cells(i, j)
            v = r0.MergeArea.item(1).Address(0, 0)
            o.Add r0.Address, v
        Next j
    Next i
    r.unmerge '結合解除はここ

    For Each v In o '結合解除したセルに左上セルのデータのコピー
        r.Parent.Range(v).Value = r.Parent.Range(o.item(v)).Value
    Next v
End Sub

mergeする方は結合セルの探索にopenpyxl.worksheet.cell_range.CellRange*2を使うといいのかな?