RubyでDomino(Notes)
はじめに
ウチのオフィスでは、情報蓄積/共有にDomino(Lotus Notes)を使っていて、データベース(DB)もたくさんある。
時々、Notes-DBの情報をExcelに書き出したり、以前作ったDBのデータを新規に作り直したDBに移す作業があったりする。 基本的にはNotes-DBのデータにアクセスするときはLotus ScriptというVBAベースのスクリプトをNotes-DB上のエージェントや ボタンに組み込んで処理する。
しかし、悲しいかなLotusScriptはVisualBasicをベースにしたスクリプト言語であり、使っていると実にストレスがたまる。 Notes自体は大好きで、これ無しには仕事ができない体になっているのだが、Lotus Scriptはどうしても好きになれない。
まぁ、DBに文書を保存するときに走らせるスクリプトや、一般ユーザーがDB上で操作するボタンなど常にDB操作とともに 動作するしくみではLotus Scriptを使うのはしょうがないとしても、たまにしか使わないような特殊なツールまでLotus Scriptを 使うのはできればさけたい。
幸い、DominoもCOMを使って制御できる。それならWIN32OLEを使ってRubyから制御して、楽しくお仕事をしよう。
Dominoのクラス構成
DominoもExcelと同じように、ほとんどの要素はクラスとして定義されていて、その要素を制御するためのメソッドや、各種属性を 参照したり変更するためのプロパティが用意されている。
主なDominoのクラスを以下に示す。
Dominoの実行環境というちょっと抽象的なものを示すクラス。COMでDominoを制御するときは、まず、NotesSessionオブジェクトを生成し、 ここから芋づる式に他の要素を示すオブジェクトを生成していく。
Dominoのデータベースを示す。
データベース内のビューを示す。ビューとは文書の一覧のこと。「作成者別」や「日付順」、「システム別」などいろんな観点で文書を 並べ替えて表示するための要素。
データベース内の文書を示す。
1つ以上の文書の集合。ビューなどからある条件で検索した結果を示す。NotesDocumentの配列のようなもの。
文書内のフィールドを示す。フィールドとは、各文書内で文字列や値や時刻などを保持するデータ領域のこと。ビューにはフィールドの 値を表示することができる。
RubyからDominoを制御する利点
DominoはR5.02からCOMによる制御ができるようになった*1。COMというのは、 Windowsが提供するオブジェクト間の通信機構のこと。
RubyもWIN32OLEという拡張ライブラリを使うとCOMを利用できる。RubyからDominoを制御する利点は、ずばり、「プログラムが楽しく組める」ということだ。 長年、NotesでいろんなDBを作ってきてLotusScriptも使っているが、LotusScriptによるプログラミングそのものにはいつもストレスを感じる。
Rubyが持つ強力な文字列処理とArrayやHashといった強力なデータ構造が自由に使えるのは魅力的だ。Rubyの文字列やArrayに 慣れてしまうと、LotusScriptの文字列や配列はどうしようもないくらい低機能だ。
LotusScriptでも自前のクラスを定義できるんだろうが、実は一度もクラスを自分で定義したことはない。関数や定数でさえ、あれほど面倒なのだから、 クラスの定義なんて死ぬほどまどろっこしいに違いない。Rubyではクラス定義はあたりまえのようにできる。
逆に欠点は、
- 遅い。これはRubyが遅いわけじゃなくて、COMで通信しているからだと思う
- スクリプトはNotesの外に独立して存在している。LotusScriptのように、Domino文書やDB内に組み込まれてないから、文書に貼り付けられたボタンを 押せば処理が開始されるといったことはできない
RubyからDominoを使うサンプル(生のWIN32OLE)
以下の例は、Dominoのヘルプ文書から、文書のタイトルの一覧を表示するサンプルだ。
01: require 'win32ole'
02:
03: ns = WIN32OLE.new('Notes.NotesSession')
04: db = ns.GetDatabase("", "help/help5_client.nsf")
05: view = db.GetView("目次")
06: doc = view.GetFirstDocument
07: while doc
08: form_name = doc.GetItemValue('Form')
09: subject = doc.GetItemValue('Subject')
10: puts "Form:#{form_name}, Subject:#{subject}"
11: doc = view.GetNextDocument(doc)
12: end
これをみると、ほとんどLotusScriptと同じだとわかるだろう。Dominoが用意しているメソッドがそのまま使えるのはCOMとWIN32OLEのおかげだ。
ちなみに、LotusScriptだとこうなる。
01: Sub Click(Source As Button)
02: Dim ns As New NotesSession
03: Set db = ns.GetDatabase("", "help/help5_client.nsf")
04: Set view = db.GetView("目次")
05: Set doc = view.GetFirstDocument
06: While Not(doc Is Nothing)
07: Print "Form: "+doc.Form(0) + ", Subject:" + doc.Subject(0)
08: Set doc = view.GetNextDocument(doc)
09: Wend
10: End Sub
ちなみに、私がどのへんでストレスを感じるかというと、
- 数字や文字列の代入は "index = 10"のように書けるのに、オブジェクトをセットするときは"Set db = ns.GetView(xxx)"と書かされる
- 6行目の"while Not(doc is Nothing)"のような書き方。while(doc != Nothing)と書けないがつらい。
- 7行目のような書き方しかできないのはコードの可読性が非常に悪い。Rubyスクリプトの10行目の書き方の方がスマートだと思わない?
Dominoの各オブジェクトをラップしよう
WIN32OLEを使えば、DominoのオブジェクトをRubyから扱える。しかし、どんなオブジェクトもWIN32OLEクラスの オブジェクトにしか見えないため、ちょっとあつかいづらい場面が出てくる。
デバッグしようと思って、p doc と書いても、みんなWIN32OLEとしか表示されないのはちょっと寂しい。やっぱり、NotesDocument オブジェクトであれば"NotesDocument"と表示してほしい。
例えば、NotesViewオブジェクトであれば、eachメソッドでイテレータが欲しいし、NotesDocumentクラスであれば、[]メソッドで 文書中のフィールド(NotesItem)にアクセスしたい。
このように機能を拡張できれば、RubyからDominoを制御するのはより楽しくなる。
そこで、RubydeExcelと同じようにDominoの各クラスをラップするクラスを用意し、 別のオブジェクトを得る主なメソッドはオーバーライドしてしまって、生のWIN32OLEではなく、用意したラップクラスの オブジェクト(内部にWIN32OLEオブジェクトを内包)を返すようにすれば、以下のような記述が可能になる。
ns = Notes::NotesSession.new
db = ns.database("","test.nsf")
p db # -> NotesDatabase
view = db.view("ALL")
view.each {|doc|
p doc['Subject'].text # "Subject"フィールドの内容を表示
}
ちなみに、上の例でviewはDominoのNotesViewクラスをラップしたNotes::NotesViewクラスのオブジェクトで、内部にDominoのviewオブジェクトを指す WIN32OLEオブジェクトを内包している。
RubydeDominoライブラリ
RubydeDominoは、RubyからDominoを制御するための拡張ライブラリである。
ダウンロード
インストール方法
- LZHファイルを展開
- notes_lib.rbをRubyのライブラリフォルダか制御スクリプトと同じフォルダにコピーする
RubydeDominoのドキュメント
RubydeDominoの使い方。
LotusScriptユーザーのためのRubyレクチャー
RubydeDominoのサンプルをいくつか載せながら、Rubyスクリプトの書き方を説明していく。
ライセンス
ライセンスはRubyのライセンスに従います。
Copyright (C) 2003,2004 Oka Yasushi <yac@tech-notes.dyndns.org>
You may redistribute it and/or modify it under the same license terms as Ruby.
免責事項
本プログラムは無保証です。作者は、プログラム自身のバグ、あるいは、本プログラムの実行など から発生するいかなる損害に対しても責任を持ちません。
変更履歴
Ver 1.00 Initial Release
*1R4.6でもできてたが、いまいち動作が不安定だった。