ようこそ、Access VBAの深淵なる世界へ。
あなたが「マクロの記録」を卒業し、自分の手でコードを書き始めたのは、まさに「アプリケーションを支配する第一歩」を踏み出したということです。素晴らしい決断です。
しかし、Accessを「自分一人」ではなく「チーム全員」で使うようになったとき、避けては通れない巨大な壁が立ちはだかります。それが「排他制御(レコードロック)」です。
「誰かが編集中のデータに、別の人が上書きしてしまったら?」
「同時に保存ボタンを押したらどうなるの?」
こうした不安を解消し、データの整合性を守り抜く武器が、DAO(Data Access Objects)の`LockEdits`プロパティです。今日は、このプロパティを使いこなし、プロ級のデータ処理を実現するための秘訣を、優しく、かつ本質的に伝授しましょう。
—
1. 「排他制御」は、データの整合性を守る「予約システム」
複数人で一つのデータベースを共有する場合、同じレコード(行)を同時に書き換えようとすると衝突が起きます。これを防ぐ仕組みが「排他制御」です。
DAOのRecordsetオブジェクトには、この制御を切り替えるための`LockEdits`というスイッチが備わっています。
- 悲観的排他制御(Pessimistic Locking): 「誰にも触らせない!」という慎重派
- 楽観的排他制御(Optimistic Locking): 「たぶん大丈夫、最後に確認しよう」という信頼派
この2つの違いを理解すれば、Access VBAの基本はバッチリですよ。
—
2. 悲観的排他制御:ガッチリ守る「鉄壁のガード」
`LockEdits = True` に設定すると、このモードになります。
仕組み
VBAで `.Edit` メソッドを実行した瞬間に、そのレコードにロックがかかります。
他のユーザーは、その人が `.Update`(保存)または `.CancelUpdate`(破棄)するまで、そのレコードを編集することすらできません。
メリットとデメリット
- メリット: `.Edit` が成功した時点で「編集権」が確定するため、保存時に衝突することが絶対にありません。
- デメリット: 編集中のユーザーがコーヒーを飲みに行って放置してしまうと、他の誰もそのレコードを更新できなくなります(「デッドロック」に近い状態を招きやすい)。
—
3. 楽観的排他制御:効率重視の「スマートな連携」
`LockEdits = False`(デフォルト設定)に設定すると、このモードになります。
仕組み
`.Edit` の瞬間にはロックをかけません。他のユーザーも自由に編集できます。
本当の勝負は `.Update`(保存)の瞬間です。Accessは「自分が編集を開始したときから、他の誰かが内容を書き換えていないか?」をチェックします。もし書き換えられていたら、エラーを吐いて教えてくれます。
メリットとデメリット
- メリット: ロック時間が極めて短いため、同時実行性が高く、システムのパフォーマンスが向上します。
- デメリット: 保存する瞬間に「他の人が更新済みです」というエラー(実行時エラー 3197など)が発生するため、その際の対処(リトライ処理など)をコードに書く必要があります。
—
4. 【実践】DAOでの実装コード例
では、実際にどのようにコードを書くのか見てみましょう。現場でそのまま使える、エラーハンドリングを含めたプロ仕様の構成です。
Sub UpdateRecordWithLocking()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = CurrentDb
‘ Recordsetを開く(テーブル名は「T_在庫」と仮定)
Set rs = db.OpenRecordset(“T_在庫”, dbOpenDynaset)
On Error GoTo ErrorHandler
‘ — ここが運命の分かれ道 —
‘ True : 悲観的(Editした瞬間にロック)
‘ False: 楽観的(Updateするまでロックしない)
rs.LockEdits = False ‘ 今回はモダンな「楽観的」を採用
‘ 特定のレコードを探す
rs.FindFirst “商品ID = 101”
If Not rs.NoMatch Then
‘ 編集開始
rs.Edit
‘ データの書き換え
rs!在庫数 = rs!在庫数 – 1
rs!更新日時 = Now()
‘ 保存(楽観的制御の場合、ここで競合チェックが入る)
rs.Update
MsgBox “更新が完了しました!”, vbInformation
End If
CleanUp:
‘ オブジェクトのライフサイクルを適切に閉じる(チーフアーキテクトの嗜み)
If Not rs Is Nothing Then
rs.Close
Set rs = Nothing
End If
Set db = Nothing
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 3197 ‘ 楽観的ロックで他者が更新済みの場合
MsgBox “他のユーザーがこのデータを更新しました。最新の状態を読み直してください。”, vbExclamation
Case 3260 ‘ 悲観的ロックで他者がロック中の場合
MsgBox “現在、他のユーザーがこのレコードを編集中のため、アクセスできません。”, vbCritical
Case Else
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical
End Select
Resume CleanUp
End Sub
—
5. どちらを選ぶべきか? プロの選定基準
「結局、どっちがいいんですか?」という質問への答えは、あなたのアプリケーションの「ユーザーの密度」にあります。
1. 楽観的排他制御 (`LockEdits = False`) を選ぶべきケース
- ほとんどの現代的な業務システム。
- ユーザー数が多い。
- 同じレコードを同時に触る確率がそれほど高くない。
- 理由: システム全体の応答性が良くなり、ユーザーのストレスが減るからです。
2. 悲観的排他制御 (`LockEdits = True`) を選ぶべきケース
- 在庫の引き落としや、金銭の計算など、1円の狂いも許されないシビアな処理。
- 「誰かが触っているなら、最初から編集させない方が親切」と思えるワークフロー。
- 理由: `.Edit` の段階でエラーが出るため、ユーザーは「後出しジャンケンで負ける(せっかく入力したのに保存できない)」という悲劇を避けられます。
—
終わりに:Access VBAを掌握するあなたへ
`LockEdits` の使い分けができるようになれば、あなたはもう単なる「マクロ作成者」ではありません。データの衝突を予見し、安全なシステムを設計できる「アーキテクト」の入り口に立っています。
Accessは非常に懐が深く、正しく扱えば大規模な基幹システムにも引けを取らない堅牢なツールになります。今回学んだ「排他制御」を意識して、ぜひ「止まらない、壊れない」最高のVBAツールを構築してください。
ここをクリアすれば、Access VBAの基本はバッチリですよ。応援しています!
