Excel操作その後

じっくり調べたら単にオブジェクトが解放されていないだけという良くある話でした。参考までに動作するサンプルをあげておきます。

画像ファイルをExcel2007のワークブックに変換するスクリプト

import sys
import clr
clr.AddReference('System.Drawing')
clr.AddReference('Microsoft.Office.Interop.Excel')
from Microsoft.Office.Interop import Excel
from System.Runtime.InteropServices import Marshal
from System.Drawing import Bitmap,Color

def bmp2xlsx(path):
    """Excel2007を前提にしているので画像サイズチェックは入れてない"""
    bmp = Bitmap(str(path))
    app = Excel.ApplicationClass()
    app.Visible = True
    wbs = app.Workbooks
    book = wbs.Add()
    wss = book.Worksheets
    sheet = wss[1]
    cells = sheet.Cells
    begin = cells[1,1]
    end = cells[bmp.Height,bmp.Width]
    r = sheet.Range[begin, end]
    r.RowHeight = 0.75
    r.ColumnWidth = 0.08
    for y in xrange(bmp.Height):
        for x in xrange(bmp.Width):
            cell = r[y+1, x+1]
            interior = cell.Interior
            c = bmp.GetPixel(x, y)
            # c.ToArgb()は使えない
            interior.Color = c.B << 16 | c.G << 8 | c.R
            Marshal.ReleaseComObject(interior)
            interior = None
            Marshal.ReleaseComObject(cell)
            cell = None
    book.SaveAs(path + ".xlsx")
    book.Close()
    # 解放が面倒・・・
    Marshal.ReleaseComObject(r)
    r = None
    Marshal.ReleaseComObject(end)
    end = None
    Marshal.ReleaseComObject(begin)
    begin = None
    Marshal.ReleaseComObject(cells)
    cells = None
    Marshal.ReleaseComObject(sheet)
    sheet = None
    Marshal.ReleaseComObject(wss)
    wss = None
    Marshal.ReleaseComObject(book)
    book = None
    Marshal.ReleaseComObject(wbs)
    wbs = None
    app.Quit()
    Marshal.ReleaseComObject(app)
    app = None
    bmp.Dispose()
    bmp = None

if __name__ == '__main__':
    import sys
    if len(sys.argv) > 1:
        bmp2xlsx(sys.argv[1])

COMオブジェクトはMarshal.ReleaseComObjectを使って徹底的に開放しないとダメなんですね。