如何使用MS Access中的form_error事件返回描述

时间:2016-06-22 10:06:54

标签: vba ms-access access-vba

我在MS Access中使用form_error事件来捕获错误,这只会给出dataerr integer而不是像vba错误这样的描述,但是MS Website给出了以下事件描述:

  

您可以将DataErr参数与Error函数一起使用来映射   编号为相应的错误消息

但实际上并没有给出这样的例子,我正在努力弄明白。

具体情况是用户将更新子窗体中的记录,某些字段可能会破坏参照完整性规则,该编号只会告诉我参考完整性规则已被破坏,而描述会给我表名称,这允许我给出与发生错误的字段有关的规定性错误消息

有一种简单的方法吗?

4 个答案:

答案 0 :(得分:2)

创建一个单独的函数来执行所有验证,并向用户发送任何遗漏的消息。在表单的beforeupdate事件中运行它,并在需要时取消该事件。这可能会消除你的许多form_error。在form_error事件中,您可以调用相同的函数。它已发现问题,禁止默认消息。如果需要,弹出的任何其他错误都可以单独处理。

答案 1 :(得分:1)

通常只是将数字传递给错误以获取描述:

MsgBox Error(DataErr)

答案 2 :(得分:1)

简而言之

据我所知,除了一个例外,@ AVG的解决方案可能是最佳的解决方法。也就是说,@ AVG可能最好的解决方法是:尝试在Form_BeforeUpdate事件中捕获错误;并(可能根据您的需要)取消Form_BeforeUpdate中的活动。

但是,最好不要在Form_Error级别抑制默认错误。如果您在Form_BeforeUpdate处捕获并取消了该错误,则该错误不会在Form_Error处出现。因此,在这种情况下,无需抑制Form_Error处的错误。但是,如果等待中存在另一种参照完整性违规(例如,类别/组织违规,而不是类别/子类别违规),那么您就没有想到要以开发人员身份进行处理,那么{{{ 1}}会提醒您。您不想因为未发现的错误而隐藏消息。

下面,我提供此变通方法的示例代码。

我还讨论了Form_Error看起来像是一种可能的解决方案,但还不完全可行。也就是说,它可以用于将AccessError(DataErr)号映射到消息。这部分有用。但是,不幸的是,消息是变量 un取代的版本。因此,例如,我们不能在代码中使用DataErr来查询特定的参照完整性违规消息。

使问题更加突出

当用户通过以下形式触发AccessError(DataErr)事件:违反了参照完整性(您已完全设置为防止在无效数据状态下进行此类尝试);违反了在表级别设置的验证规则;否则(?)会产生数据错误。

但是,返回的默认消息可能对用户不友好。例如,在涉及到参照完整性的情况下...

您不能添加或更改记录,因为表'CategorySubcategory'中需要相关记录。

在此示例中,表“ CategorySubcategory”表示表“ Category”和“ CategorySubcategory”之间的多对多关系,定义了属于特定类别的特定子类别。 (在我的示例中)在CategorySubcategory中还表示某些类别没有子类别。

所需要的是一种用用户友好的消息代替用户不友好的消息的方法。为此,可以方便地查询默认错误消息的出现,抑制它并替换您自己的错误消息。

(据我所知),我们在Form_Error中查询默认消息的最接近值为Form_Error。与AccessError(DataErr)不同,Error(DataErr)承诺

Microsoft > Docs > Office VBA Reference > Access > Object model > Application object > Methods > AccessError

...返回与Microsoft Access相关的描述性字符串或 DAO错误 [已添加强调]

[并且保证您可以]使用AccessError方法从表单的Error事件中返回描述性字符串。

因此,您可能会想做类似的事情,如果您可以做类似的事情,那将会很方便。

AccessError

Private Sub Form_Error(DataErr As Integer, Response As Integer) If AccessError(DataErr) Like "*CategorySubcategory*" Then MsgBox "[My user friendly message] Choose the right Subcategory given the Category; or change the Category.", vbOKOnly Or vbExclamation Response = acDataErrContinue ' Suppress default message End If End Sub 可以工作吗?

但是,事实证明AccessError仅返回错误消息的变量 un取代版本,而不返回用户在运行时看到的变量取代消息。例如AccessError返回类似...

您不能添加或更改记录,因为表'|'中需要相关记录。

...而不是...

您不能添加或更改记录,因为表'CategorySubcategory'中需要相关记录。

为证明此情况触发了 data 错误(例如,通过违反参照完整性),

AccessError

观察两个:Private Sub Form_Error(DataErr As Integer, Response As Integer) ' For some reason you'll need to call AccessError(DataErr) before Error(DataErr) Debug.Print "AccessError(DataErr): ", AccessError(DataErr) Debug.Print "Error(DataErr): ", Error(DataErr) End Sub 返回特定消息,其中AccessError返回无用的通用“应用程序定义或对象定义的错误”; Error返回错误消息的变量 un取代版本。

@Hello World正确引用了MS Docs > ... > Form.Error event (Access)

您可以将DataErr参数与Error函数一起使用,以将数字映射到相应的错误消息

即使用AccessError代替了AccessError,@ Hello World的哀叹仍然是公平的...

[MS docs not]实际上给出了一个例子,我正在努力找出答案。

将邮件映射到Error

MS文档作者可能想到的是类似以下的代码

DataErr

要使用该代码,请创建一个新的数据库,将代码放入模块中,将光标置于代码中间,然后按F5键(以运行它)。将创建一个表Function AccessAndJetErrorsTable() As Boolean ' Source: Access 2000 Help "Determine the Error Codes Reserved by Microsoft Access ' and the Microsoft Jet Database Engine" Const strTable As String = "zttblAccessAndJetErrors" Dim cat As New ADOX.Catalog Dim tbl As New ADOX.Table Dim cnn As ADODB.Connection Dim rst As New ADODB.Recordset, lngCode As Long Dim strAccessErr As String Const conAppObjectError = "Application-defined or object-defined error" On Error GoTo Error_AccessAndJetErrorsTable Set cnn = CurrentProject.Connection ' Create Errors table with ErrorNumber and ErrorDescription fields. tbl.Name = strTable tbl.Columns.Append "ErrorCode", adInteger tbl.Columns.Append "ErrorString", adLongVarWChar Set cat.ActiveConnection = cnn cat.Tables.Append tbl ' Open recordset on Errors table. rst.Open strTable, cnn, adOpenStatic, adLockOptimistic ' Loop through error codes. For lngCode = 0 To 35000 On Error Resume Next ' Raise each error. strAccessErr = AccessError(lngCode) DoCmd.Hourglass True ' Skip error numbers without associated strings. If strAccessErr <> "" Then ' Skip codes that generate application or object-defined errors. If strAccessErr <> conAppObjectError Then ' Add each error code and string to Errors table. rst.AddNew rst!ErrorCode = lngCode ' Append string to memo field. rst!ErrorString = strAccessErr rst.Update End If End If Next lngCode ' Close recordset. rst.Close DoCmd.Hourglass False RefreshDatabaseWindow MsgBox strTable & " errors table created." AccessAndJetErrorsTable = True Exit_AccessAndJetErrorsTable: Exit Function Error_AccessAndJetErrorsTable: MsgBox Err & ": " & Err.Description AccessAndJetErrorsTable = False Resume Exit_AccessAndJetErrorsTable End Function ,您可以在其中查找Access和Jet错误消息的所有变量 un取代的版本;并将它们与一个zttblAccessAndJetErrors数字相对应。

该代码将为您提供错误消息的最新列表。但是,作为替代,您可以只查找发布该资源的在线资源。例如。 FMS > Microsoft Access 2010 Error Numbers and Descriptions

因此,通过DataErr或在线查找,您现在可以确定与测试期间看到的错误消息最接近的zttblAccessAndJetErrors号。这样我们就可以做类似...

DataErr

也就是说,我们不直接在Private Sub Form_Error(DataErr As Integer, Response As Integer) Select Case DataErr Case 3201 ' "You cannot add or change a record because a related record is required in table '|'." MsgBox "[My user friendly message] Choose the right Subcategory given the Category; or change the Category.", vbOKOnly Or vbExclamation Response = acDataErrContinue ' Suppress default message End Select End Sub 中使用AccessError返回消息。而是我们使用了Form_Error(或依靠其他人使用过的)来生成DataErr / Message映射。在AccessError中,我们仅继续与Form_Error数字匹配。但是现在我们可以将相关消息复制为我们的DataErr号的注释。

但是,至少在这种参照完整性(DataErr 3201)的情况下,我们的问题仍然存在。如果像上面的代码一样,针对特定的引用完整性违例(例如类别/子类别不匹配)取消了默认消息,则可能会掩埋其他特定的引用完整性违例。例如。如果针对用户选择的类别和组织发生了另一个参照完整性违规,则上述代码将错误地(以用户友好的方式)错误地表示发生了类别/子类别违规。

可能的最佳可行解决方法

据我所知,@ AVG的解决方案可能是最好的解决方法,只有一个例外。也就是说,@ AVG可能最好的解决方法是:尝试在DataErr事件中捕获错误;并(可能根据您的需要)取消Form_BeforeUpdate中的活动。

但是,最好不要在Form_BeforeUpdate级别抑制默认错误。如果您在Form_Error处捕获并取消了该错误,则该错误不会在Form_BeforeUpdate处出现。因此,在这种情况下,无需抑制Form_Error处的错误。但是,如果等待中存在另一种参照完整性违规(例如,类别/组织违规,而不是类别/子类别违规),那么您就没有想到要作为开发人员来处理,那么{{{ 1}}会提醒您。您不想因为未发现的错误而隐藏消息。

因此,就我而言,解决方法代码看起来像(必须按照@Hello World的建议“沿DLookup路线走”)。

Form_Error

答案 3 :(得分:0)

我总是使用下面的代码模式,以便用户可以获得正确的错误消息,然后他们可以向我传达以了解原因。

<img ng-src="{{ a.hero }}"></img>

对代码中使用的每个Private Sub cmdSearch_Click() On Error GoTo Sub_Err --Your code here--- 'errors catching stuff Sub_Exit: Exit Sub Sub_Err: MsgBox Error$ Resume Sub_Exit End Sub 使用相同的内容。