我之前的标题引起了一些混乱......更新了 我最近在使用一些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”运行,但它没有。 一次密钥违规后的所有后续条目将返回相同的错误。
所以我的问题如下:
如果需要进一步澄清,请告诉我们!
答案 0 :(得分: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
。是的,它需要创建一个字符串,但您可以捕获并忽略关键违规的错误。
替代方案可能是
AddNew
这对我来说似乎很麻烦,特别是搜索数组的方面。
答案 1 :(得分: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