Microsoft Access 2010 でリンク テーブル アプリケーションの保守作業を行っているときに、この小さな問題が発生しています。アプリケーションは、SQL Server 2008 データベースにリンクされています。アプリケーションには、ユーザーがパーク コードとリソースの組み合わせを選択できるメイン フォームがあり、その特定の組み合わせの詳細を編集するためのフォームがポップアップ表示されます。そのコンボがデータベースに存在しない場合、アプリケーションは新しいレコードを挿入しますが、問題は 2 つのレコードが挿入されることです。
問題のコードの場所は次のとおりです。詳細ポップアップ フォームに新しいレコードを挿入する必要があるときに呼び出されます。
Private Sub New_Rec(unit_code As String, resource As String, sql As String)
DoCmd.RunSQL ("INSERT INTO PARK_RESOURCES (unit_code, resource, sensitivity) VALUES " _
& "('" & unit_code & "','" & resource & "','public')")
'Force an explicit save
'http://www.pcreview.co.uk/forums/update-cancelupdate-without-addnew-edit-t1150554.html
If Me.Dirty Then
Me.Dirty = False
End If
Me.RecordSource = sql
End Sub
「新しい」レコードを作成すると、2 つのレコードが Recordset に挿入されます。RecordSource を設定する前または後に明示的な保存コードを移動しても問題ないようです。どちらの順序でも (そしていずれかの後に停止すると)、データベースに挿入される 2 つの新しいレコードが生成されます (SSMS でのクエリによって確認されます)。
RecordSource プロパティを設定してコードをステップ実行すると、イベント チェーンは Me.RecordSource = sql --> Form_BeforeUpdate() --> Form_AfterUpdate() --> Form_After_Insert() --> Form_Current() のようになります。BeforeUpdate の終了時には重複は存在しませんが、AfterUpdate に到達するまでに、重複は既に挿入されています。これを引き起こす BeforeUpdate と AfterUpdate の間で何が起こりますか?
MSDN によると、順序は、 BeforeInsert → BeforeUpdate → AfterUpdate → AfterInsert です。また、Visual Basic を使用してコントロールの値を設定しても、これらのイベントはトリガーされないと述べています。しかし、コードで RecordSource を更新すると、最後の 3 つのイベントが確実に発生します。BeforeInsert は、ステップスルーが停止しない唯一のものです。
Daniel Cook のリクエストによると、呼び出しコードは次のとおりです。
Private Sub Form_Load()
On Error GoTo Err_Form_Load
Me.KeyPreview = True
If Not IsNull(Me.OpenArgs) Then
ProcessOpenArgs (Me.OpenArgs)
Me.lblHeader.Caption = Me.unit_code & ": Resource - " & Me.resource
Else
Me.lblHeader.Caption = "Information Needs"
End If
... (error trapping)
End Sub
そして ProcessOpenArgs サブ (OpenArgs は "park;resource" として設定されます):
Private Sub ProcessOpenArgs(open_args As String)
On Error GoTo Err_ProcessOpenArgs
Dim Args() As String
Args = Split(open_args, ";")
Me.unit_code = Args(0)
Me.resource = Args(1)
'Check to see if there are records in the database for current unit/resource combo'
Dim rs As DAO.Recordset
Dim sql As String
sql = "SELECT * FROM PARK_RESOURCES " & _
"WHERE resource='" & Me.resource & "' AND unit_code='" & Me.unit_code & "'"
Set rs = CurrentDb.OpenRecordset(sql, dbOpenDynaset, dbSeeChanges)
'if there aren''t, create a new record'
If (rs.RecordCount = 0) Then
New_Rec Me.unit_code, Me.resource, sql
Else 'go to the current listing'
Me.RecordSource = sql
End If
Exit_ProcessOpenArgs:
Exit Sub
Err_ProcessOpenArgs:
MsgBox Err.Number & Err.description
Resume Exit_ProcessOpenArgs
End Sub
私はイベントのドキュメントを精査し続けます.最後の手段として、私は完全に気が狂ってVBAコードにすべての可能なイベントを貼り付けてステップスルーするかもしれません.