如何在Excel 2010中用VBA查询UTF-8编码的CSV文件?

我想用以下数据库连接在Excel 2010中使用VBA查询UTF-8编码的CSV文件:

provider=Microsoft.Jet.OLEDB.4.0;;data source='xyz';Extended Properties="text;HDR=Yes;FMT=Delimited(,);CharacterSet=65001" 

所有的CSV文件都以BOM \ xEF \ xBB \ xBF和标题行开头。 不知怎的,BOM不能被正确识别,第一列标题被读作“?header_name”,也就是说问号被前置了。 我已经尝试了不同的CharacterSets,我也尝试使用Microsoft.ACE.OLEDB.12.0,但一切都没有成功。

这是一个已知的错误,或者有什么办法来获得正确的第一列标题名称,而不改变源文件的编码?

以下过程将整个CSV文件提取到新工作Sheet ,从头文件中清除BOM 。 它具有path,文件名和BOMstring作为variables来提供灵活性。

使用此过程来调用查询过程

 Sub Qry_Csv_Utf8() Const kFile As String = "UTF8 .csv" Const kPath As String = "D:\StackOverFlow\Temp\" Const kBOM As String = "\xEF\xBB\xBF" Call Ado_Qry_Csv(kPath, kFile, kBOM) End Sub 

这是查询过程

 Sub Ado_Qry_Csv(sPath As String, sFile As String, sBOM As String) Dim Wsh As Worksheet Dim AdoConnect As ADODB.Connection Dim AdoRcrdSet As ADODB.Recordset Dim i As Integer Rem Add New Sheet - Select option required 'With ThisWorkbook 'Use this if procedure is resident in workbook receiving csv data 'With Workbooks(WbkName) 'Use this if procedure is not in workbook receiving csv data With ActiveWorkbook 'I used this for testing purposes Set Wsh = .Sheets.Add(After:=.Sheets(.Sheets.Count)) 'Wsh.Name = NewSheetName 'rename new Sheet End With Set AdoConnect = New ADODB.Connection AdoConnect.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _ "Data Source=" & sPath & ";" & _ "Extended Properties='text;HDR=Yes;FMT=Delimited(,);CharacterSet=65001'" Set AdoRcrdSet = New ADODB.Recordset AdoRcrdSet.Open Source:="SELECT * FROM [" & sFile & "]", _ ActiveConnection:=AdoConnect, _ CursorType:=adOpenDynamic, _ LockType:=adLockReadOnly, _ Options:=adCmdText Rem Enter Csv Records in Worksheet For i = 0 To -1 + AdoRcrdSet.Fields.Count Wsh.Cells(1, 1 + i).Value = _ WorksheetFunction.Substitute(AdoRcrdSet.Fields(i).Name, sBOM, "") Next Wsh.Cells(2, 1).CopyFromRecordset AdoRcrdSet End Sub 

我发现这个问题唯一的解决scheme是使用Schema.ini文件。

我的testingCSV文件

 Col_A;Col_B;Col_C Some text example;123456789;3,14 

在这里输入图像说明

Schema.ini为我的testingCSV文件

 [UTF-8_Csv_With_BOM.csv] Format=Delimited(;) Col1=Col_A Text Col2=Col_B Long Col3=Col_C Double 

Schema.ini文件包含源csv文件的名称并描述了我的列。 每列由其名称和types指定,但您可以指定更多信息。 该文件必须位于与csv文件相同的文件夹中 。 更多信息在这里 。

最后是读取csv文件的VBA代码。 请注意, HDR=No 这是因为在Schema.ini中定义了列标题。

 ' Add reference to Microsoft ActiveX Data Objects 6.1 Library Sub ReadCsv() Const filePath As String = "c:\Temp\StackOverflow\" Const fileName As String = "UTF-8_Csv_With_BOM.csv" Dim conn As ADODB.Connection Dim rs As New ADODB.Recordset Set conn = New ADODB.Connection conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & filePath & _ "';Extended Properties='text;HDR=No;FMT=Delimited()';" With rs .ActiveConnection = conn .Open "SELECT * FROM [" & fileName & "]" If Not .BOF And Not .EOF Then While (Not .EOF) Debug.Print rs.Fields("Col_A") & " " & _ rs.Fields("Col_B") & " " & _ rs.Fields("Col_C") .MoveNext Wend End If .Close End With conn.Close Set conn = Nothing End Sub 

产量

 Some text example 123456789 3,14