試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

OpenOffice.orgのマクロをPythonで記述して動かす(Calcのシート追加に関するメモとシート追加のコード例)

OpenOffice.orgのマクロをPythonで記述して動かす(Calc上でマクロが動作しているかのチェックと全シートのオブジェクトの取得に関するメモ)」の続き。

シート操作

シート名が存在しているかをチェックする

全シートを含むオブジェクトのメンバ関数hasByName()を用いると、既存のシート一覧からその名前のシートが存在している場合にTrue,存在しなければFalseを返す。これを用いると、シートを追加する処理の前にチェックを行うことができる。

新しくシートを追加

同オブジェクトのメンバ関数insertNewByName()を用いると、現在のドキュメントに新しくシートを追加する。1番目の引数が名前で2番目の引数が追加する位置となり、位置は0番(一番左)から始まる整数となる。
シート数には上限*1があるため、既にこの数だけシートが存在する場合は失敗する。その際には例外unohelper.RuntimeExceptionが発生するが、Pythonのtry-except構文で例外処理をする場合にはモジュールunohelperをインポートする必要がある。

import unohelper

...

def macroname():
  ...
  try:
    [全シートのオブジェクト].insertNewByName([シート名], [位置])
  except unohelper.RuntimeException:
    # ここに失敗したときの処理を記述


# もしくは

from unohelper import RuntimeException

...

def macroname():
  ...
  try:
    [全シートのオブジェクト].insertNewByName([シート名], [位置])
  except RuntimeException:
    # ここに失敗したときの処理を記述
シート数の取得

同オブジェクトのプロパティCountかメンバ関数getCount()により、現在のドキュメントのシート数が戻り値として得られる。
シートを右側に追加したい場合にはこの値を利用してinsertNewByName()の2番目の引数に追加位置をうまく指定する。

コード例

OpenOffice.orgのマクロをPythonで記述して動かす(Calc上でマクロが動作しているかのチェックと全シートのオブジェクトの取得に関するメモ)」と本記事の内容を踏まえた上でのコード例を貼り付ける。
(2010/4/8)このコードの改善版を「OpenOffice.orgのマクロをPythonで記述して動かす(Calc上でマクロが動作しているかのチェックを改善)」に貼り付けた。
[任意]ファイル名: [OOoユーザディレクトリ]/user/Scripts/python/calc_insert_sheet.py

# -*- mode: python; coding: utf-8 -*-

import uno
import unohelper

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_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
    self.__supported = self._document.supportsService('com.sun.star.sheet.SpreadsheetDocument')
    if self.__supported:
      # Calcの全シート
      # プロパティSheetsかメンバ関数getSheets()
      # http://api.openoffice.org/docs/common/ref/com/sun/star/sheet/XSpreadsheetDocument.html
      self.__sheets = self._document.Sheets
  @property
  def supported(self): return self.__supported
  @property
  def sheets(self): return self.__sheets


def m01_add_sheet():
  "OOo Calcでシート「新しいシート」を一番左に追加"
  calc = OOoCalc()
  # Calcの中かどうかをチェックする
  if not calc.supported:
    calc.run_errordialog(title='エラー', message='このマクロはOpenOffice.org Calcの中で実行してください')
    return
  else:
    # 新規シートを作成
    sheetname = '新しいシート'
    # シートの存在をチェックする
    # 指定された名前のシートが既に存在していればTrue
    # http://api.openoffice.org/docs/common/ref/com/sun/star/container/XNameAccess.html
    if calc.sheets.hasByName(sheetname):
      calc.run_errordialog(title='エラー', message='既にシート "%s" が存在します' % sheetname)
    else:
      # 1番目の引数は名前
      # 2番目の引数は追加位置(0は一番左に追加する)
      # http://api.openoffice.org/docs/common/ref/com/sun/star/sheet/XSpreadsheets.html
      try:
        calc.sheets.insertNewByName(sheetname, 0)
        # ここでは毎回ダイアログを出すことにする
        calc.run_infodialog(title='シート追加成功', message='シート "%s" を追加しました' % sheetname)
      except unohelper.RuntimeException:
        # 上限シート数を超えると例外unohelper.RuntimeExceptionが発生
        calc.run_errordialog(title='エラー', message='シート数が上限に達したため\n新しいシートを追加できませんでした')
        return

def m02_add_5_sheets():
  "OOo Calcでシート「シート [番号]」を5つ続けて右側に追加"
  calc = OOoCalc()
  if not calc.supported:
    calc.run_errordialog(title='エラー', message='このマクロはOpenOffice.org Calcの中で実行してください')
    return
  else:
    # 現在のシート数を取得
    # http://api.openoffice.org/docs/common/ref/com/sun/star/container/XIndexAccess.html
    # プロパティCountかメンバ関数getCount()
    cnt = calc.sheets.Count
    for i in range(5):  # iは0から4
      sheetname = 'シート %d' % (i + 1,)
      if calc.sheets.hasByName(sheetname):
        calc.run_errordialog(title='エラー', message='既にシート "%s" が存在します' % sheetname)
        return
      else:
        # 追加シートが一番右に来るように2番目の引数を調整
        try:
          calc.sheets.insertNewByName(sheetname, i + cnt)
          calc.run_infodialog(title='シート追加成功', message='シート "%s" を追加しました' % sheetname)
        except unohelper.RuntimeException:
          calc.run_errordialog(title='エラー', message='シート数が上限に達したため\n新しいシートを追加できませんでした')
          return

def m03_add_300_sheets():
  "OOo Calcでシート「シート [番号]」を300個続けて右側に追加(しようとする)"
  calc = OOoCalc()
  if not calc.supported:
    calc.run_errordialog(title='エラー', message='このマクロはOpenOffice.org Calcの中で実行してください')
    return
  else:
    cnt = calc.sheets.Count
    for i in range(300):
      sheetname = 'シート %d' % (i + 1,)
      if calc.sheets.hasByName(sheetname):
        calc.run_errordialog(title='エラー', message='既にシート "%s" が存在します' % sheetname)
        return
      else:
        try:
          calc.sheets.insertNewByName(sheetname, i + cnt)
        except unohelper.RuntimeException:
          calc.run_errordialog(title='エラー', message='シート数が上限に達したため\n新しいシートを追加できませんでした')
          return


# このタプルに名前を書いた関数のみマクロ選択ダイアログから実行できる
# g_exportedScriptsを記述しない場合は全て実行可
g_exportedScripts = (m01_add_sheet, m02_add_5_sheets, m03_add_300_sheets)

以下は実行内容となる。

  • 1番目のマクロでは一番左にシート「新しいシート」を追加・ダイアログで結果表示
  • 2番目のマクロでは「シート [番号]」を5番まで一番右に追加・1つごとにダイアログで結果表示
  • 2番目のマクロでは「シート [番号]」を300番まで一番右に追加しようとする・シート数上限により失敗したらダイアログを表示


Calc以外で実行されたときのエラーダイアログ

シート追加時のダイアログ

シート数上限で追加に失敗したときのエラーダイアログ

関連記事:

使用したバージョン:

*1:バージョン3.1系の時点では256