在Access 2013表单上捕获更改时的保留错误

时间:2018-12-27 16:07:23

标签: vba ms-access

我正在使用Access 2013表单中以下链接中的代码来捕获对记录所做的更改:https://www.techrepublic.com/article/a-simple-solution-for-tracking-changes-to-access-data/

我已将import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { HttpClientModule } from '@angular/common/http'; import { CleanupComponent } from './cleanup.component'; import { OrganisationsApiService } from 'src/app/api/organisations/organisations-api.service'; describe('CleanupComponent', () => { let component: CleanupComponent; let fixture: ComponentFixture<CleanupComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ CleanupComponent ], imports : [HttpClientModule], providers : [OrganisationsApiService ] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(CleanupComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); }); 注释掉,并在ModalWipedAll这一行中得到了ErrorHandler。这将导致该语句不读取 True 并被跳过。

我在评论表单上的BeforeUpdate触发器中称此"<Reserved Error>"

If (.Value <> .OldValue or ((Not IsNull ...

1 个答案:

答案 0 :(得分:1)

通过在MS Access'QueryDef.Parameters中使用参数化查询,在应用程序层(即VBA)上使用SQL时,请考虑行业标准,我认为这是问题的症结所在。

使用这种方法,您可以将SQL与VBA分开,以提高可读性和可维护性,而无需将其连接或用引号引起来。您上面的链接运行了VBA串联的SQL字符串,奇怪的是没有将两个重复的If块组合在一起:

SQL (与其他任何MS Access查询一样)

PARAMETERS paramEditDate Date, paramUser Text(255), paramRecordID Long, 
           paramSourceTable Text(255), paramSourceField Text(255), 
           paramBeforeValue Text(255), paramAfterValue Text(255), paramChangeReason Text(255);
INSERT INTO xAudit (EditDate, [User], RecordID, SourceTable
                    SourceField, BeforeValue, AfterValue, ChangeReason)
VALUES (paramEditDate, paramUser, paramRecordID, paramSourceTable,
        paramSourceField, paramBeforeValue, paramAfterValue, paramChangeReason);

VBA (将表单名称作为参数并使用Forms()集合)

Sub ReviewFormAuditTrail(frm_name As String, recordid As Control)
On Error GoTo ErrHandler    
    '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, varAfter As Variant, ChangeReason As Variant
    Dim strControlName As String, strSQL As String
    Dim qdef As QueryDef

    'Get changed values.
    For Each ctl In Forms(frm_name).Controls
       With ctl
          'Avoid labels and other controls with Value property.
          If .ControlType = acComboBox Or .ControlType = acTextBox Then
             'Changed this is allow for both null to value and value to null
              If (.Value <> .OldValue) Or ((Not IsNull(.OldValue) And IsNull(.Value))) _
                Or ((IsNull(.OldValue) And Not IsNull(.Value))) Then

                   varBefore = .OldValue
                   varAfter = .Value
                   strControlName = .Name
                   ChangeReason = Forms![Review Form]!ChangeReason

                   ' RETRIEVE SAVED QUERY
                   Set qdef = CurrentDb.QueryDefs("mySavedQuery")

                   ' BIND PARAMS
                   qdef!paramEditDate = Now()
                   qdef!paramUser = Environ("username")
                   qdef!paramRecordID = recordid.Value
                   qdef!paramSourceTable = Forms(frm_name).RecordSource
                   qdef!paramSourceField = strControlName
                   qdef!paramBeforeValue = varBefore
                   qdef!paramAfterValue = varAfter
                   qdef!paramChangeReason = ChangeReason

                   ' EXECUTE QUERY
                   qdef.Execute dbFailOnError

              End If
          End if
       End With
    Next ctl

ExitHandler:
   Set ctl = Nothing: Set qdef = Nothing
   Exit Sub 

ErrHandler:
  MsgBox Err.Description & vbNewLine & Err.Number, vbOKOnly, "Runtime Error"
  Resume ExitHandler
End Sub