with statement
IronPython2.0でwithが使えないと思っていたのですが、実は対話型コンソールだとダメでファイルから実行する分にはOKでした。
http://d.hatena.ne.jp/akiramei/20070929/1191045521
↑ってことで、これをwithを使って書き直してみます。
from __future__ import with_statement from contextlib import contextmanager, nested import sys, 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 @contextmanager def auto(comobj): """COMオブジェクトを自動的に開放する""" try: yield comobj finally: Marshal.ReleaseComObject(comobj) def bmp2xlsx(path): bmp = Bitmap(str(path)) with auto(Excel.ApplicationClass()) as app: app.Visible = True with auto(app.Workbooks) as wbs: with auto(wbs.Add()) as wb: with auto(wb.Worksheets) as wss: with auto(wss[1]) as ws: with auto(ws.Cells) as cells: with nested(auto(cells[1,1]), auto(cells[bmp.Height,bmp.Width])) as (begin, end): with auto(ws.Range[begin, end]) as r: r.RowHeight = 0.75 r.ColumnWidth = 0.08 for y in xrange(bmp.Height): for x in xrange(bmp.Width): with auto(r[y+1, x+1]) as cell: with auto(cell.Interior) as interior: c = bmp.GetPixel(x, y) interior.Color = c.B << 16 | c.G << 8 | c.R wb.SaveAs(path + ".xlsx") wb.Close() app.Quit() if __name__ == '__main__': if len(sys.argv) > 1: bmp2xlsx(sys.argv[1])
一応、短くなっていますが、ネストが深いのがちょっと・・・