Takenoff Labs

Lotus Notes/Domino に関する Tips や、クラシックの名曲などを紹介します

[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 を対象の文書自体にかけてしまうと、文書が巨大な場合、極度に処理が遅くなってしまいます。そこで、

  1. 新規文書を作成
  2. その新規文書に、処理対象のアイテムをコピーする
  3. 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 をたどっていったほうがよろしいかと思います。また、複数値を改行で繋げた値にしてテキストフィールドにセットしているコードになっていますが、そこらへんは配列にセットするなり、自由に読み替えてください。

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
読み込み中...

トラックバック

トラックバックはありません

コメント

コメントはありません

※コメントは承認制となっております。管理者が承認するまで表示されません。申し訳ありませんが、投稿が表示されるまでしばらくお待ちください。





(以下のタグが使えます)
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

For spam filtering purposes, please copy the number 1828 to the field below:

^
×