OpenOffice.orgのマクロをPythonで記述して動かす(Calcのセル内容へのアクセスに関する追加メモ・ページ3/3)
「OpenOffice.orgのマクロをPythonで記述して動かす(Calcのセル内容へのアクセスに関する追加メモ・ページ2/3)」の続き。
同様な計算を繰り返す際の式について
「OpenOffice.orgのマクロをPythonで記述して動かす(Calcのセル内容へのアクセスについてとセル内容の操作に関する例)」の中で少し触れたが、例えば、CSV(コンマ区切り)表記で92,79,83,95 79,92,97,90 94,94,96,84
というデータがあったとして、それぞれの行の末尾に行ごとの合計を入れるとすると
92,79,83,95,=SUM(A1:D1) 79,92,97,90,=SUM(A2:D2) 94,94,96,84,=SUM(A3:D3)
となるが、マクロでこのような式を入れていく場合、各行ごとに関数(上の例ではSUM())の引数のセル名の数字部分に変数の値が入るようにしてループで処理する。
# 注意:別途、後述のクラス定義部分が動作に必要 def test(): "test" try: calc = OOoCalc() except NotOOoCalcException: return sheet = calc.active_sheet data = [[92, 79, 83, 95], [79, 92, 97, 90], [94, 94, 96, 84]] for (i, line) in enumerate(data): y = i + 1 for (j, item) in enumerate(line): # 各データを入れる sheet.getCellByPosition(j, i).Formula = item # SUM()を行ごとに入れる sheet.getCellByPosition(4, i).Formula = '=SUM(A%d:D%d)' % (y, y)
これを実行したときのE列の内容は
- E1(値は349): =SUM(A1:D1)
- E2(値は358): =SUM(A2:D2)
- E3(値は368): =SUM(A3:D3)
となる。
場合によっては、セル名を用いずにセルの座標のみを用いてセル名を得て処理したいことがあるが、そのときには表計算関数INDIRECT()とADDRESS()を組み合わせる。それぞれの関数の引数に関する詳細はヘルプが詳しいのでここでは扱わない。
# 注意:別途、後述のクラス定義部分が動作に必要 def test2(): "test2" try: calc = OOoCalc() except NotOOoCalcException: return sheet = calc.active_sheet sheetname = sheet.Name data = [[92, 79, 83, 95], [79, 92, 97, 90], [94, 94, 96, 84]] for (i, line) in enumerate(data): y = i + 1 for (j, item) in enumerate(line): sheet.getCellByPosition(j, i).Formula = item sheet.getCellByPosition(4, i).Formula = '=SUM(INDIRECT(ADDRESS(%d;1;4;"%s")):INDIRECT(ADDRESS(%d;4;4;"%s")))' % (y, sheetname, y, sheetname)
これをシート「Sheet1」上で実行したときのE列の内容は
- E1(値は349): =SUM(INDIRECT(ADDRESS(1,1,4,1,"Sheet1")):INDIRECT(ADDRESS(1,4,4,1,"Sheet1")))
- E2(値は358): =SUM(INDIRECT(ADDRESS(2,1,4,1,"Sheet1")):INDIRECT(ADDRESS(2,4,4,1,"Sheet1")))
- E3(値は368): =SUM(INDIRECT(ADDRESS(3,1,4,1,"Sheet1")):INDIRECT(ADDRESS(3,4,4,1,"Sheet1")))
となる。
この方法には
- セルの式を見たときにどこを指しているのかが分かりにくい
- シート名を引数にとる部分があるため、シート名を後で変更するとエラー(502)が出る
といった欠点もある。
上記2つの例をマクロとして実行するにはマクロ本体よりも手前(上)に以下の内容をコピペする。
# -*- mode: python; coding: utf-8 -*- import uno #import unohelper # このコードでは未使用 class NotOOoCalcException(Exception): """ OOo Calcの中でマクロが呼ばれなかったときに発生する例外 """ pass class Bridge(object): """ PythonとOOoの仲立ちをする各種オブジェクトと それを用いた幾つかの操作を提供 """ def __init__(self): """ 各種オブジェクトの取得 """ # http://api.openoffice.org/docs/common/ref/com/sun/star/script/provider/XScriptContext.html # http://api.openoffice.org/docs/common/ref/com/sun/star/uno/XComponentContext.html self._context = XSCRIPTCONTEXT.getComponentContext() # self._manager = self._context.ServiceManager # このコードでは未使用 self._desktop = XSCRIPTCONTEXT.getDesktop() self._document = XSCRIPTCONTEXT.getDocument() # http://api.openoffice.org/docs/common/ref/com/sun/star/frame/XDesktop.html self._frame = self._desktop.CurrentFrame # http://api.openoffice.org/docs/common/ref/com/sun/star/frame/XFrame.html self._window = self._frame.ContainerWindow self._toolkit = self._window.Toolkit def run_errordialog(self, title='', message=''): """ エラーダイアログを表示する http://api.openoffice.org/docs/common/ref/com/sun/star/awt/XMessageBoxFactory.html """ msgbox = self._toolkit.createMessageBox(self._window, uno.createUnoStruct('com.sun.star.awt.Rectangle'), 'errorbox', 1, title, message) msgbox.execute() msgbox.dispose() class OOoCalc(Bridge): """ OOo Calcの制御 BridgeをベースにCalcのサポート状態とシート一覧を追加したもの """ def __init__(self): Bridge.__init__(self) # 必須 # Calcの中から実行されたならTrue,それ以外ならFalse # http://api.openoffice.org/docs/common/ref/com/sun/star/lang/XServiceInfo.html if not self._document.supportsService('com.sun.star.sheet.SpreadsheetDocument'): self.run_errordialog(title='エラー', message='このマクロはOpenOffice.org Calcの中で実行してください') raise NotOOoCalcException() # http://api.openoffice.org/docs/common/ref/com/sun/star/frame/XModel.html self.__current_controller = self._document.CurrentController def get_active_sheet(self): return self.__current_controller.ActiveSheet def set_active_sheet(self, value): self.__current_controller.ActiveSheet = value active_sheet = property(get_active_sheet, set_active_sheet) @property def supported(self): return self.__supported # この後ろにマクロtest,test2をコピペ
使用したバージョン:
- OpenOffice.org(Go-oo) 3.1.1
- Python 2.6.4