三流君のソースコード置き場

ブログにソースコードをアップして、ブログの検索機能で利用してます(利用予定です)

よく検索されるキーワード: [VBA]/ [VBS]/ [CreateObject]/ [Excel]/ [ADO]


過去動画をAIでまとめるテスト Access VBA重複チェックの決定版|DCountとOldValueを組み合わせた「エラーを出さない」入力フォーム作成術

Access VBA データの重複登録を防ぐ!DCount関数とBeforeUpdate(更新前処理)の実装方法

Accessでフォーム入力を作っていると必ず直面するのが、''「データの重複登録をどう防ぐか?」''という問題です。
今回は、DCount関数を使って件数を数え、BeforeUpdateイベントで保存を阻止する、という一連の流れを解説します。

さらに、単に重複を弾くだけでなく、''「マスターに存在しないコード」のチェック''や、''「別フォームから値を代入した時にイベントが走らない問題」''の解決策まで踏み込んでいきます。

AIにまとめてもらいました

説明したかったこと・伝えたかったこと

  • DCount関数を使って、テーブル内の重複レコード件数を正確に把握する。
  • BeforeUpdate(更新前処理)で「Cancel = True」を使い、エラー時に保存させない。
  • .OldValueプロパティを活用し、自分自身の修正(値が変わっていない場合)はチェックをスルーさせる。
  • チェック処理を「標準モジュール」に共通関数として出し、どこからでも呼び出せるようにする。

1. 基本のDCountテスト(単体テスト

まずはボタンのクリックイベントなどで、正しく件数が数えられるかテストします。

Private Sub btnTest_Click()
    Dim nCNT As Integer
    ' T_注文履歴テーブルから、入力された商品コードの件数を数える
    nCNT = DCount("商品コード", "T_注文履歴", "[商品コード] = '" & Me.商品コード & "'")
    
    MsgBox nCNT & " 個データがあります"
End Sub

[01:55](https://www.youtube.com/watch?v=Irr_9wx6CAY&t=115s) 頃の解説にある通り、まずは単体で動くことを確認するのがデバッグの鉄則です。

2. 鉄壁のチェック関数(標準モジュール)

フォームごとに同じコードを書くのは非効率です。また、別フォームから値をセットした時にイベントが発火しない問題を解決するため、チェック処理を共通関数化します。

' 商品コードをチェックし、エラーがあればTrueを返す
Public Function chk商品コード(str商品コード As String) As Boolean
    Dim nCNT As Integer
    
    ' 1. マスター(T_メニュー一覧)に存在するかチェック
    nCNT = DCount("商品コード", "T_メニュー一覧", "[商品コード] = '" & str商品コード & "'")
    If nCNT = 0 Then
        MsgBox str商品コード & "が見つかりません。マスターを確認してください。"
        chk商品コード = True ' エラー
        Exit Function
    End If
    
    ' 2. 注文履歴に既に登録(重複)がないかチェック
    nCNT = DCount("商品コード", "T_注文履歴", "[商品コード] = '" & str商品コード & "'")
    If nCNT > 0 Then
        MsgBox str商品コード & "は重複しています。再入力してください。"
        chk商品コード = True ' エラー
        Exit Function
    End If

    ' エラーなし
    chk商品コード = False
End Function

3. フォーム側での実装(BeforeUpdate)

フォームの「商品コード」コントロールの更新前処理に記述します。ここで ''.OldValue'' を使うのがポイントです。

Private Sub 商品コード_BeforeUpdate(Cancel As Integer)
    ' 変更がない場合はチェック不要
    If Me.商品コード.Value = Me.商品コード.OldValue Then
        Exit Sub
    End If

    ' 共通関数を呼び出してエラーならキャンセル
    If chk商品コード(Me.商品コード.Value) = True Then
        Cancel = True ' 更新処理の中断
    End If
End Sub

[20:04](https://www.youtube.com/watch?v=Irr_9wx6CAY&t=1204s) では、修正時に自分自身の値を重複と判定させないための「OldValue」活用法を解説しています。

4. 選択用サブフォームからの呼び出し

一覧フォーム(別窓)から商品を選択して親フォームに代入する場合、そのままでは親のBeforeUpdateが走りません。そのため、セットする直前に同じ関数を呼び出します。

Private Sub 選択ボタン_Click()
    Dim menuCode As String
    menuCode = Me.商品コード.Value

    ' 親フォームに代入する前にチェック
    If chk商品コード(menuCode) = True Then
        Exit Sub ' エラーならここで中断(画面を閉じない)
    End If

    ' 正常なら親フォームにセットして閉じる
    Forms(Me.OpenArgs).商品コード.Value = menuCode
    DoCmd.Close acForm, Me.Name
End Sub

デバッグの手順と動画リンク

今後の課題とアドバイス

今回の実装で基本的な重複は防げますが、実務レベルでは以下の点も考慮するとさらに良くなります。

  • ''マルチユーザー環境'': 厳密には保存の瞬間に再度チェックをかけないと、二人同時に同じコードを打った際にすり抜ける可能性があります。
  • ''UIの親切さ'': 商品コードを弾くだけでなく、正常な場合はそのまま「商品名」を自動表示させるロジックを組み合わせるとユーザーに喜ばれます。

質問・感想・クレームなど、
気軽にコメント欄に書いてもらえるとうれしいです。

[Googleフォームにコメントを残す]
↑質問・コメントの入力フォームです、気軽に書いてください


フッター:最後にKen3Videoの動画一覧を紹介します

YouTubeにアップした動画です。他の動画を一瞬でも見てもらえるとさらに嬉しいです。
再生リスト:[三流君Ken3の最新動画]←リストの一覧形式で表示する


また、ブログを見に来てくださいね。ではまたぁ~