VBA使用ADO读取.msr转CSV文件列数缺失的问题求助
我用VBA的ADO文本/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
已成功建立连接并打开记录集,但记录集仅返回2个字段,与预期的103列不符。奇怪的是,手动打开文件并另存为CSV/TXT格式后,再运行VBA就能正常获取所有列。
目标文件本质是.msr格式,非标准TXT/CSV,但可通过记事本或Excel正常打开。我先将扩展名改成.csv,再用ADO的CSV连接字符串拉取数据,就出现列缺失问题。文件内容非标准表格:表头行的列数远少于数据行,CSV中第一行数据仅在A列,其他行最多有103列。试过设置HDR=No,无效。
已尝试的解决方法
1. 通过ADO保存文件
因为手动保存能解决问题,尝试打开记录集后修改第一行内容再保存:执行rs.field(2)="New Text"后调用rs.Update,触发运行时错误3251:当前记录集不支持此ISAM的更新操作;修改rs.field(1)仍报错;跳过rs.Update能执行,但还是只返回2列。尝试rs.Save 原文件完整路径, adPersistADTG,触发运行时错误58:文件已存在,改成新文件名仍报错。
2. 修改rs.Open的参数
搜索后尝试调整rs.Open的第3、4个参数为adOpenKeyset, adLockOptimistic,或者把查询语句改成直接指定表名,均无效。
3. 尝试以Excel格式连接
把文件扩展名改成xls、xlsx、xlsm后用对应ADO连接字符串,连接阶段直接失败,报错数据库错误0x80004005:外部表不是预期格式。相关连接字符串生成代码如下:
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
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
4. 小型测试文件复现
创建表头仅A1有值、数据行含5列的CSV,ADO能正常返回5个字段,推测问题源于.msr文件的特殊内容。原.msr文件表头行A1内容为**>ver MF01 00.00**,用ADO读取后变成**>ver MF01 00#00**(A列)和F2(B列)。
5. 调整分隔符及使用schema.ini
修改连接字符串中FMT=Delimited的分隔符为逗号、@、空格等,仍仅返回2列;尝试用schema.ini指定分隔符,在测试CSV中有效,但在目标.msr转的CSV中无效。
求助需求
- 如何通过ADO将读取的记录集保存为可正常识别的CSV文件?
- 如何让ADO读取CSV时不拆分列,将所有数据放在A列?
- 或提供其他可行的解决方法,能正确获取所有103列数据。
内容的提问来源于stack exchange,提问作者jou yungcheng

