Engineer as a Lifestyle @tenkoma

What We Find Changes Who We Become -- Peter Morville著『アンビエント・ファインダビリティ 』

win32comでExcel

こんどはこっちでExcelにアクセスしてみよう.Python本体の他にwin32all,あとMicrosoft Excelも必要.これが欠点.
win32comでExcelを操作する方法について扱っているページと言えばまずhttp://www.hlj.com/~tanoue/Python/Wdw/wpy1.htmlを見ることになるはず.このページ新しくブックを作る方法は書いてあるが,既存のブックを開く方法が書いてない.

準備

ファイルパスに日本語が入っている場合に対処するためにはスクリプトエンコーディングを変える必要がある.スクリプトファイルではファイルの最初に"# -*- coding:utf-8 -*-"でいいが,インタラクティブシェルで動かすときはsitecustomize.pyを所定の位置に置いてそのなかでエンコーディングを指定する必要がある.

import sys
sys.setdefaultencoding("utf-8")

これでインタラクティブシェルからsys.getdefaultencoding()して"utf-8"が返ってくればOK

xlsファイルを開く

import win32com.client
xlApp = win32com.client.Dispatch("Excel.Application")
xlApp.Workbooks.Open(r"C:\example.xls")

1行目はなんとなくわかるとして,2行目で変数に入っているのはExcelブック・シートなどにアクセスするマシンみたいなものと思っている.このなかにブックを複数持てる.
3行目でファイルを開いている.インタラクティブシェルでパスをコピーペーストするときなど"\"のエスケープがめんどくさいので文字列の最初にrをつけてRAW文字列にしてしまおう.これを忘れると意味不明なtracebackがでてきてハマる.Openしたファイルのオブジェクトは開いた順番でつけられる(たぶん)idかファイル名でアクセスできる.

>>> xlApp.Workbooks(1)
<COMObject <unknown>>
>>> xlApp.Workbooks(1).Name
u'example.xls'
>>> xlApp.Workbooks("example.xls").Name
u'example.xls'

xlAppで開かれているブックやそのなかのシートの名前を確認するコードはこんな感じ

>>> for i in xlApp.Workbooks("example.xls").Worksheets:
	print i.Name

	
hoge
Sheet2
Sheet3
>>> for i in xlApp.Workbooks:
	print i.Name

	
example.xls

単にWorkbookやWorksheetのオブジェクトをprintすると>と表示されてわかりにくい.ブックやシートのリストを作っておけば,あとで簡単にアクセスできる.あ,ディクショナリもいいね.keyがシート名で値がシートのオブジェクトに.
全体的にアクセス方法がPythonぽくないのでやりにくい.そんな手探り状態で最も役に立つ資料が例えばOfficeXPならC:\Program Files\Microsoft Office\Office10\1041\にあるVBAXL10.CHM
このWindowsヘルプファイルがないときは追加インストールが必要.いま操作した限りでは一階層下のオブジェクトにアクセスするのに"."でつなげるだけでいいみたい.

名前で簡単にブックやシートのオブジェクトを取り出すためのスクリプト

def booksdict(Workbooks):
	d ={}
	for book in Workbooks:
		d[book.Name]=(book,{})
		for sheet in book.Worksheets:
			d[book.Name][1][sheet.Name]=sheet
	return d

こんな感じで使えば.

>>> d = booksdict(xlApp.Workbooks)
>>> d
{u'example.xls': (<COMObject <unknown>>, {u'Sheet2': <COMObject <unknown>>, u'Sheet3': <COMObject <unknown>>, u'hoge': <COMObject <unknown>>})}
>>> d.keys()
[u'example.xls']
>>> d['example.xls'][1].keys()
[u'Sheet2', u'Sheet3', u'hoge']
>>> d['example.xls'][1]['hoge'].Range('A1:F6').Value
((56.0, 49.0, 11.0, 39.0, 71.0, 33.0), (21.0, 85.0, 7.0, 26.0, 51.0, 41.0), (68.0, 27.0, 54.0, 18.0, 84.0, 80.0), (26.0, 17.0, 58.0, 51.0, 7.0, 24.0), (77.0, 56.0, 29.0, 15.0, 80.0, 78.0), (94.0, 12.0, 60.0, 42.0, 38.0, 89.0))

example.xlsのhogeシートにアクセスしているというのがわかりやすくなったかも?(例で使ったexample.xlsはA1:F6に"=INT(RAND()*100)"で乱数を発生させた後コピー→形式を選択して貼り付け,値貼り付けをしています.)