Workbooks.OpenText 未正确解析 csv 文件 Excel 2016

Workbooks.OpenText not parsing csv files properly Excel 2016

我很确定这在以前的 Excel

版本中工作正常

测试文件:

d/mm/yyyy hh:mm:ss
5/12/1999 6:01:12
30/11/2001 5:00:00

并且日期和时间之间的分隔符是一个Space(ASCII码32)

我的 Windows 区域设置是 mdy,我的 Excel 版本是 2016


Option Explicit
Sub foo()
    Dim WB As Workbook
    Dim sFN As String
    Dim FD As FileDialog

Set FD = Application.FileDialog(msoFileDialogFilePicker)

With FD
    .AllowMultiSelect = False
    .Filters.Add "Text or CSV", "*.txt, *.csv", 1
    .Show
    sFN = .SelectedItems(1)
End With

Workbooks.OpenText Filename:=sFN, DataType:=xlDelimited, origin:=437, _
        TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Tab:=False, _
        Semicolon:=False, Comma:=False, Space:=True, Other:=False, _
        FieldInfo:=Array(Array(1, xlDMYFormat), Array(2, xlGeneralFormat))


Set WB = ActiveWorkbook

End Sub

看来这可能与此线程中解决的问题相同:

CSV files are Character Separated Value files, not Comma separated. For more than half the world the separator character is semicolon (;), not a comma (,)

Excel 2016 properly respects your Windows regional settings, and uses the specified "List separator" character

One solution is to change your regional settings for the "List separator" attribute to the character you want Excel to default to using, e.g. a comma (,)

This can be changed in:

Control Panel / Region / Additional Settings / List separator:

CSVText 实际上 Excel 不同 。不仅 CSV 的定界符设置非常特殊,而且 不能 使用 Workbooks.OpenText 中的参数设置。打开 CSV 文件时,也不会考虑字段类型 (FieldInfo) 等其他参数。而且 unicode 处理对于 CSV 来说是一个非常特殊的情况,并且与 Text.

有明显的不同

您可以像这样尝试使用 QueryTables

Sub foo1()
    Dim WB As Workbook
    Dim sFN As String
    Dim FD As FileDialog

Set FD = Application.FileDialog(msoFileDialogFilePicker)

With FD
    .AllowMultiSelect = False
    .Filters.Add "Text or CSV", "*.txt, *.csv", 1
    .Show
    sFN = .SelectedItems(1)
End With

Set WB = Workbooks.Add

With WB.Worksheets(1).QueryTables.Add(Connection:= _
    "TEXT;" & sFN & "", Destination:=Range("$A"))
    .Name = "test"
    .TextFileParseType = xlDelimited
    .TextFileTextQualifier = xlTextQualifierDoubleQuote
    .TextFileConsecutiveDelimiter = True
    .TextFileTabDelimiter = False
    .TextFileSemicolonDelimiter = False
    .TextFileCommaDelimiter = False
    .TextFileSpaceDelimiter = True
    .TextFileColumnDataTypes = Array(xlDMYFormat, xlGeneralFormat)
    .Refresh BackgroundQuery:=False
End With

End Sub

但是使用 QueryTables 当然你必须小心,不要在没有必要的情况下多次添加它们,而是刷新它们或者先删除它们然后再添加它们。

感谢大家的建议。在可能的解决方案中,为了我的目的,我决定从文件中删除 *.csv 后缀。这有效并且可以适应。 QueryTable 方法也可以工作,以及 Axel 发布的警告。

如果有人感兴趣,这是适用于我的方法的代码。


Option Explicit
Sub foo()
    Dim WB As Workbook, wbCSV As Workbook, swbCSV As String
    Dim sFN As String, sCopyFN
    Dim FD As FileDialog

Set WB = ThisWorkbook
Set FD = Application.FileDialog(msoFileDialogFilePicker)

With FD
    .AllowMultiSelect = False
    .Filters.Add "Text or CSV", "*.txt, *.csv", 1
    .Show
    sFN = .SelectedItems(1)
End With

'If CSV, remove suffix
sCopyFN = ""
If sFN Like "*.csv" Then
    sCopyFN = Left(sFN, Len(sFN) - 4)
    FileCopy sFN, sCopyFN
    sFN = sCopyFN
End If

Workbooks.OpenText Filename:=sFN, DataType:=xlDelimited, origin:=437, _
        TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=True, Tab:=False, _
        Semicolon:=False, Comma:=False, Space:=True, Other:=False, _
        FieldInfo:=Array(Array(1, xlDMYFormat), Array(2, xlGeneralFormat))

Set wbCSV = ActiveWorkbook

'Get path as string since it will not be available after closing the file
swbCSV = wbCSV.FullName

'Move the data into this workbook
Dim rCopy As Range, rDest As Range

With WB.Worksheets("sheet1")
    Set rDest = .Cells(.Rows.Count, 1).End(xlUp)
End With
Set rCopy = wbCSV.Sheets(1).UsedRange

rCopy.Copy rDest

'must close the file before deleting it
wbCSV.Close False
Kill swbCSV

End Sub

巩固我的实验和 Axel Richter 的回答 with dwirony's answer to a related question :

  1. 通过 OpenTextOpen 导入具有 .csv 扩展名的 CSV 文件会将所有日期视为 MDY(美国)格式。
  2. OpenText 忽略扩展名为 .csv 的 CSV 文件的所有格式选项。
  3. 对于扩展名为 .txt 并使用 xlDelimited 选项的 CSV 文件,OpenText 会考虑 FileInfo 参数,但会忽略列号,因此数组从 1 开始的每一列都必须存在元素,直到描述了具有 non-default 格式的所有列。

令人沮丧的是用户界面工作正常(包括默认为区域日期格式),但 VBA 界面存在这些问题。

问题存在于 Excel 2013 年和 Excel 2016 年。