Microsoft Access帳票フォームでの重複入力チェック


Accessテーブルと紐づく帳票フォームで、キーではない項目の重複入力チェックをやるにあたって。
なぜかネットではしっくりくる結果が得られなかったので、いろいろやった結果のメモ。

○レコードの重複チェック⇒DCount関数を使う
ネットで「Access 重複チェック」とググったら、ほぼこれ一辺倒。
あと「重複クエリ」云々なんてのもありました。

いや、でもね。
例えば帳票フォームで10レコードくらいしかなく、目チェックが早いレベルとして。
その裏にベースのテーブルが数十万レコードあったら(しかもインデックスなし)、どうすんよ?


○そやったら
人間の動きをシミュレーションしてやってみては?
フォームに表示したレコードのみで処理するから、DCountより速いのでは?

Dim rs1 As DAO.Recordset, rs2 As DAO.Recordset
Dim i As Long, 検索条件 As String
Set rs1 = Me.RecordsetClone
Set rs2 = rs1.Clone           ' フォームのRecordsetCloneの、さらにCloneを作成

rs1.MoveFirst
i = 1
Do While (Not rs1.EOF)        ' 帳票フォームの先頭からチェック
    検索条件 = "[条件1] = " & rs1![条件1]
    With rs2
        .FindFirst 検索条件    ' 調べてるキーで最初から検索⇒ここで、おそらくrs1のカレントレコードがヒット
        .FindNext 検索条件     ' 同一キーで次を検索⇒キー重複がなければここでNoMatchのはず
        If Not .NoMatch Then  ' さらにマッチした=重複あり
            MsgBox i & "行目と" & (.AbsolutePosition + 1) & "行目のデータが重複しています。", vbExclamation
            Exit Do
        End If
    End With
    rs1.MoveNext
    i = i + 1
Loop

これやと、具体的な重複行を指摘できて親切かも。


○で、パフォーマンスはどうなん?
DCountと比べ、どちらがどのくらい速いかを実験。

【環境】
・Windows10 Pro/Intel Xeon Gold 6126(2.6GHz×2)/8MB RAM/Access2013(VDI環境)
・ベースのレコードはインデックスなしの10,000件
・フィルターでフォームの表示件数を変えながら、最後&最後から1件前が重複するケースを5回計測

【結果(平均:秒)】

画面表示 DCount Find検索
10,000件 228.29 123.81
1,000件 22.81 1.14
100件 1.95 0.01

当然ではありますが、フォーム表示件数が少ないほど、Find検索の速さが際立ちますね・・・