[Notes/Domino] VBScript で、Notes の複数値を取り扱う方法
最近、ソフトを自由にインストールできない会社がほとんどになってきており、管理人は Notes 用のちょっとしたツールを作るのに VBScript を使う機会が増えてきております。が、VBScript では Notes の複数値を取り扱えない場合があり、それがずっと頭痛のタネでした 🙁
今回、一括置換ツールを改修しているときに、ようやく(すごーく無理矢理ちっくですが)解決方法を思いついたので、それをご紹介いたします。
現象
VBScript で、NotesDocument.GetItemValues や NotesItem.Values の戻り値にアクセスしようとすると、エラーになります(Ubound は使えますが、値にアクセスしようとするとNG)。エラーになる条件は以下のすべてを満たす場合です。
- OLE(Notes.NotesSession or Notes.NotesUIWorkspace)を使用している。
- 文字列の複数値にアクセスした場合。
COM(Lotus.NotesSession)のほうを使用した場合は、エラーにはなりません。何で OLE と COM とでこんなところが微妙に違うのか……orz
ちなみに、COM だと、プリファレンスの設定によってはパスワードが要求されてしまったり、UI が一切扱えない、などの問題があり、ノーツクライアント起動中が前提のツールを作るには、OLE のほうが便利だったりします。
2番目の「文字列の複数値」については、String 型の配列になってしまうためです。VBScript は Variant 配列しか扱えませんので、String 配列ではエラーになってしまうというわけです。日付/時刻 や 数値 の場合は、Variant 配列になるので、エラーにはなりません。
これは JScript でも同じで、VBArray() を使っても、String 配列にはアクセスできないみたいです。
解決方法1
ネットでよく見つかるのは、NotesItem.Text を使用する方法です。NotesItem.Text では、複数値の場合、「;」で繋げられた値が返りますので、値を取得した後「;」で分割すればよい、というわけです。
この方法はお手軽ではありますが、値の中に「;」が含まれると、そこで分割されてしまう、という問題があります。
解決方法2
そこで、今回わたしが思いついた(無理矢理な)解決策は、NotesDXLExporter を使用するというもの(^^;。いったん DXL に出力してしまえば、いくらでもデータを取得できるでしょう、という考え方です。(残念ながら、R5 以下では DXL が使用できないので、この方法は使えません……)
ただ、NotesDXLExporter を対象の文書自体にかけてしまうと、文書が巨大な場合、極度に処理が遅くなってしまいます。そこで、
- 新規文書を作成
- その新規文書に、処理対象のアイテムをコピーする
- NotesDXLExporter を実行
という、まだるっこしい処理にしました。こうやれば、アイテムが数個ならそれほど大きくパフォーマンスは落ちません。
以下、サンプルとして一括置換ツールのコードを抜粋いたします(vbCrLf を使っていないのはご愛嬌ということで(汗)。そのうち直します)。
If TypeName(itm.Values) = "String()" Then If Ubound(itm.Values) = Ubound(Split(itm.Text, ";")) Then '「;」で分割した結果の個数が、元と同じであれば、NotesItem.Text を使用します txtval.value = Join(Split(itm.Text, ";"), Chr(13) & Chr(10)) Else Set docTmp = db.CreateDocument() Call docTmp.CopyItem(itm, itm.Name) Set dom = ss.CreateDOMParser() Set exporter = ss.CreateDXLExporter(docTmp, dom) exporter.OutputDOCTYPE = False Call exporter.Process() Set nodes = dom.Document.documentElement.GetElementsByTagName("text") s = "" For i = 1 to nodes.NumberOfEntries If i = 1 Then s = nodes.GetItem(i).FirstChild.NodeValue Else s = s & Chr(13) & Chr(10) & nodes.GetItem(i).FirstChild.NodeValue End If txtval.value = s Next End If ・ ・ ・
上記コードでは、アイテムが1つの前提なので、いきなり「text」タグの中身を取得するという暴挙にでておりますが(^^;、複数の場合は、ちゃんと DOM をたどっていったほうがよろしいかと思います。また、複数値を改行で繋げた値にしてテキストフィールドにセットしているコードになっていますが、そこらへんは配列にセットするなり、自由に読み替えてください。
コメント
コメントはありません
※コメントは承認制となっております。管理者が承認するまで表示されません。申し訳ありませんが、投稿が表示されるまでしばらくお待ちください。