Описание проблемы: при объединении двух таблиц с использованием Excel и ADO (ACE OLEDB 12.0) в алфавитно-цифровых строках ADO не различает клавиши «a12a», и «A12a» (они рассматривают их так, как если бы они были одинаковыми, т.е. без учета регистра). У меня, однако, есть буквенно-цифровые клавиши в моих данных. Соединение свяжет данные неправильно!ADO (Excel, ACE OLEDB 12.0) не сравнивается с ключевыми строками, чувствительными к регистру
Я построил небольшой пример в книге Excel, чтобы воспроизвести поведение. в программе Excel Учебное пособие содержит 3 листов:
- AlphaNum1
- AlphaNum2
- Результат
AlphaNum1 Лист содержит следующие данные
Key Val
a12b 1
A12b 2
a12B 3
A12B 4
e12f 7
E12F 8
1234 9
AlphaNum2 лист содержит следующие данные:
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
Обратите внимание, что это не имеет значения, если я использую внутренний или LEFT JOIN; результат неправильный, а в этом примере я использую LEFT JOIN для демонстрации поведения.
Результат результата: AlphaNum1.Key и AlphaNum2.Val, соединенный LEFT JOIN.
Ожидаемый результат (Я присоединяюсь с помощью "=" не НРАВИТСЯ ...) является:
Key Val
a12b 1
A12b 2
a12B 3
A12B 4
e12f
E12F
1234 9
Но ADO дает мне Фактический результат (он рассматривает случай Ключи нечувствительным .. .):
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 ведет себя, как это? Любые идеи о том, как/если я могу изменить поведение?
Это уже было задано и ответили [здесь] (http://stackoverflow.com/questions/29533346/join-2-tables-case-sensitive-upper-and-lower-case) – leowyn
Спасибо для ответа - но как решить проблему с помощью ADO? Когда я добавляю сортировку (используя COLLATE latin1_bin), я получаю сообщение об ошибке при открытии RecordSet. Используя BINARY, я получаю синтаксическую ошибку. Есть ли ключевое слово в ADO? – dakami
Хм, я плохо, я недостаточно внимательно изучил ваш вопрос. Проблема не в ADO (ADO - это просто переход), это с движком базы данных. Из того, что я могу найти, ACE OLEDB в Excel не поддерживает COLLATE. Кажется, вы нашли свое собственное решение :) – leowyn