OpenOffice.orgのマクロを Pythonで記述して動かす(Calcで整形されたカレンダーを生成)
「OpenOffice.orgのマクロを Pythonで記述して動かす(Calcでスケジュールカレンダーを生成)」とは異なり、今度は曜日が横に並んだ形のカレンダーを生成するOpenOffice.org Calc向けのマクロを作成した。
実行すると既存のシートの後ろに「2011年1月」から「2011年12月」までの12のシートが自動的に作成され、その中にカレンダーが書き込まれて前後の月の日付も薄い色で表示される。
今回も土日の日付に色が付いているが、日本の祝日は強調されない。また、セルは日付で埋まっており、予定などを書き込む場合は日付のセルの内容を上書きすることになる。
日曜日開始版
月曜日開始版
下のスクリプトは文字列オブジェクトにformat()を用いている関係でPython 2.6以上を対象としている。
[任意]ファイル名: [OOoユーザディレクトリ]/user/Scripts/python/calc_gen_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') # constant定数(名前から値に展開されるもの)は # uno.getConstantByName()で得る com_sun_star_awt_FontWeight_NORMAL = uno.getConstantByName ('com.sun.star.awt.FontWeight.NORMAL') com_sun_star_awt_FontWeight_BOLD = uno.getConstantByName ('com.sun.star.awt.FontWeight.BOLD') 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_calendar_from_sunday (): "OOo Calcで新規に12のシートから成るカレンダーを生成\n日曜日開始版" 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) # ヘッダ(曜日) for (i, name) in enumerate (['日', '月', '火', '水', '木', '金', '土']): cell = sheet.getCellByPosition (i, 0) cell.Formula = name cell.HoriJustify = Bridge.com_sun_star_table_CellHoriJustify_CENTER cell.CharWeight = Bridge.com_sun_star_awt_FontWeight_BOLD if i == 0: # 日曜 cell.CellBackColor = 0xffeeee cell.CharColor = 0x660000 elif i == 6: # 土曜 cell.CellBackColor = 0xeeeeff cell.CharColor = 0x000066 else: # 土日以外 if i % 2: # シマシマにする cell.CellBackColor = 0xf3f4f4 else: cell.CellBackColor = 0xe6e7e7 # 日付の追加 line = 1 # 行「2」から下 # 「6」を指定すると日曜開始のカレンダーとなる c = calendar.Calendar (6) # itermonthdates()が返すジェネレータを用いてループすると # その月のカレンダー上の開始曜日に合わせた前の月の日から # 終了曜日に合わせた後の月の日までが順番に返される # monthは0から11 for (i, d) in enumerate (c.itermonthdates (Config.year, month + 1)): cell = sheet.getCellByPosition (i % 7, line) if d.month == month + 1: # この月 cell.Formula = d.day if i % 7 == 0: # 日曜 cell.CharColor = 0x660000 elif i % 7 == 6: # 土曜 cell.CharColor = 0x000066 else: # 前後の月 # cell.Formulaとすると割り算の式になるのでcell.Stringにする cell.String = '{0}/{1}'.format (d.month, d.day) if i % 7 == 0: cell.CharColor = 0xccbbbb elif i % 7 == 6: cell.CharColor = 0xbbbbcc else: cell.CharColor = 0xc0c1c1 # いずれのセルも中央寄せにする cell.HoriJustify = Bridge.com_sun_star_table_CellHoriJustify_CENTER # 曜日が一周したら次の行へ if i % 7 == 6: line += 1 def m02_gen_calendar_from_monday (): "OOo Calcで新規に12のシートから成るカレンダーを生成\n月曜日開始版" 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) if sheets.hasByName (sheetname): calc.run_errordialog (title='エラー', message='既にシート "{0}" が存在します'.format (sheetname)) return else: try: sheets.insertNewByName (sheetname, sheets_count_before + month) except unohelper.RuntimeException: calc.run_errordialog (title='エラー', message='シート数が上限に達したため\n新しいシートを追加できませんでした') return sheet = sheets.getByIndex (sheets_count_before + month) for (i, name) in enumerate (['月', '火', '水', '木', '金', '土', '日']): cell = sheet.getCellByPosition (i, 0) cell.Formula = name cell.HoriJustify = Bridge.com_sun_star_table_CellHoriJustify_CENTER cell.CharWeight = Bridge.com_sun_star_awt_FontWeight_BOLD if i == 6: # 日曜 cell.CellBackColor = 0xffeeee cell.CharColor = 0x660000 elif i == 5: # 土曜 cell.CellBackColor = 0xeeeeff cell.CharColor = 0x000066 else: # 土日以外 if i % 2: cell.CellBackColor = 0xf3f4f4 else: cell.CellBackColor = 0xe6e7e7 line = 1 c = calendar.Calendar () # 既定値は0(月曜日開始) for (i, d) in enumerate (c.itermonthdates (Config.year, month + 1)): cell = sheet.getCellByPosition (i % 7, line) if d.month == month + 1: cell.Formula = d.day if i % 7 == 6: # 日曜 cell.CharColor = 0x660000 elif i % 7 == 5: # 土曜 cell.CharColor = 0x000066 else: cell.String = '{0}/{1}'.format (d.month, d.day) if i % 7 == 6: cell.CharColor = 0xccbbbb elif i % 7 == 5: cell.CharColor = 0xbbbbcc else: cell.CharColor = 0xc0c1c1 cell.HoriJustify = Bridge.com_sun_star_table_CellHoriJustify_CENTER if i % 7 == 6: line += 1 # このタプルに名前を書いた関数のみマクロ選択ダイアログから実行できる # g_exportedScriptsを記述しない場合は全て実行可 g_exportedScripts = (m01_gen_calendar_from_sunday, m02_gen_calendar_from_monday)
使用したバージョン:
- OpenOffice.org 3.2.1
- Python 2.6.6