Pythonでマクロ(9):Sheetのイヴェントを処理する

LibreOfficeのCalcのシートで発生するイヴェントには様々なものがあるが、ここではその一つである「セルをマウスでダブルクリック」で起こるイヴェントを処理してみる。

意図したことは「シート上の任意のセルをマウスでダブルクリックするとそのセルの背景色が赤に変わる」である。

【準備】
Calcのシート名を右マウスでクリックすると設定メニュが出る。その一つの「シートイベント」を選択する。イベントの種類を対応するイヴェント処理マクロを繋げる表のなかで「マウスでダブルクリック」を選択。マクロ欄で対応するマクロ名を選択する。

【マクロ】


#coding: utf-8
import uno
import screen_io as ui

doc = XSCRIPTCONTEXT.getDocument()
sheet = doc.Sheets[0]
#
def OnDoubleClicked(event):
  CellAddress = event.getCellAddress()
  Row = CellAddress.Row
  Column = CellAddress.Column
  msg =  str(Row) + '   ' + str(Column) 
  cell = sheet.getCellByPosition(Column, Row)
  cell.CellBackColor = 0xff0000
  ui.Print(msg)
  return

 

Pythonでマクロ(8):チェックボックスを使ってみる

チェックボックスは多数の選択肢がありそれから複数を選択するコントロールである。よくアンケートなどで見かけるもの。フォームのコントロールにもチェックボックスがあるので使ってみた。多数の選択肢をきれいに配置することに手数がかかる。この点はフォームを使わずにCalc画面で直接コントロールを配置する方が楽である。フォームのよいところは細かな制御ができることである。今回は8個のチェックボックス、2個のボタンをフォームに配置した。

【フォームの画像】

チェックボックスの一例

ボタン「確認」は選択した結果をシートへ反映されるため、ボタン「リセット」は選択した結果を廃棄し無選択の状態にするためのものである。

【マクロ】


#coding: utf-8
import uno
import screen_io as ui
import unohelper
from com.sun.star.awt import XActionListener

class FinishedListener(unohelper.Base, XActionListener):
  def __init__(self, ckbxs, sheet):
    self.ckbxs = ckbxs
  def actionPerformed(self, evnt):
    for ckbx in self.ckbxs:
      print(ckbx.State)

class ResetListener(unohelper.Base, XActionListener):
  def __init__(self, ckbxs):
    self.ckbxs = ckbxs
  def actionPerformed(self, evnt):
    for ckbx in self.ckbxs:
      ckbx.State=0

def createDialog():
  ctx = XSCRIPTCONTEXT.getComponentContext()
  smgr = ctx.getServiceManager()
  dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
  dialog = dp.createDialog("vnd.sun.star.script:Standard.Dialog4?location=application")
  sheet = 0
#コントロールの登録
  cmdbtn1 = dialog.getControl("CommandButton1") 
  cmdbtn2 = dialog.getControl("CommandButton2")
  ckbx1 = dialog.getControl("CheckBox1")
  ckbx2 = dialog.getControl("CheckBox2")
  ckbx3 = dialog.getControl("CheckBox3")
  ckbx4 = dialog.getControl("CheckBox4")
  ckbx5 = dialog.getControl("CheckBox5")
  ckbx6 = dialog.getControl("CheckBox6")
  ckbx7 = dialog.getControl("CheckBox7")
  ckbx8 = dialog.getControl("CheckBox8")
  ckbxs = (ckbx1, ckbx2, ckbx3, ckbx4, ckbx5, ckbx6, ckbx7, ckbx8)
#エヴェント監視(ボタンが押されたとき)
  btn1_listener = FinishedListener(ckbxs, sheet)
  cmdbtn1.addActionListener(btn1_listener)
  btn2_listener = ResetListener(ckbxs)
  cmdbtn2.addActionListener(btn2_listener)
  dialog.execute()
  dialog.dispose()

 

Pythonでマクロ(7):誕生日の入力を日付フィールドを使って

ダイアログのコントロール(部品)に日付フィールドというものがある。形式に従って日付けを入力すると年、月、日に自動的に分解しくれる。

作例では誕生日を入力して<Enter>キーを入力すると入力の終わりを意味し結果はCalcのシートに表示される。

【ダイアログ上の日付フィールド】

作例の入力フォーム

【マクロ】


#coding: utf-8
import uno
import screen_io as ui
import unohelper
from com.sun.star.awt import XKeyListener

class MyKeyListener(unohelper.Base, XKeyListener):
  def __init__(self, sheet, datef1):
    self.sheet = sheet
    self.datef1 = datef1
    self.row = 0
  def keyPressed( self,  event ):
    k = event.KeyCode
    c = event.KeyChar.value 
    mods = event.Modifiers
    # mods are additive
    # 0 - None
    # 1 - Shift
    # 2 - Ctrl
    # 4 - Alt
    # 8 - Super_R
    print(k, c, mods)
    if k == 1280:  #Enterキー
      #print(self.datef1.IsDate)
      year = self.datef1.Date.Year
      month = self.datef1.Date.Month
      day = self.datef1.Date.Day
      #表への書き出し
      self.row+=1
      print(self.row)
      print(year, month, day)
      self.sheet.getCellByPosition(0,self.row).Value=year
      self.sheet.getCellByPosition(1,self.row).Value=month
      self.sheet.getCellByPosition(2,self.row).Value=day

def createDialog():
  ctx = XSCRIPTCONTEXT.getComponentContext()
  smgr = ctx.getServiceManager()
  dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
  dialog = dp.createDialog("vnd.sun.star.script:Standard.Dialog3?location=application")
#表
  doc = XSCRIPTCONTEXT.getDocument()
  sheet = doc.Sheets[0]
#コントロールの登録
  datef1 =  dialog.getControl("DateField1")
#エヴェント監視(Enterキーを検出)
  datef1_listener = MyKeyListener(sheet, datef1)
  datef1.addKeyListener(datef1_listener)
  dialog.execute()
  dialog.dispose()

<\div>

  • <Enter>キーの入力はイヴェントとして発生する。このイヴェントは keyPressedメッソドで処理される。このメソッドは親クラスXKeyListenerで定義されているのでクラスMyKeyListenerではそれを継承し再定義している。
  • このキー・イヴェントは全てのキー入力で起こる。eventの属性Kcodeの値を調べ<Enter>キーを取り出す。
  • 日付フィールドの属性、Date.Year、Date.Month、Date.Dayから入力した年、、月、日が得られる。
  • このマクロではダイアログとCalcのシートを同時に使っている。

Pythonでマクロ(6):ラジオボタンを使う

「ラジオボタン」というコントロールがある(libreOfficeではオプションボタンと呼んでいる)。名前の由来は古いラジオには選局用のボタンが複数付いており、選局はそのボタンの一つを押すとその局の放送が聞けるようになっていた。当然他の局のボタンはオフの状態になる。つまり複数のボタンの一つをオンにするとその他のボタンは自動的にオフになるような複数のボタンがラジオボタンである。

【配置】今回は「ラジオボタン」を三つ、普通の「ボタン」を一つ、そして「テキストボックス」を一つ配置する。詳細は省くがこのままでは三つの「ラジオボックス」はそれぞれ独立して動く。この三つの「ラジオボックス」をコントロールの一つである「グループボックス」で囲ってやると、この三つは連動して動く。

ラジオボタンを含むダイアログ (三つのラジオボタンを囲むグループボックスが微かに見える)

【マクロ】このダイアログの意図していることは「ラジオボタンの一つを選択し、「確認」ボタンを押すと選択したボタンのラベルが表示される」である。

試作したマクロを示す:


#coding: utf-8
import uno
import screen_io as ui
import unohelper
from com.sun.star.awt import XActionListener

class MyActionListener(unohelper.Base, XActionListener):
  def __init__(self, rbtns, langs):
    self.rbtns = rbtns
    self.langs = langs
  def actionPerformed(self, evnt):
    for i, rbtn in enumerate(self.rbtns):
      if rbtn.State:
        print(self.langs[i])
        msg = 'やっぱり'+self.langs[i] + 'ですね'
        ui.Print(msg)

def createDialog():
  ctx = XSCRIPTCONTEXT.getComponentContext()
  smgr = ctx.getServiceManager()
  dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
  dialog = dp.createDialog("vnd.sun.star.script:Standard.Dialog1?location=application")
#コントロールの登録
  rbtn1 =  dialog.getControl("radioButton1")
  rbtn2 =  dialog.getControl("radioButton2")
  rbtn3 =  dialog.getControl("radioButton3")
  rbtns =[rbtn1, rbtn2, rbtn3]
  langs = ['Python', 'Java', 'Perl']
  cmdbtn1 = dialog.getControl("commandButton1") 
#エヴェント監視(ボタンが押されたとき)
  btn1_listener = MyActionListener(rbtns, langs)
  cmdbtn1.addActionListener(btn1_listener)
  dialog.execute()
  dialog.dispose()

各ラジオボタンのオン。オフの状態は各ボタンの属性Stateの値で判定できる。

 

Pythonでマクロ(5):コントロールを制御する

Pythonでマクロ(4):ダイアログ(フォーム)の配置で配置したダイアログ上にある部品(コントロール)を制御する。

このダイアログには「テキストボックス」と「ボタン」の二つのコントロールが配置されている。

このダイアログの意図していることは
『ユーザが「テキストボックス」に語句を入力し、「ボタン」をクリックするとこの語句が別の窓に表示される』という簡単なものである。
マクロは以下のようになる:


#coding: utf-8
import uno
import screen_io as ui
import unohelper
from com.sun.star.awt import XActionListener

class MyActionListener(unohelper.Base, XActionListener):
  def __init__(self, ctrl):
    self.ctrl = ctrl
  def actionPerformed(self, evnt):
    ui.Print(self.ctrl.Text)

def createDialog():
  ctx = XSCRIPTCONTEXT.getComponentContext()
  smgr = ctx.getServiceManager()
  dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
  dialog = dp.createDialog("vnd.sun.star.script:Standard.Dialog2?location=application")
#コントロールの登録
  txtf1 =  dialog.getControl("TextField1")
  cmdbtn1 = dialog.getControl("CommandButton1") 
#エヴェント監視(ボタンが押されたとき)
  btn1_listener = MyActionListener(txtf1)
  cmdbtn1.addActionListener(btn1_listener)
  dialog.execute()
  dialog.dispose()

ダイアログ自体の登録は以前紹介したマクロと同じである。新たに登録したものはテキストボックス(名称:TextField1)とボタン(名称:CommandButtam1)の二つのコントロールである。

クラスMyActionListenerは親クラスunohelper.Baseと XActionListenerを継承している。。この新たなクラスは親クラスXActionListenerで定義されているメソッドactionPerformedを再定義するためのものである。メソッドactionPerformedはコントロール(今の場合はボタン)をマウスの左ボタンでクリックしたときのイヴェントを処理するメソッドである。コントロール「ボタン」で起こり得るイヴェントはこれ以外にも沢山ある(15個)。例えばmouseEntered 。これはマウスがそのコントロールに入ったときのイヴェントで、親クラスはXMouseListenerである。詳細はここで。

メソッドactionPerformedではクラスMyActionListenerのインスタンスbtn1_listenerの引数として渡されたコントロールtxtf1の属性Textの中身をPrint文で表示する。各コントロールが持つ属性の詳細はここで。

 

 

Pythonでマクロ(4):ダイアログの配置

作成したダイアログをLibreOffice:Calcのシート画面上に配置するだけのマクロである。

【ダイアログの作成】

シート画面のプロダウンメニュ「ツール」->「ダイアログの管理」と進む。管理画面で配置ツリーから「マイダイアログ」-> 「Standard」と進み、それをクリックすると連番号のダイアログ名(今はDialog2)が現れる。「新規作成」のボタンを選ぶとマッサラなダイアログ画面がでる。

この画面にいろんな部品(コントロールと呼ぶ)を配置する。

作例では「テキストボックス」(名称:TextField1)と「ボタン」(名称:CommandButtom1)を配置した。プレビューで実際のダイアログの画面が現れる。作例の画面を示す:

上のコントロールが「テキストボックス」で、下のコントロールが「ボタン」である。このダイアログはユーザが「テキストボックス」に字句を入力して「ボタン」を押すとその字句がプログラムで使える(例えばその字句をCalcの表に表示する)。

【配置】

このダイアログをCalcのシート上に配置するマクロを作ってみる。マクロの全体は以下のようになる:


#coding: utf-8

import uno
import unohelper

def dialog_example(*args):
     ctx = XSCRIPTCONTEXT.getComponentContext()
     smgr = ctx.getServiceManager()
     dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
     dialog = dp.createDialog("vnd.sun.star.script:Standard.Dialog2?location=application")
     dialog.execute()
     dialog.dispose()

Basicのマクロ記述に比較すると結構複雑な記述になる。Transfer from Basic to Pythonに詳しい説明がある。

泥縄窯(どろなわかま):名前が面白い

今朝の新聞の「ひと」欄には、タイトルのような面白い名前の窯で焼しめで陶器を作っている中島浩文さんが紹介されていた。

陶器の町佐賀県武雄(たけお)市でその泥縄窯の窯元として釉薬(うわくすり)を使わない焼し締めという方法で陶器を製作している。焼き締めの面白さは「窯を開いたときに、思いかけないものができていることがある」と語っている。

Pythonでマクロ(3):セルの属性(文字の色等)を変える

表計算(Calc)のシート画面で条件にしたがって文字の色を変えるマクロである。

10X10のセルには0から100までの数値が書かれている。これは教課目の試験の点数だ。これに対してユーザは及第点を入力する(ui.InputBox関数を使う)。マクロではこの及第点と点数を比較して及第点に及ばないときはこのセルの中の文字を赤にする。

マクロ全体を示す:


#coding: utf-8
import uno
import screen_io as ui
import random

def level_judge_macro( *args):
  doc = XSCRIPTCONTEXT.getDocument()
  sheet = doc.Sheets[0]
  for  i in range(10):
    for j in range(10):
      sheet.getCellByPosition(i,j).Value=random.randrange(101)
#
  level = ui.InputBox('及第点を入力してください')
  level_v = int(level)
  for  i in range(10):
    for j in range(10):
      cell = sheet.getCellByPosition(i, j )
      point_v =int(cell.Value)
      if point_v < level_v:
        cell.CharColor = 0xff0000

  return

セルの属性(文字の色)は
cell.CharColor = 0xff0000
で16進定数で与えた。

InputBoxの実行イメージは:

とラベルの付いた入力窓である。

東北大学片平キャンパス周辺のメタセコイア

米ヶ袋の広瀬川の岸辺近くには珪化木となったメタセコイアが沢山見られる。下の写真はその一つである。近くにある説明板によると約300万年まえに大量の火山灰に埋もれたメタセコイアである。

珪化木となったメタセコイア

片平キャンパスには沢山メタセコイアが植えられている。下の写真は旧理学部生物棟近くに植えられたメタセコイアの大木である。

旧理学部生物棟のメタセコイア

右の建物が旧理学部生物棟(通称赤レンガ)である。このメタセコイアは嘗て米国から東北大学に贈られた三本の苗木の一つの成長したすがたと思われる。

構内にはメタセコイアが並木に植えられているとことが幾つかある。下の写真は構内北門近くにあるメタセコイアの並木である。

メタセコイアの並木

近くにある案内板の説明によればこの並木は前の写真の旧理学部生物棟にあったメタセコイアから挿し木として移植されたものである。メタセコイア(あけぼの杉)と書いてあった。

Pythonでマクロ(2):マクロ実行ボタンを作る

LibreOfficeでマクロを実行するときに便利なマクロ実行ボタンを配置することにする。

LibreOfficeのCalcの表計算のシート上にマクロ実行ボタンを付けることにする。

ボタンはフォーム機能が持つ部品の一つである。Calcの画面でプルダウンメニュー「表示」-> 「ツールバー」-> 「フォームコントロール」を選択し、フォーム作成のためのツール一覧を出しておく。

まず一覧窓の上部にあるフォーム機能の切り替えをデザイン・モードする。様々な部品が使えるようになる。その中の「ボタン」選択し、シートの適当な場所にドラックして配置する。

設置したボタンアイコンを右クリックしてメニューから「コントロールのプロパティー」を選択する。「全般」ではボタンの表面にあるタイトルを変えたり(例えば「マクロの実行」)、ボタンの背景色を変えたりできる。「イベント」ではこのボタンで起こり得るイベントとそのイベント処理プログラム(イベント・ハンドラ)を繋げることをする。今の場合は「ボタンが押されたとき」に問題のマクロが実行されるように繋ぐ(マクロに実行関数は引数なしでよいが、イベントハンドラーでは不定個数の引数を取れるようにする。つまりmacro()  -> macro(*arg))。

これで準備ができた。デザイン・モードをオフにしてボタンを押してみる。マクロが実行されることを確認する。

フォーム実装例

【重要】このまま表を保存すると再度この表を開いたときにはフォームはデザインモードになっている。これは開発中であればよいがこのフォームをユーザが使うときは都合が悪い。表を開いたときにフォームのデザインモードがオフではじめたい。そのためにはこの表を保存するまえに

プルダウンメニュ「ツール」-> 「フォーム」-> 「フォームナビゲーター」選択。そのナビゲーター画面で「フォーム」を右クリックしデザインモードを解除した後に保存する。