Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vba 在MS Access表单控件(即文本框)为空时跟踪表单中更改的数据_Vba_Ms Access_Audit Logging - Fatal编程技术网

Vba 在MS Access表单控件(即文本框)为空时跟踪表单中更改的数据

Vba 在MS Access表单控件(即文本框)为空时跟踪表单中更改的数据,vba,ms-access,audit-logging,Vba,Ms Access,Audit Logging,我使用MS Access数据库,为了跟踪用户活动,我使用了以下VBA模块: 在下面的代码中,我的访问表单文本框中的每一项更改都以“Audit”的名称插入到日志表中 选项比较数据库 常量干熄焦为字符串“” 子审核跟踪(frm作为表单,recordid作为控件) '跟踪对数据的更改。 'recordid标识frm中pk字段的相应控件,以便标识记录。 Dim-ctl作为对照 作为变体的Dim varBefore Dim varAfter作为变体 Dim strControlName作为字符串 作为字符

我使用MS Access数据库,为了跟踪用户活动,我使用了以下VBA模块: 在下面的代码中,我的访问表单文本框中的每一项更改都以“Audit”的名称插入到日志表中

选项比较数据库
常量干熄焦为字符串“”
子审核跟踪(frm作为表单,recordid作为控件)
'跟踪对数据的更改。
'recordid标识frm中pk字段的相应控件,以便标识记录。
Dim-ctl作为对照
作为变体的Dim varBefore
Dim varAfter作为变体
Dim strControlName作为字符串
作为字符串的Dim strSQL
关于错误转到错误处理程序
'获取更改的值。
对于frm.控件中的每个ctl
带ctl
'避免标签和其他具有Value属性的控件。
如果.ControlType=acTextBox,则
如果.Value.OldValue,则
varBefore=.OldValue
varAfter=.Value
strControlName=.Name
'生成INSERT INTO语句。
strSQL=“插入到”_
&审核(EditDate、RecordID、SourceTable、_
&SourceField,BeforeValue,AfterValue)_
&“值(现在为(),”_
&cDQ&recordid.Value&cDQ&“_
&干熄焦和frm.RecordSource和干熄焦_
&干熄焦名称和干熄焦名称_
&干熄焦、变风量和干熄焦_
&干熄焦&varAfter&cDQ&“
'在即时窗口中查看已计算语句。
调试.打印strSQL
DoCmd.SetWarnings错误
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
如果结束
如果结束
以
下一个
设置ctl=Nothing
出口接头
错误处理程序:
MsgBox错误说明和vbNewLine_
&错误编号,仅限vbOKOnly,“错误”
端接头
我可以在表单的更新前事件中使用上述代码。当我的文本框已经有一个值时,它可以完美地工作,但是当这些文本框为空时,子例程就不工作了。
如果您有任何建议,我们将不胜感激。

虽然wazz共享的方法只要文本字段中没有引号就行,但这不是解决问题的方法

正确的方法是使用参数。这样可以防止在文本字段包含引号时发生SQL注入和错误。这也将避免出现
DoCmd.SetWarnings
代码

strSQL = "INSERT INTO " _
           & "Audit (EditDate, RecordID, SourceTable, " _
           & " SourceField, BeforeValue, AfterValue) " _
           & "VALUES (Now(), ?, ?, ?, ?, ?)"
With CurrentDb.CreateQueryDef("", strSQL)
    .Parameters(0) = recordid.Value
    .Parameters(1) = frm.RecordSource
    .Parameters(2) = strControlName 
    .Parameters(3) = varBefore 
    .Parameters(4) = varAfter
    .Execute
End With
全面实施:

Sub AuditTrail(frm As Form, recordid As Control)
  'Track changes to data.
  'recordid identifies the pk field's corresponding control in frm, in order to id record.
  Dim ctl As Control
  Dim varBefore As Variant
  Dim varAfter As Variant
  Dim strControlName As String
  Dim strSQL As String
  On Error GoTo ErrHandler
  'Get changed values.
  For Each ctl In frm.Controls
    'Avoid labels and other controls with Value property.
    If ctl.ControlType = acTextBox Then
      If ctl.Value <> ctl.OldValue Then
        varBefore = ctl.OldValue
        varAfter = ctl.Value
        strControlName = ctl.Name
        'Build INSERT INTO statement.
        strSQL = "INSERT INTO " _
           & "Audit (EditDate, RecordID, SourceTable, " _
           & " SourceField, BeforeValue, AfterValue) " _
           & "VALUES (Now(), ?, ?, ?, ?, ?)"
        With CurrentDb.CreateQueryDef("", strSQL)
            .Parameters(0) = recordid.Value
            .Parameters(1) = frm.RecordSource
            .Parameters(2) = strControlName 
            .Parameters(3) = varBefore 
            .Parameters(4) = varAfter
            .Execute
        End With
      End If
      End If
  Next
  Set ctl = Nothing
  Exit Sub

ErrHandler:
  MsgBox Err.Description & vbNewLine _
   & Err.Number, vbOKOnly, "Error"
End Sub
子审计跟踪(frm作为表单,recordid作为控件)
'跟踪对数据的更改。
'recordid标识frm中pk字段的相应控件,以便标识记录。
Dim-ctl作为对照
作为变体的Dim varBefore
Dim varAfter作为变体
Dim strControlName作为字符串
作为字符串的Dim strSQL
关于错误转到错误处理程序
'获取更改的值。
对于frm.控件中的每个ctl
'避免标签和其他具有Value属性的控件。
如果ctl.ControlType=acTextBox,则
如果ctl.Value ctl.OldValue,则
varBefore=ctl.OldValue
varAfter=ctl.Value
strControlName=ctl.Name
'生成INSERT INTO语句。
strSQL=“插入到”_
&审核(EditDate、RecordID、SourceTable、_
&SourceField,BeforeValue,AfterValue)_
&“值(现在为(),?,?,?,?,?)”
使用CurrentDb.CreateQueryDef(“,strSQL)
.参数(0)=记录ID.值
.参数(1)=frm.RecordSource
.参数(2)=strControlName
.参数(3)=varBefore
.参数(4)=varAfter
.执行
以
如果结束
如果结束
下一个
设置ctl=Nothing
出口接头
错误处理程序:
MsgBox错误说明和vbNewLine_
&错误编号,仅限vbOKOnly,“错误”
端接头

现在您只需检查当前值。您必须添加另一个if/then来检查文本框是否为null或“”。您是对的。我刚刚添加了一些代码来检查文本框中的空值。而且效果很好!谢谢你,瓦兹。非常感谢你的回答。这肯定比以前的解决方案好。
Sub AuditTrail(frm As Form, recordid As Control)
  'Track changes to data.
  'recordid identifies the pk field's corresponding control in frm, in order to id record.
  Dim ctl As Control
  Dim varBefore As Variant
  Dim varAfter As Variant
  Dim strControlName As String
  Dim strSQL As String
  On Error GoTo ErrHandler
  'Get changed values.
  For Each ctl In frm.Controls
    'Avoid labels and other controls with Value property.
    If ctl.ControlType = acTextBox Then
      If ctl.Value <> ctl.OldValue Then
        varBefore = ctl.OldValue
        varAfter = ctl.Value
        strControlName = ctl.Name
        'Build INSERT INTO statement.
        strSQL = "INSERT INTO " _
           & "Audit (EditDate, RecordID, SourceTable, " _
           & " SourceField, BeforeValue, AfterValue) " _
           & "VALUES (Now(), ?, ?, ?, ?, ?)"
        With CurrentDb.CreateQueryDef("", strSQL)
            .Parameters(0) = recordid.Value
            .Parameters(1) = frm.RecordSource
            .Parameters(2) = strControlName 
            .Parameters(3) = varBefore 
            .Parameters(4) = varAfter
            .Execute
        End With
      End If
      End If
  Next
  Set ctl = Nothing
  Exit Sub

ErrHandler:
  MsgBox Err.Description & vbNewLine _
   & Err.Number, vbOKOnly, "Error"
End Sub