关于excel:处理AddNew键冲突ADODB.Recordset

Handling AddNew Key Violations ADODB.Recordset

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

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

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

Access中的唯一键设置为EmployeeNumber。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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"运行的错误,但事实并非如此。
一键违反后的所有后续条目将返回相同的错误。

所以我的问题如下:

  • 是否有清除与记录集相关的错误的方法? (为了记录,我尝试获取"错误集合"并使用
    方法Errors.Clear。那并没有解决问题。错误集合是特定于ADO对象的属性-MSDN错误集合)
  • 可以在不关闭并重新打开记录集的情况下完成此操作吗?
  • 请让我知道是否需要进一步说明!


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

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

    示例代码为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    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

    我不会使用错误处理(处理ADO错误很棘手),但是在执行插入操作之前,请使用"查找"来每次检查键是否不存在。如果键是索引字段(如您的描述所建议),则可以考虑Seek,它对于大型数据集更有效。 (但是,Seek不适用于客户端光标-adUseClient。)

    这是我发现的代码片段,概述了步骤:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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(文件末尾)为true,则表中尚未包含该键,因此可以执行插入操作。

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

    替代方案可能是

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

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

    • 执行注释中链接的多查找方法。