Takenoff Labs

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

[Notes/Domino] 取り込み処理でのキーチェックの問題

CSV や Excel からデータを読み込んで文書を作る際、「同じキーの文書が存在したら上書き(または何もしない)、存在しなければ新規作成」という処理を書くことは多いと思います。が、キーのチェックにビューを使用していると、取り込みデータのほうに重複が存在した場合、重複チェックができないことがあるようです。

再現方法

以下、実証コードです。(現象を実証するためだけのコードなので、あまり意味がないコードになっています。また動作には、フィールド Test を第1列にソートした TestView ビューが必要です。)

Dim ss As New NotesSession
Dim db As NotesDatabase
Dim vw As NotesView
Dim doc As NotesDocument
Dim i As Integer

Set db = ss.CurrentDatabase
Set vw = db.GetView("TestView")

For i = 1 To 2
	Set doc = vw.GetDocumentByKey("aaa", True)
	If doc Is Nothing Then
		Set doc = db.CreateDocument()
		doc.Form = "TestForm"
		doc.Test = "aaa"
		Call doc.Save(True, True)
	End If
Next

同じ文書を作っているので、期待動作は「1文書のみ作成」ですが、初回実行時は2文書作成されてしまいます。また、2回目に実行した場合は、1文書も作成されません。

上記のことから、エージェントの処理実行中は、ビューが更新されていないことが判ります。「vw.AutoUpdate = True」を入れてみても結果は同じでした。

# R4くらいのときはビューが更新されたような気がしますが、記憶違いかな???

回避策

最も単純なのは、もちろん GetDocumentByKey の前に「Call vw.Refresh()」を入れること。簡単ではありますが、動作は遅くなります。

次に、取り込みデータがキーでソートされていることが確実であれば、ひとつ前のデータと比較することでチェックは可能です。これもとても簡単ですが、ソートされていることが前提なので、ソートされていることが確実でない場合は、この手段は採れません。

そこで管理人がおすすめする方法は、List を使うことです。List に処理したキーを入れていき、IsElement にてキーが存在するかどうかを確認すれば、重複が防げます。

以下、てきとーな処理イメージ :mrgreen:

Dim chklst List As String
…
Do (終了条件)
	…
	If IsElement(chklst(キーの値)) = False Then
		Set doc = vw.GetDocumentByKey(キーの値, True)
		If doc Is Nothing Then
			…
		End If
		chklst(キーの値) = ""
	End If
	…
Loop

配列だと上限が3万ちょっとで、値を検索するにもループで処理しなければなりませんが、List だとけっこうな個数でも大丈夫(10万個でも大丈夫でした)ですし、IsElement で一発チェックできるため、速く処理できます。(メモリは食うのかも知れませんが)


それにしても、なんでこんなことをやらなければならないのか……。管理人が何か間違っているようでしたら、コメントで指摘していただけるとありがたいです。

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 2970 to the field below:

^
×