誰も使っていないのに…

*おすすめ書籍:失敗しないデータベース プログラミング
ある人が、Access でフォームをつくっていました。(仮にAさんとします)
伝票入力のフォームなので、データ修正中は他の人にいぢられては困ると、フォームの「レコードロック」プロパティは「編集済みレコード」に設定しました。
単価を伝票ごとに保持する必要があったので、伝票テーブルには「単価」項目と「金額」項目があります。Aさんは、「単価」は「商品マスタ」に登録されていますから、最新の単価をとってきて伝票テーブルを自動で更新しようと考えました。まぁこんなのよくある処理ですな。
で、商品コードの更新後処理イベントにこんなモジュールを書きました。
Dim Mydb As Database
Dim MyRS as Recordset
Set Mydb = Currentdb()
Set MyRS = Mydb.OpenRecordset(“select * from [伝票] where [伝票番号]=” & me![伝票番号])
With MyRS
.Edit
.Fields(“単価”) = DlookUP(“単価”,”商品マスタ”,”商品コード =” & me![商品コード])
.Fields(“金額”) = .Fields(“単価”) * me![数量]
.Update
End With
MyRS.close
Mydb.close
ところが、商品コードを変更すると、奇妙なエラーが発生するのです。
「実行時エラー’3188′: このマシンのほかのセッションによってロックされているので、更新できませんでした。」
…あれ?
自分のマシンを確認しましたが、他に Access が立ち上がっている様子もありません。mdb が入っているフォルダは自分のマシンにあり共有設定もしていませんから他から開くことはできないはず。mdb が壊れたかと修復・最適化・新規 mdb へのインポートも当然試しましたが効果はありません。
一体なぜ、誰も使っていないのに、ロックされてしまっているんでしょう?
この mdb は呪われてしまったのでしょうか?この後どうしたらいいんでしょうか?
…いや別に呪われてはいないでしょう(^_^;) 壊れやすい mdb なんかは呪われてると思いたくもなりますが、今回の場合はそれとも違いますね。
問題は、フォームのレコードソースになっているテーブルを、モジュールを使って更新しようとしたことにあります。
フォームのレコードソースになっているテーブルは、フォームによって更新データがロックされます。そのロックのやり方を指定するのが、最初に出てきたフォームの「レコードロック」プロパティです。
今回の場合、これを「編集済みレコード」に指定していますので、フォームのレコードセレクタが「えんぴつマーク」(どこかの連結コントロールの内容が変更された状態)になっている場合、フォームによって該当ページがロックされます。 え?そんなの判ってる?判ってて指定してるんだ?まぁそう言わずに(^_^;)
実は、モジュールによる更新は、連結フォームのそれとは別セッションになります。たとえフォームのイベント プロシージャだったとしても。
ぜんぜん別のフォームや別のモジュールから実行してれば同じセッションとは思わないでしょうから、こんなカンチガイはしなくて済むのですが、フォームのイベントプロシージャではうっかり同一セッションと思い込んでしまうこともあります。(当然ですが、別フォームや別モジュールからの更新を含めすべて別セッション扱いになります)
フォームの「レコードロック」プロパティを「しない」にすればメッセージは出なくなりますが、それでは排他制御の問題が残りますのでここは変更するべきではありません。
んじゃ、こんなときAさんはどうしたらいいんでしょう?
こたえは簡単。モジュールから更新できないんだったら、フォームの連結コントロールを利用すればよいのです。これなら当然同一セッションになります。
Aさんの場合ですと、フォーム上に非表示でもいいから、[単価]、[金額]項目と連結しているコントロールを用意し、そこへ値をセットしてあげればいいのです。
me![単価] = DlookUP(“単価”,”商品マスタ”,”商品コード =” & me![商品コード])
me![金額] = me![単価] * me![数量]
こうすれば、修正したレコードが保存されるタイミングで単価、金額がいっしょに保存されます。セットするタイミングは、商品コード等の更新後処理でもいいですし、フォームの更新前処理でもいいでしょう。
モジュールで先に変更して保存してしまうと、商品コードに対する変更がキャンセルされても単価と金額は変わってしまったりと不都合が生じますので、そういう意味でもモジュールで別更新することは避けたほうがいいと言えます。
どうも、「自動で更新」というコトバから、ついついモジュールでレコードセットとか更新クエリーで一括更新とか考えてしまいがちですが、「更新」手段はそれだけではないということですね。