
直接运行版本→告别转圈圈!这款「Excel极速导出神器」,一键让CSV瞬间落地
曾遇此窘境?处理上万行数据并导出 CSV 时,Excel 如同断气,鼠标转圈到怀疑人生。
因为通常以循环逐个单元格去读取再写入。这种方式慢,是因为 VBA 与 Excel 单元格(Sheet)的「频繁互动」导致通讯开销巨大。
根据之前文章的总结。秘诀就两个字:「数组」。
打个比方,「逐个单元格读取」像蚂蚁搬家,每搬一粒米都要跑一趟仓库;而「数组法」则直接开大货车,一次拉走整屋的米。
在 VBA,每读一次 Range("A1").Value,系统就得跨对象调用一次。如有 5 万行 10 列的数据,那就是 50 万次调用,因此卡顿。

主要分为三步:
一键装车(数据入数组):将工作表的数据范围一次性赋值给一个 Variant 的变量。所有数据瞬间尽入内存。
内存加工(字符串拼接):在内存透过循环数组,用「,」拼接每行数据。因为在内存跑,比在 Sheet 跑快了不止百倍。
批量卸货(写入文件):利用 Print 语句,将处理好的数据直接写入目标 .csv 。

「为何仅换成数组,就能提速数十倍?」奥妙在于 VBA 引擎的底层机理。
每次访问 Range("A1"),代码从 VBA 引擎跳到 Excel 界面引擎,取完数据再跳回。这「跨界」非常耗时。
普通做法:循环 10000 次,就反复跳 10000 次。
数组做法:vData = ws.UsedRange.Value。这行代码仅大规模地跨界通讯了一次,就「打包」全表的数据到 VBA 自己的内存空间。
' 关键行:一次性搬运数据vData = ws.UsedRange.Value' 此时 vData 已是一个在内存的二维数组,' 访问 vData(1, 1) 比访问 Cells(1, 1) 快上百倍。
定义 Dim vData As Variant 时,VBA 有一个高级特性:将一个 Range 赋值给它,它会变成一个基于 1 的二维数组(1-based 2D Array)。即便表格仅一列,它仍保持 vData(行, 列) 的结构,理解这点能避免在写循环时报错。
比如,v = Range("A1:C10").Value,VBA 会自动创建一个 1 to 10, 1 to 3 的二维数组。因为无需逐个 Cells(i, j) 调用,通常提速 10 倍以上。
导出 CSV 需接合字符串,因此采用「逐行拼接,整行写入」的策略:
' 内存中的高效拼接For j = 1 To UBound(vData, 2)If j = 1 ThenrowString = vData(i, j)ElserowString = rowString & "," & vData(i, j)End IfNext j
为何不一次性拼接全表?如数据量达几十万行且每行内容极长,一次性拼接一个巨大的字符串会导致内存溢出。
为何不写一格就 Print 一次?频繁的磁盘写入(I/O)会大幅减速。现在的做法在「速度」与「稳定性」之间取得完美的平衡。
' 如需处理复杂的编码,可用以下逻辑:Dim objStream As ObjectSet objStream = CreateObject("ADODB.Stream")objStream.Charset = "UTF-8"objStream.Open' ... 循环中用 objStream.WriteText 代替 Print ...objStream.SaveToFile filePath, 2
Sub ExportCSV_HighSpeed()' ==========================================' 功能:利用数组高速导出当前工作表为 CSV' 特点:避开逐格读取,处理数万行仅需数秒' ==========================================Dim ws As WorksheetDim vData As VariantDim i As Long, j As LongDim rowString As StringDim filePath As StringDim fileNum As IntegerDim startTime As Double' 记录开始时间startTime = Timer' 设置目标工作表和保存路径Set ws = ThisWorkbook.ActiveSheetfilePath = ThisWorkbook.Path & "\HighSpeedExport_" & Format(Now, "YYYYMMDD_HHMMSS") & ".csv"' 1. 「数据入数组」:一次将所有有数据的区域装载到内存' 这是提升速度的核心技巧vData = ws.UsedRange.Value' 获取一个可用文件号fileNum = FreeFile' 2. 「打开文件准备写入」Open filePath For Output As #fileNum' 3. 「内存循环加工」' UBound(vData, 1) 代表行数,UBound(vData, 2) 代表列数For i = 1 To UBound(vData, 1)rowString = ""For j = 1 To UBound(vData, 2)' 拼接每一列数据If j = 1 ThenrowString = vData(i, j)Else' 用逗号分隔rowString = rowString & "," & vData(i, j)End IfNext j' 4. 「逐行写入文件」' 这样做比一次性拼接全表字符串更省内存,且速度依然极快Print #fileNum, rowStringNext i' 关闭文件Close #fileNum' 显示执行结果MsgBox "导出成功!" & vbCrLf & _"保存路径:" & filePath & vbCrLf & _"耗时:" & Format(Timer - startTime, "0.00") & " 秒", vbInformationEnd Sub
写在最后
用内存和数组「架构优化」,面对数万行数据不再束手无策。不妨试试这套「数组导出法」,你会发现,原来 VBA 也可快如跑车。

参考文章: