Excel VBA通过ADODB连接CSV仅返回部分记录问题求助
看起来你遇到了ACE OLEDB驱动读取大CSV文件时的典型问题——驱动没有完整读取文件,导致行数统计和筛选结果异常。下面我会拆解可能的原因,并给出具体的解决步骤:
一、核心问题分析
你的CSV有2400多万行,但count(*)只返回15万+,说明驱动在读取过程中跳过了大量行,大概率是因为数据类型推断错误、格式识别问题,或者驱动本身的隐性限制导致的。
二、具体解决方法
1. 用Schema.ini强制指定文件格式(最关键的一步)
ACE驱动默认只会扫描前25行推断列的数据类型,如果某列前25行是数字,后面出现文本,驱动会把这些文本行标记为“错误行”直接跳过。解决这个问题的最佳方式是在CSV所在文件夹创建Schema.ini文件,强制驱动按正确规则读取:
在CSV的同目录下新建一个名为Schema.ini的文本文件,写入以下内容:
[MyFileName.csv] Format=Delimited(,) ColNameHeader=True MaxScanRows=0 ; 扫描所有行确定列类型,避免推断错误 ImportMixedTypes=Text ; 强制混合类型列按文本读取 CharacterSet=65001 ; 对应UTF-8编码,ANSI编码改为1252
MaxScanRows=0:让驱动扫描全部行来确定列类型,而不是默认的25行。ImportMixedTypes=Text:彻底避免因数据类型不匹配导致的行丢失。
2. 修正连接字符串参数
原连接字符串缺少IMEX=1参数,这个参数会强制驱动将混合类型的列当作文本处理,进一步减少行丢失的可能。修正后的连接字符串:
sconnect = "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" & rawFile & ";Extended Properties='text;HDR=YES;FMT=Delimited;IMEX=1;CharacterSet=65001'"
⚠️ 注意:rawFile必须是CSV所在的文件夹路径,而不是CSV文件的完整路径!这是很多人踩坑的点——ADODB连接文本文件时,Data Source指向的是文件夹,SQL语句里才指定文件名。
3. 检查驱动与Excel的位数匹配
如果你的Excel是64位,但安装的是32位ACE驱动(或者反过来),驱动会无法正常处理大文件,出现读取截断:
- 查看Excel位数:文件 → 账户 → 关于Excel。
- 安装对应位数的Microsoft Access Database Engine 2016 Redistributable:如果已经装了不同位数的Office,需要用静默安装参数(比如
setup.exe /quiet)避免冲突。
4. 排查CSV格式问题
如果CSV里存在未转义的字段内换行(比如某单元格的内容包含换行,但没有用双引号包裹),驱动会错误识别行边界,导致行数统计错误。可以用文本编辑器打开CSV,检查这类格式问题并修复。
三、修正后的测试代码
我给你优化了代码,加上错误处理和总行数验证:
Public adoConn As ADODB.Connection Public adoRS As ADODB.Recordset Sub getdata() On Error GoTo Cleanup Set adoConn = New ADODB.Connection Set adoRS = New ADODB.Recordset Dim rawFolder As String ' 注意:这里是文件夹路径,不是文件路径 Dim strSQL As String Dim sconnect As String ' 替换为你的CSV所在文件夹路径 rawFolder = "C:\Your\CSV\Folder\Path" ' 修正后的连接字符串 sconnect = "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" & rawFolder & ";Extended Properties='text;HDR=YES;FMT=Delimited;IMEX=1;CharacterSet=65001'" adoConn.Open sconnect ' 第一步:验证总行数是否正确 strSQL = "SELECT count(*) from [MyFileName.csv]" adoRS.Open strSQL, adoConn, adOpenStatic Debug.Print "Total rows detected: " & adoRS(0).Value adoRS.Close ' 第二步:执行你的筛选SQL strSQL = "SELECT * from [MyFileName.csv] WHERE YourTargetColumn = 'YourFilterValue'" adoRS.Open strSQL, adoConn, adOpenStatic If Not adoRS.EOF Then Blad1.Range("A1").CopyFromRecordset adoRS MsgBox "Filtered data imported successfully!" Else MsgBox "No records found after filtering." End If Cleanup: ' 确保资源正确释放 If Not adoRS Is Nothing Then If adoRS.State = adStateOpen Then adoRS.Close Set adoRS = Nothing End If If Not adoConn Is Nothing Then If adoConn.State = adStateOpen Then adoConn.Close Set adoConn = Nothing End If If Err.Number <> 0 Then MsgBox "Error occurred: " & Err.Description, vbExclamation End If End Sub
先运行这段代码,如果总行数接近2400多万,说明驱动已经能完整读取文件了,此时再执行筛选应该就能得到你要的1500行数据。
内容的提问来源于stack exchange,提问作者pk_22

