最後に残ったのが氏名行である。困ったことに氏名を特定する手掛りはほとんどなにもない。ここでは安直に残った行データが氏名行であるする。
全体を纏めると:
- 最も規則が厳しい郵便番号行を始めに検出する。
- 次に電話番号行を特定する。
- その次に住所行を確定する。
- 残った行データが氏名データである。
これらをLibreOfficeのマクロに組み込む。
【実行例】

このマクロはここにある。
最後に残ったのが氏名行である。困ったことに氏名を特定する手掛りはほとんどなにもない。ここでは安直に残った行データが氏名行であるする。
全体を纏めると:
これらをLibreOfficeのマクロに組み込む。
【実行例】
このマクロはここにある。
住所録の住所行の検出の問題である。
手掛りは住所特有な文字だろう。
#coding: utf-8
import re
msgs = ['仙台市泉区天神澤', \
'山梨県東八代郡大沢町', \
'東京都千代田区霞ヶ関', \
'北海道小樽市小牧二丁目2-3', \
'山県有朋',\
'布施市介']
for i, msg in enumerate(msgs):
ms = []
m1 = re.search(r'都|道|府|県', msg)
ms.append(m1)
m2 = re.search(r'郡|市', msg)
ms.append(m2)
m3 = re.search(r'区|町|村|大字', msg)
ms.append(m3)
m4 = re.search(r'丁|番|号|字', msg)
count = 0
for m in ms:
if bool(m):
count+=1
if count >= 2:
print(msg, ' OK')
else:
print(msg, ' NG')
規模の大きさをグループにして探す。「都・道・府・県」という文字を含んでいること。次は「郡・市」、次は「区・町・村・大字」、最後は「丁・番・号・字」。プログラムではこれらのグループ化された文字を二ヶ所以上含んでいると住所としてしている。従って「山県有朋」や「布施市介」は住所でない。
郵便番号については既に議論した。次は電話番号行を特定するための正規表現である。
電話番号行は
行の先頭が’電話’、’Tel’、’TEL’で始まる文字列の行(例:電話022-222-4444)。または0から9の半角数字、記号’-‘、記号'(‘、記号’)’の文字からのみなる文字列(例:022(222)2345や022-227-2345)とする。
この条件をPythonで書くと:
#coding: utf-8
import re
msgs = ['電話022-222-2222', 'Tel022-222-2345', 'TEL022-228-5678', \
'022(2267)5678', '234-3456-4567', '456局345(65678)','34+456+4567']
for i, msg in enumerate(msgs):
m1 = re.search(r'^電話|Tel|TEL', msg)
#print(i, m1)
m2 = re.search(r'[^0-9-()]', msg)
#print(i, m2)
if bool(m1) or not bool(m2):
print(msg, ' OK')
else:
print(msg, ' NG')
m1は文の先頭に’電話’等の文字列があることを条件にしている。m2は当該の位置にない文字を指定している。つまり、0から9まで半角数字、記号’-‘、記号'(‘、記号’)’以外のものがあるとマッチする。文字列のどこかに該当する文字があるとマッチする1文字マッチの条件である。m2にはその文字が代入される。その文字列の最後まで探して該当する文字がないとm2はNoneになる。つまり、除外した文字のみでできている文字列であるかどうかを判定できる。
結果は
電話022-222-2222 OK
Tel022-222-2345 OK
TEL022-228-5678 OK
022(2267)5678 OK
234-3456-4567 OK
456局345(65678) NG
34+456+4567 NG
となる。
Pythonによる正規表現はここが詳しい。
黒部渓谷、劔岳、立山連峰周辺の地図を眺めていると「長次郎谷」、「源次郎尾根」、「作朗越」など人の名前に由来すると思われるものが地形の名前に使われていることがある。これらはこの周辺の山を案内した地元の案内人の名前であるが、「内蔵の助谷」と古風な名前の谷がある。これは現在の「黒四ダム」の少し下流で左岸に流れ込んでいる谷である。
この谷の名前は古風なはずで戦国時代の武将の名前に由来する。その武将は佐々内蔵之助成政という。天正12年(1584年)、越中を支配していた成政が越中から信州に出て、浜松まで行き家康に面会したとされるときに通過したルートが、「早月入りを伊折から大窓を越えて立山の東面に入り、内蔵の助平の岩窟で泊まり、内蔵の助谷を下った」という伝説があるという(「黒部渓谷」)。
ユーザ・インタフェースで難しいのは入力であると言われている。ここでは自由形式で入力した住所録のデータ(氏名・郵便番号・住所・電話番号)から、氏名、郵便番号、住所、電話番号の文字列を取り出すことを考えた。全くの自由であると処理方法が極めて複雑ななるので、ここではこれらの文字列はそれぞれ一行に書かれているとするが、氏名をはじめに書くときもあれば、郵便番号最初に書くばあいもある。問題は行毎に書かれている文字列を判定する作業である。
最も簡単なものは郵便番号行で「〒」(例:〒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
となり、期待した結果がでる。
郵便番号行の検出が最も簡単である。次は電話番号行の検出、住所行の検出、氏名行の検出を考える。氏名行の検出が手掛りがなく最も困難であると思われる。
黒部渓谷の中流域に阿曽原(アゾハラ)という地名がある。この地名の由来について「黒部渓谷」(冠松次郎著)に記載があった。それによれば「湯の湧き出る熱いところ」の意味だそうだ。事実こに地域は黒部渓谷のなかでも最も湯が湧き出る量が多いところの一つで、熱湯が川に流れ込むところがいく筋があるという。
現在ではここには温泉山小屋があって「高熱隧道」(吉村昭著)で「胞雪崩」で倒壊した宿舎跡地にその温泉山小屋は建っている。
LibreOfficeのマクロをPythonで書くことを調べてきたが、この付録ではほんの少しだけ実用的になるかなというマクロの話である。
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, textf1):
self.sheet = sheet
self.textf1 = textf1
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 == 1282: #キー
#表への書き出し
self.row+=1
print(self.row)
textd = self.textf1.Text
print(textd)
sheetd=textd.split("\n")
print(len(sheetd))
for i, celld in enumerate(sheetd):
self.sheet.getCellByPosition(i,self.row).String=celld
self.textf1.Text = ''
def createDialog(*args):
ctx = XSCRIPTCONTEXT.getComponentContext()
smgr = ctx.getServiceManager()
dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
dialog = dp.createDialog("vnd.sun.star.script:Standard.Dialog5?location=application")
#表
doc = XSCRIPTCONTEXT.getDocument()
sheet = doc.Sheets[0]
#コントロールの登録
textf1 = dialog.getControl("TextField1")
#エヴェント監視(Enterキーを検出)
textf1_listener = MyKeyListener(sheet, textf1)
textf1.addKeyListener(textf1_listener)
dialog.execute()
dialog.dispose()
このマクロでは1つの入力の終わりは
【マクロ】
#coding: utf-8
import uno
import screen_io as ui
import unohelper
from com.sun.star.awt import XMouseListener
class MyMouseListener(unohelper.Base, XMouseListener):
def __init__(self, sheet, textf1):
self.sheet = sheet
self.textf1 = textf1
self.row = 0
def mouseEntered( self, event ):
#表への書き出し
self.row+=1
print(self.row)
textd = self.textf1.Text
print(textd)
sheetd=textd.split("\n")
print(len(sheetd))
for i, celld in enumerate(sheetd):
self.sheet.getCellByPosition(i,self.row).String=celld
self.textf1.Text = ''
return False
def mouseExited(self, event):
return False
def mousePressed(self, event):
return False
def mouseReleased(self, event):
return False
def createDialog(*args):
ctx = XSCRIPTCONTEXT.getComponentContext()
smgr = ctx.getServiceManager()
dp = smgr.createInstanceWithContext("com.sun.star.awt.DialogProvider", ctx)
dialog = dp.createDialog("vnd.sun.star.script:Standard.Dialog5?location=application")
#表
doc = XSCRIPTCONTEXT.getDocument()
sheet = doc.Sheets[0]
#コントロールの登録
textf1 = dialog.getControl("TextField1")
#エヴェント監視(Enterキーを検出)
textf1_listener = MyMouseListener(sheet, textf1)
textf1.addMouseListener(textf1_listener)
dialog.execute()
dialog.dispose()
この例では意図しないタイミングでマウスを窓に入れてしまうのでインタフェースとしてはオリジナルのものがよいと思われる。
利便性が高いとディジタル化が叫ばれている。
ディジタル化で失われるものもある。それが多様性だ。
ものごとのディジタル化に際して規格化がされる。規格化は篩いにかけることである。篩いの目が粗いと篩いに残ったものは質が均質で扱いやすくディジタルシステムの利便性は大きくなる。しかし篩いの目からこぼれてしまったものも多い。これがものごとの多様性を担っている部分である。
利便性だけを追い求めるとますます多様性が失われる。
熟旨(じゅくうま)と曙光(しょこう)も台所にあった食品に付けられていた商標である。
熟旨にはかなが振ってあって「じゅくうま」と読ませる。曙光は「しょこう」とかなが振ってある。
曙光(しょこう)が音だけで読ませるのに対して、「熟旨(じゅくうま)は最初の漢字は音で、二番目は訓で読ませる。じゅくうま」はいわゆる重箱読みである。熟旨は音だけで読むと「じゅくし」となる。こちらの方が美味しそうかな。
このシリーズの最終回である。
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
実行画面
同じことをダイアログで行う例はここにある。
【まとめ】