【问题标题】:ADO (Excel, ACE OLEDB 12.0) does not compare Key-Strings case-sensitiveADO (Excel, ACE OLEDB 12.0) 不比较 Key-Strings 区分大小写
【发布时间】:2016-03-30 20:21:15
【问题描述】:

问题描述:在字母数字字符串上使用 Excel 和 ADO (ACE OLEDB 12.0) 连接 2 个表时,ADO 不区分键“a12a”和“A12a”(它将它们视为相同,即不区分大小写)。但是,我的数据中有字母数字键。 Join 会错误链接数据!

我在 Excel 工作簿中构建了一个小示例来重现该行为。 Excel 工作簿包含 3 张工作表:

  1. AlphaNum1
  2. AlphaNum2
  3. 结果

AlphaNum1 Sheet 包含以下数据

Key   Val
a12b    1
A12b    2
a12B    3
A12B    4
e12f    7
E12F    8
1234    9

AlphaNum2 Sheet 包含以下数据:

Key   Val
a12b    1
A12b    2
a12B    3
A12B    4
c12d    5
C12D    6
1234    9

我使用以下 VBA 代码连接到 ADO 并加入表(LEFT JOIN):

Sub AlphaNumTest()
    Dim oAdoConnection As New ADODB.Connection
    Dim oAdoRecordset As New ADODB.Recordset
    Dim sAdoConnectString As String, sPfad As String
    Dim sQuery As String
    On Error GoTo ExceptionHandling
    sPfad = ThisWorkbook.FullName
    sAdoConnectString = "Provider=Microsoft.ACE.OLEDB.12.0; Extended Properties='Excel 12.0 Xml;HDR=YES;';Data Source=" & sPfad

    oAdoConnection.Open sAdoConnectString
    sQuery = "Select a1.[Key], a2.[Val] from [AlphaNum1$] a1 LEFT JOIN [AlphaNum2$] a2 ON a1.[Key] = a2.[Key]"
    With oAdoRecordset
        .Source = sQuery
        .ActiveConnection = oAdoConnection
        .Open
    End With

    Dim writeRange As Range
    Dim headerRange As Range

    'Set headerRange = ThisWorkbook.Sheets("WriteHere").Range("A1")
    Set writeRange = ThisWorkbook.Sheets("Result").Range("A2")

    ' print the table header from recordset
    For i = 0 To oAdoRecordset.Fields.Count - 1
        ' careful! the recordset is zero-indexed like it should be! Excel table however starts at index one, thus the i+1~
        ThisWorkbook.Sheets("Result").Cells(1, i + 1).Value = oAdoRecordset.Fields(i).Name
        ' set bold
        ThisWorkbook.Sheets("Result").Cells(1, i + 1).Font.Bold = True
    Next i

    ' print the data directly from recordset!
    writeRange.CopyFromRecordset oAdoRecordset


CleanUp:
    On Error Resume Next ' Lazy skip
    oAdoRecordset.Close
    oAdoConnection.Close
    Set oAdoRecordset = Nothing
    Set oAdoConnection = Nothing
    Exit Sub
ExceptionHandling:
    MsgBox "Fehler: " & Err.Description
    Resume CleanUp
End Sub

请注意,我使用 INNER 还是 LEFT JOIN 并不重要;结果是错误的方式 - 在此示例中,我使用 LEFT JOIN 来演示行为。

Result 输出是 AlphaNum1.Key 和 AlphaNum2.Val 通过 LEFT JOIN 连接。

预期结果(我加入时使用“=”而不是 LIKE...)是:

Key   Val
a12b    1
A12b    2
a12B    3
A12B    4
e12f    
E12F    
1234    9

但是 ADO 给了我实际结果(它不区分 Keys 大小写...):

Key   Val
a12b    4
a12b    3
a12b    2
a12b    1
A12b    4
A12b    3
A12b    2
A12b    1
a12B    4
a12B    3
a12B    2
a12B    1
A12B    4
A12B    3
A12B    2
A12B    1
e12f    
E12F    
1234    9

知道为什么 ADO 会这样吗?任何想法如何/如果我可以改变行为?

【问题讨论】:

  • 这已经被问及回答here
  • 感谢您的回复 - 但是如何使用 ADO 解决问题?当我添加排序规则(使用 COLLATE latin1_bin)打开 RecordSet 时出现错误。使用 BINARY 我得到一个语法错误。 ADO 中有不同的关键字吗?
  • 嗯,我的错,我没有仔细阅读你的问题。问题不在于 ADO(ADO 只是中间人),而在于数据库引擎。据我所知,Excel 中的 ACE OLEDB 不支持 COLLATE。您似乎找到了自己的解决方案:)
  • 该解决方案有效,但它确实降低了性能......好吧,我猜是情不自禁;)

标签: excel ms-access vba ado


【解决方案1】:

我找到了 ADO 的解决方法。似乎COLLATE 不存在(参见:http://www.utteraccess.com/forum/Collate-Access-t1940463.html)。

可以使用 StrComp 并将其设置为二进制比较:

sQuery = "Select a1.[Key], a2.[Val] from [AlphaNum1$] a1 LEFT JOIN [AlphaNum2$] a2 **ON StrComp(a1.[Key], a2.[Key], 0)=0**"

如果有更好的解决方案,我很乐意提供更多建议:)

【讨论】:

  • 就是这样。
  • 有没有什么方法可以不让性能下降太多?我有很多数据要处理,现在使用 StrComp 需要几个小时(之前需要几秒钟)。
【解决方案2】:

您可以为每个表添加一个新的索引文本字段,然后使用下面的函数用值填充它,然后使用这些字段以正常方式连接表:

Public Function StrToByte(ByVal strChars As String) As String

  Dim abytChar()  As Byte
  Dim lngChar     As Long
  Dim strByte     As String

  abytChar() = StrConv(strChars, vbFromUnicode)

  strByte = Space(2 * (1 + UBound(abytChar) - LBound(abytChar)))
  For lngChar = LBound(abytChar) To UBound(abytChar)
    Mid(strByte, 1 + 2 * lngChar) = Hex(abytChar(lngChar))
  Next

  StrToByte = strByte

End Function

它会产生像这样的键:

StrToByte("a12b") -> 61313262
StrToByte("A12b") -> 41313262

【讨论】:

  • 好主意,谢谢。我知道该函数将字符串转换为字节,但我不太了解细节。它有多可靠?是否有可能对不同的字符串产生相同的结果?
  • 不,它转换为字节数组,该数组使用每个字符的十六进制表示形式作为字符串写出。我不明白你为什么认为这些不应该是独一无二的。
【解决方案3】:

只是为了报告我已经复制了您的示例,并在第一时间得到了“预期结果”,您的代码没有任何修改

我正在使用 Excel 2007 和 ADO 2.8

【讨论】:

  • 是的,但由于“声誉”,我无法在其他帖子中发表评论......
猜你喜欢
  • 1970-01-01
  • 2011-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 2012-04-18
相关资源
最近更新 更多