0

我以前的标题在那里引起了一些混乱......更新我最近在使用一些 VBA 连接 Excel 和 Access 时遇到了这个问题。

所以我有一个电子表格,其中包含一个需要导入 Access 数据库的表。该表是通用的,如下所示。

EmployeeNumber  Unused_Field2   Unused_Field3
1                    @@@              @@@
2                    @@@              @@@
3                    @@@              @@@

Access 中的唯一键设置为 EmployeeNumber。

我在 Excel 中的 VBA 代码如下所示:

Sub test()
    Dim con As ADODB.Connection
    Dim rst As ADODB.Recordset

    strcon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\temp\mydb.mdb;"
    strsql = "SELECT * FROM Table1"

    Set con = New Connection
    Set rst = New Recordset

    con.Open strcon
    rst.Open strsql, strcon, adOpenStatic, adLockOptimistic

    For i = 0 To n
        On Error GoTo Errhdl
        rst.AddNew Array("Field1", "Field2", "Field3"), Array(Range("A" & i), Range("B" & i), Range("C" & i))
        On Error GoTo 0
    Next

    Exit Sub

Errhdl:

    Debug.Print "Record" & i & "caused an error"
    Resume Next

End Sub

不幸的是,数据质量不高,我经常会有重复的值导致密钥违规。虽然我虽然 Resume Next 将清除允许另一个“AddNew”运行的错误,但它没有。一个键违规后的所有后续条目都将返回相同的错误。

所以我的问题如下:

  1. 是否可以清除与记录集相关的错误?(作为记录,我试图获取“错误集合”并使用了 Errors.Clear 方法。那没有成功。错误集合是 ADO 对象特有的属性 - MSDN 错误集合
  2. 这可以在不关闭和重新打开记录集的情况下完成吗?

如果需要更多说明,请告诉我!

4

2 回答 2

0

我不会使用错误处理(处理 ADO 错误很棘手),而是在每次执行插入之前使用Find来检查密钥是否不存在。如果键是索引字段(如您的描述所示),那么您可能会考虑Seek哪个对大型数据集更有效。(但是,Seek不适用于客户端光标 - adUseClient。)

这是我发现的一个代码片段,其中概述了这些步骤:

If Not .EOF Then
   .MoveFirst
   .Find "TPItemNbr='" & m_TPItemNbr & "'", , adSearchForward
End If
If .EOF Then
   .AddNew
   !TPItemVendorID = m_TPItemVendorID
   !TPItemNbr = m_TPItemNbr
   !TPItemEUOM = m_TPItemEUOM
   !TPItemUOMFactor = m_TPItemUOMFactor
   !TPItemPUOM = m_TPItemPUOM
   !TPItemDescription = m_TPItemDescription
   !TPItemUnitCost = m_TPItemUnitCost
   !TPItemUnitLabor = m_TPItemUnitLabor
   .Update

也就是说,每次在循环中执行查找,如果 EOF(文件结尾)为真,则键不在表中,因此可以执行插入。

添加以响应有关复合键的更多信息。我会创建一个Command对象并使用Execute. 是的,它需要创建一个字符串,但是您可以捕获并忽略键违规的错误。

替代方案可能是

  • 运行单独的 SQL 语句以获取重复列表的记录集
  • 循环遍历将值存储在数组中
  • 执行AddNew每次检查数组

这对我来说似乎很乱,特别是搜索数组的方面。

  • 追求评论中链接的多查找方法。
于 2013-07-26T19:31:52.697 回答
0

因此,如果 Recordset.AddNew 遇到错误,我找到了解决方案。诀窍是使用 CancelUpdate - MSDN

还可以使用 Status 属性来检查操作是否成功。

示例代码是:

Sub test()
    Dim con As ADODB.Connection
    Dim rst As ADODB.Recordset

    strcon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\temp\mydb.mdb;"
    strsql = "SELECT * FROM Table1"

    Set con = New Connection
    Set rst = New Recordset

    con.Open strcon
    rst.Open strsql, strcon, adOpenStatic, adLockOptimistic

    For i = 0 To n
        On Error GoTo Errhdl
        rst.AddNew Array("Field1", "Field2", "Field3"), Array(Range("A" & i), Range("B" & i), Range("C" & i))
        On Error GoTo 0
    Next

    Exit Sub

Errhdl:

    Debug.Print "Record" & i & "caused an error"
    If rst.Status <> 0 Then
        rst.CancelUpdate
    End If
    Resume Next

End Sub
于 2013-07-31T21:21:47.180 回答