内蔵の助(くらのすけ)谷と佐々成政(ささなるまさ)

黒部渓谷、岳、立山連峰周辺の地図を眺めていると「長次郎谷」、「源次郎尾根」、「作朗越」など人の名前に由来すると思われるものが地形の名前に使われていることがある。これらはこの周辺の山を案内した地元の案内人の名前であるが、「内蔵の助谷」と古風な名前の谷がある。これは現在の「黒四ダム」の少し下流で左岸に流れ込んでいる谷である。

この谷の名前は古風なはずで戦国時代の武将の名前に由来する。その武将は佐々内蔵之助成政という。天正12年(1584年)、越中を支配していた成政が越中から信州に出て、浜松まで行き家康に面会したとされるときに通過したルートが、「早月入りを伊折から大窓を越えて立山の東面に入り、内蔵の助平の岩窟で泊まり、内蔵の助谷を下った」という伝説があるという(「黒部渓谷」)。

Pythonで正規表現:郵便番号

ユーザ・インタフェースで難しいのは入力であると言われている。ここでは自由形式で入力した住所録のデータ(氏名・郵便番号・住所・電話番号)から、氏名、郵便番号、住所、電話番号の文字列を取り出すことを考えた。全くの自由であると処理方法が極めて複雑ななるので、ここではこれらの文字列はそれぞれ一行に書かれているとするが、氏名をはじめに書くときもあれば、郵便番号最初に書くばあいもある。問題は行毎に書かれている文字列を判定する作業である。

最も簡単なものは郵便番号行で「〒」(例:〒888-8888)ではじまる。または行末が「数字3文字-数字4文字」(例:888-8888)、または「数字7文字」(例:8888888)になっているという条件に合う行がそれであるとする。

このような条件に有った文字列を調べるには「正規表現」が便利である。このような正規表現をPythonで書くと以下のようになる:


#coding: utf-8
import re
msgs = ['〒123-4567', '123-4567',  '1234567', '123-45']
for i, msg in enumerate(msgs):
    m1 = re.search(r'^〒', msg)
    m2 = re.search(r'\d{3}\-\d{4}$', msg)
    m3 = re.search(r'\d{7}$', msg)
    if bool(m1) or bool(m2) or bool(m3):
        print(msg, ' OK')
    else:
        print(msg, 'NG')

結果は
〒123-4567 OK
123-4567 OK
1234567 OK
123-45 NG

となり、期待した結果がでる。

郵便番号行の検出が最も簡単である。次は電話番号行の検出、住所行の検出、氏名行の検出を考える。氏名行の検出が手掛りがなく最も困難であると思われる。

黒部渓谷の阿曽原(アゾハラ)

黒部渓谷の中流域に阿曽原(アゾハラ)という地名がある。この地名の由来について「黒部渓谷」(冠松次郎著)に記載があった。それによれば「湯の湧き出る熱いところ」の意味だそうだ。事実こに地域は黒部渓谷のなかでも最も湯が湧き出る量が多いところの一つで、熱湯が川に流れ込むところがいく筋があるという。

現在ではここには温泉山小屋があって「高熱隧道」(吉村昭著)で「胞雪崩」で倒壊した宿舎跡地にその温泉山小屋は建っている。

利便性vs.多様性:ディジタル化で失われるもの

利便性が高いとディジタル化が叫ばれている。

ディジタル化で失われるものもある。それが多様性だ。

ものごとのディジタル化に際して規格化がされる。規格化は篩いにかけることである。篩いの目が粗いと篩いに残ったものは質が均質で扱いやすくディジタルシステムの利便性は大きくなる。しかし篩いの目からこぼれてしまったものも多い。これがものごとの多様性を担っている部分である。

利便性だけを追い求めるとますます多様性が失われる。

熟旨(じゅくうま)と曙光(しょこう)

熟旨(じゅくうま)と曙光(しょこう)も台所にあった食品に付けられていた商標である。

熟旨にはかなが振ってあって「じゅくうま」と読ませる。曙光は「しょこう」とかなが振ってある。

曙光(しょこう)が音だけで読ませるのに対して、「熟旨(じゅくうま)は最初の漢字は音で、二番目は訓で読ませる。じゅくうま」はいわゆる重箱読みである。熟旨は音だけで読むと「じゅくし」となる。こちらの方が美味しそうかな。

Pythonでマクロ(11):ダイアログとフォーム

このシリーズの最終回である。

LibreOfficeのユーザインタフェースとしてダイアログとフォームがある。

「日付フィールドに日付を入力して<Enter>キーを入力するとその日付の年・月・日がシートに代入される」

これをCalcの画面に付けたフォームで行うときのマクロは以下のようになる(これは日付フィールドのイヴェント表の中の「キーを押したとき」のイヴェント処理である):


#coding: utf-8
import uno
import screen_io as ui
row=0
doc = XSCRIPTCONTEXT.getDocument()
ctrl =doc.getCurrentController()
sheet = doc.Sheets[0]
form = sheet.DrawPage.Forms[0]
datef1 = form['datefield1']

def keyPressed_macro(event):
  global row
  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(datef1.IsDate)
    year = datef1.Date.Year
    month = datef1.Date.Month
    day = datef1.Date.Day
    #表への書き出し
    row+=1
    print(row)
    print(year, month, day)
    sheet.getCellByPosition(0,row).Value=year
    sheet.getCellByPosition(1,row).Value=month
    sheet.getCellByPosition(2,row).Value=day

  return

実行画面

シートとフォーム

同じことをダイアログで行う例はここにある。

【まとめ】

  • フォームもダイアログのためのマクロは同程度の手間で作れる。イヴェント処理が若干異なる。フォームではコントロールのイベント監視は付属するイヴェント表が使えるが、ダイアログ上のコントロールではイベントの監視部分からマクロに含めなければならない。
  • フォームはシートの一部として配置できるが、ダイアログは別窓の表示となる。
  • フォームの位置は固定。ダイアログは移動可。従ってフォームを何処に配置するかを配慮する必要がある。
  • ダイアログは要らないときは邪魔になる。起動のタイミングを考慮する必要がある。
  • 不要になつたダイアログは画面上から消せるが、フォームはできない。
  • ダイアログは様々な部品を配置するインタフェースに向いている。

Pythonでマクロ(10):マウスのイヴェントを処理する

セル上でマウスをダブルクリックする前回のイヴェントの作例ではマウスのイベントの監視はLibreOffice側で行うようになっていた。今回はそこの部分もマクロで行うようにした。

マウスのボタンが押された・放されたというイヴェントは親クラスXMouseClickHandlerを使う。このクラスにはmousePressedとmouseReleasedメソッドが定義されているのでこれを再定義して使う。

作例の意図は「セル上でマウスの左ボタンをダブルクリックするとそのセルの背景色は赤になる」である。

【マクロ】


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

class MouseClickHandler(unohelper.Base, XMouseClickHandler):
  def __init__(self, subj, doc, sheet):
    self.subj = subj  
    self.args = doc, sheet

  def mousePressed(self, mouseevent):
    doc, sheet = self.args
    if mouseevent.Buttons==MouseButton.LEFT:  
      if mouseevent.ClickCount==2:  #
        target = doc.getCurrentSelection()
        if target.supportsService("com.sun.star.sheet.SheetCell"):
          address = target.getCellAddress()
          Row = address.Row
          Column = address.Column
          #msg =  str(Row) + '   ' + str(Column) 
          #ui.Print(msg)
          cell = sheet.getCellByPosition(Column, Row)
          cell.CellBackColor = 0xff0000
    return False

  def mouseReleased(self, mouseevent):
    return False 

def createDialog():
#ダイアログの登録
  ctx = XSCRIPTCONTEXT.getComponentContext()
  smgr = ctx.getServiceManager()
  dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
#シートの登録
  doc = XSCRIPTCONTEXT.getDocument()
  ctrl = doc.getCurrentController()
  sheet = doc.Sheets[0]

#エヴェント監視
  mouseclickhandler = MouseClickHandler(ctrl, doc, sheet)
  ctrl.addMouseClickHandler(mouseclickhandler)  # EnhancedMouseClickHandler

「左マウスのダブルクリックか」や「マウスがセル上にあるか」の判定は再定義したmousePressedメソッドの先頭で行っている。このマクロはCalcが起動しシート画面が出た時点で起動できる(プルダウンメニュ「ツール」->「カスタマイズ」と行き、イヴェント一覧から「文書を開いたとき」を選び当該マクロとを繋ぐ)。

なお、この作例を作るにあたってはここが参考になった。

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のシートを同時に使っている。