VBA 中的 ADO 读取 txt/csv 文件但得到的列比预期的少

问题描述 投票:0回答:1

我在 vba 中使用下面的 ADO txt/csv 连接字符串来获取数据,而无需我实际打开 excel。

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FolderPath & ";Extended Properties="text;HDR=Yes;FMT=Delimited(,)";  

Dim rs As New ADODB.Recordset
query = "Select * from  [" & CStr(FileNameArr(i)) & "]"
rs.Open query, conn, adOpenKeyset, adLockOptimistic

我已经成功打开了连接和记录集,但是记录集只有两个不正确的字段。(应该是103)。最奇怪的是,如果我什么都不做打开文件并将其保存为csv或txt,然后再次运行vba,它会成功获取所有列! 该文件实际上不是 txt/csv 文件,而是 .msr 文件。但是我可以用记事本或excel打开它没有任何问题。在执行vba之前,我把.msr的扩展名删掉改成.csv,然后用ADO csv/txt连接串执行VBA拉出数据,如上语句会少一些列

文件内容不是一个严格意义上的表格,它的表头列比数据体少。如果我在 csv 中打开它,第一行中的数据仅存在于 A 列中,但其他行中的数据最多包含 103 列。

我也试过HDR=No但是没用

我尝试了几种解决方法:
<1>.尝试通过ADO保存文件:
因为我知道手动打开文件并保存它会解决问题,所以我尝试在第一行添加一些文本然后在记录集打开时保存文件。
我试过 rs.field(2)="New Text" 然后 rs.Update,
但是在 rs.field(2)="New Text" 处出现错误信息并弹出错误信息:
运行时错误 3251 当前记录集不支持通过此 ISAM 更新
我认为这是因为标题只包含 2 列,即 field(0) 和 field(1),所以我无法更新那里原本不存在的内容。所以,我改成 rs.field(1)="New Text",但仍然是同样的错误信息。
如果我跳到 rs.Update,没关系。但我仍然只有两列。
因此,我尝试了 rs.save Original file full path, adPersistADTG
这给出了runtime error 58: file already exists.
如果我更改为不存在的文件名,则会发生相同的错误。

<2>.try 指定 rs.open 的第 3 和第 4 个参数
通过谷歌搜索,我发现有人说如果我想通过 ADO 更改文件内容,我需要使用

rs.Open query, conn, adOpenKeyset, adLockOptimistic

有人说rs.Open query应该改成table_name
在此线程中回答了 Marcelo Garzzola:
运行时错误3251 当前记录集不支持更新

rs.Open table_name, conn, adOpenKeyset, adLockOptimistic

但这些都不适合我。

<3>.尝试用xls、xlsx、xlsm文件扩展名打开
这种方法在打开连接时很早就失败了,它显示:
数据库错误 0x80004005:外部表不是预期的格式。
我在 vba 中使用一个子过程来打开文件的连接和记录集

Sub OpenConnection(wb As Workbook, addr As String, FileExtensionName As String, IsUseNumberSequenceAsSheetName As Boolean, FullPathArr As Variant, FolderPath As String, FileNameArr As Variant)  
Dim conn As New ADODB.Connection
Dim sht As Worksheet
For i = 1 To UBound(FileNameArr) - LBound(FileNameArr) + 1
    Dim connStr As String: connStr = ADOstr(CStr(FullPathArr(i)), FolderPath, FileExtensionName)
    conn.Open connStr
    Dim query As String
    query = "Select * from  [" & CStr(FileNameArr(i)) & "]"
    Dim rs As New ADODB.Recordset
    rs.Open query, conn, adOpenKeyset, adLockOptimistic
    Dim asht As Worksheet: Set asht = wb.Worksheets.Add(, After:=ActiveSheet)
    If IsUseNumberSequenceAsSheetName Then
        asht.Name = i
    End If
    ReDim Header(0 To rs.Fields.Count - 1)
    With asht
        For h = 0 To rs.Fields.Count - 1
            Header(h) = rs.Fields(h).Name
        Next
        .Range(addr).Resize(1, rs.Fields.Count) = Header
        .Range(addr).Offset(1, 0).CopyFromRecordset rs
    End With
    rs.Close
    conn.Close
Next
End Sub

以上子过程将调用 ADOstr 函数:

Function ADOstr(FullPath As String, FolderPath As String, FileExtension As String) As String
Select Case True
    Case LCase(FileExtension) = "csv" Or LCase(FileExtension) = "txt"
        ADOstr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FolderPath & ";Persist Security Info=False;Extended Properties=""text;HDR=Yes;IMEX=0;FMT=Delimited(;)"";"
    Case LCase(FileExtension) = "xls"
        ADOstr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FullPath & ";Extended Properties=""Excel 8.0;HDR=No;IMEX=0"";"
    Case LCase(FileExtension) = "xlsx" 
        ADOstr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FullPath & ";Extended Properties=""Excel 12.0 Xml;HDR=YES;IMEX=1"";"
    Case LCase(FileExtension) = "xlsb"
        ADOstr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FullPath & "Extended Properties=""Excel 12.0;HDR=YES"";"
    Case LCase(FileExtension) = "xlsm" 
        ADOstr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & FullPath & ";Extended Properties=""Excel 12.0 Macro;HDR=YES;IMEX=1"";"
End Select
End Function

我将在主子程序中调用 OpenConnection 子程序并定义它需要的所有参数,包括文件扩展名,以便 ADOstr 函数可以返回相应的连接字符串。

<4>.尝试在小 csv 文件中复制错误
我在 csv 文件中创建了一个小数据集,其中包含只有 A1 具有值的标题行
和具有 5 列的数据主体。
事实证明,ADO 记录集准确地返回了正确的 5 个字段! 所以我想这个 .msr 文件中可能有一些我看不到的奇怪东西。
由于所有权问题,我无法上传文件。
但我可以说标题行在 A1 单元格中包含 >ver MF01 00.00
从recordset读取后变成:>ver MF01 00#00 in A1 Cell, F2 in B1 Cell

<5> 尝试使用带有各种分隔符的字符串打开连接
我试图将 FMT=Delimited(;) 更改为 FMT=Delimited(,) 到 FMT=Delimited(@) 到 FMT=Delimited( ),我仍然只有两列。
Google(链接下方)以 csv/txt 格式表示,我需要在同一文件夹中有一个 schema.ini 文件,其中存储程序实际使用的分隔符。我试过了,但还是一样。无论我使用什么分隔符,它仍然只返回两列/字段。
ADODB.Connection:分隔符分号不适用于 csv 文本文件
但是 schema.ini 文件确实适用于我为调试创建的小型 csv 文件。它在 schema.ini 中通过分隔符分隔列。

如果有人能指导我,我将不胜感激
如何通过 ADO 或
保存文件 如何在没有任何分隔符的情况下打开 csv 文件,以便所有数据都存在于 ColumnA 中,以便记录集可以检索所有数据
或其他解决方法。

vba ms-access ado
1个回答
0
投票

第一次看到这个,我遇到了一个非常非常相似的问题:Missing column of Dates in CSV file using Schema.ini file

你想要像 CSV 这样的标准化文件格式。如果您在自由文本文件上执行 SELECT *,它没有结构或模式。

在设置了这些属性的 CSV 文件上重试:

Extended Properties="text;HDR=Yes;FMT=Delimited(Tab)";

注意:如果 CSV 格式的 MSR 文件较大,请不要太担心,因为使用 OleDB 驱动程序是 .Net 最快的驱动程序之一,它可以在 13.5 秒内读取 128 MB 的文件:https:/ /stackoverflow.com/a/46418403/495455

© www.soinside.com 2019 - 2024. All rights reserved.