OpenOffice.orgのマクロを Pythonで記述して動かす(Calcでスケジュールカレンダーを生成)
「Pythonのカレンダーモジュールを用いる」で扱ったカレンダーのモジュールを用いたOpenOffice.org Calc向けのマクロを作成した。これを実行すると既存のシートの後ろに「2011年1月」から「2011年12月」までの12のシートが自動的に作成され、その中に「日付」と「予定」が日付順に縦方向に並び(日付については月ごとに全ての日付/曜日が自動的に入力される)、土日のみ色も付く。ただし、日本の祝日は強調されない。
予定の欄は全て空なので自由に書き込める(予定の内容は例として書き込んだもの)
最後の大晦日まで、年と月の値が入った12のシートが生成される
下のスクリプトは文字列オブジェクトにformat()を用いている関係でPython 2.6以上を対象としている。マクロは1つだけなので、それを実行する。
[任意]ファイル名: [OOoユーザディレクトリ]/user/Scripts/python/calc_gen_schedule_calendar.py ライセンス: GPL-3 (or lator)
# -*- mode: python; coding: utf-8; python-indent: 2 -*- # OpenOffice.org Calcでスケジュールカレンダーを生成 # version 20101220 # (C) 2010 kakurasan # Licensed under GPLv3+ import unohelper import calendar import uno class Config: """ 設定項目 """ year = 2011 class NotOOoCalcException (Exception): """ OOo Calcの中でマクロが呼ばれなかったときに発生する例外 """ pass class InvalidConfigException (Exception): """ 設定項目の値が不正なときに発生する例外 """ pass class Bridge (object): """ PythonとOOoの仲立ちをする各種オブジェクトと それを用いた幾つかの操作を提供 """ # enum定数(どれが選択されたかだけを示し、値に意味がないもの)は # uno.Enumオブジェクトとして得る # com.sun.star.table.CellHoriJustify.CENTERの場合は # uno.Enum ('com.sun.star.table.CellHoriJustify', 'CENTER')とする com_sun_star_table_CellHoriJustify_CENTER = uno.Enum ('com.sun.star.table.CellHoriJustify', 'CENTER') 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_infodialog (self, title='', message=''): """ 情報ダイアログを表示する http://api.openoffice.org/docs/common/ref/com/sun/star/awt/XMessageBoxFactory.html http://hermione.s41.xrea.com/pukiwiki/pukiwiki.php?OOoPython%2FOverView """ msgbox = self._toolkit.createMessageBox (self._window, uno.createUnoStruct ('com.sun.star.awt.Rectangle'), # ダイアログの種類を指定する文字列 # infobox,warningbox,errorbox, # querybox,messboxのいずれか 'infobox', 1, title, message) msgbox.execute () msgbox.dispose () 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 () # 設定値のチェック try: Config.year = int (Config.year) if Config.year < 1 or Config.year > 9999: self.run_errordialog (title='エラー', message='年({0})が無効な範囲の値です'.format (Config.year)) raise InvalidConfigException () except ValueError: self.run_errordialog (title='エラー', message='年({0})が無効です'.format (Config.year)) raise InvalidConfigException () # Calcの全シート # プロパティSheetsかメンバ関数getSheets() # http://api.openoffice.org/docs/common/ref/com/sun/star/sheet/XSpreadsheetDocument.html @property def sheets (self): return self._document.Sheets def m01_gen_schedule_calendar (): "OOo Calcで新規に12のシートから成るスケジュール記入型カレンダーを生成" try: calc = OOoCalc () except: return sheets = calc.sheets sheets_count_before = sheets.Count for month in range (12): # 新規シートを作成 sheetname = '{0}年{1}月'.format (Config.year, month + 1) # シートの存在をチェックする # 指定された名前のシートが既に存在していればTrue # http://api.openoffice.org/docs/common/ref/com/sun/star/container/XNameAccess.html if sheets.hasByName (sheetname): calc.run_errordialog (title='エラー', message='既にシート "{0}" が存在します'.format (sheetname)) return else: # 1番目の引数は名前 # 2番目の引数は追加位置(0は一番左に追加する) # http://api.openoffice.org/docs/common/ref/com/sun/star/sheet/XSpreadsheets.html try: sheets.insertNewByName (sheetname, sheets_count_before + month) except unohelper.RuntimeException: # 上限シート数を超えると例外unohelper.RuntimeExceptionが発生 calc.run_errordialog (title='エラー', message='シート数が上限に達したため\n新しいシートを追加できませんでした') return # ここから追加したシートに日付を追加していく sheet = sheets.getByIndex (sheets_count_before + month) # ヘッダ sheet.getCellByPosition (0, 0).Formula = '日付' sheet.getCellByPosition (1, 0).Formula = '予定' sheet.getCellRangeByPosition (0, 0, 1, 0).CellBackColor = 0xeaebec sheet.getCellRangeByPosition (0, 0, 1, 0).HoriJustify = Bridge.com_sun_star_table_CellHoriJustify_CENTER # 日付 wday = ['月', '火', '水', '木', '金', '土', '日'] day = 0 c = calendar.Calendar () # 既定では月曜日開始(月=0 日=7) for (i, d) in enumerate (c.itermonthdates (Config.year, month + 1)): if d.month == month + 1: cell = sheet.getCellByPosition (0, 1 + day) # 1足すのはヘッダ行の分 day += 1 cell.Formula = '{0}/{1} ({2})'.format (d.month, d.day, wday[i % 7]) if i % 7 == 5: # 土曜 cell.CellBackColor = 0xeeeeff cell.CharColor = 0x000066 elif i % 7 == 6: # 日曜 cell.CellBackColor = 0xffeeee cell.CharColor = 0x660000 # このタプルに名前を書いた関数のみマクロ選択ダイアログから実行できる # g_exportedScriptsを記述しない場合は全て実行可 g_exportedScripts = (m01_gen_schedule_calendar, )
(2010/12/20)OOoCalcオブジェクト生成時の例外の処理を微調整
年は初期値が2011年となっているが
class Config: year = 2011
の部分の値を変更することで他の年でも動作する。
関連:日付の自動生成を行う別の方法
適当なセルに「2011/1/1」のような書式の文字列(カレンダー上に存在しない日付は除く)を入力すると「1月1日」のような表示(セルの書式設定で変更可)になり、選択されているセルの右下の四角の部分を始点として下もしくは右にドラッグ・アンド・ドロップすると、数値と同様に日付の連番が作れる(書式は元のセルと同じものが作られる)。また、向きを逆にして左か上にすることでさかのぼった連番も作れる。
使用したバージョン:
- OpenOffice.org 3.2.1
- Python 2.6.6