Excel·VBA使用ADO合并工作簿

之前文章《Excel·VBA合并工作簿(7,合并子文件夹同名工作簿中同名工作表,纵向汇总数据)》处理合并工作簿问题,代码运行速度比较慢

《Excel·VBA使用ADO读取工作簿工作表数据》读取数据非常快,那么是否可以使用ADO合并工作簿?

ADO合并子文件夹同名工作簿中同名工作表,纵向汇总数据

注意:合并生成结果表格不带格式,公式都读取为值,仅适用表头行1行,仅测试xlsx格式文件合并

vbnet 复制代码
Sub ADO合并子文件夹同名工作簿中同名工作表_纵向汇总数据2()
    '不打卡工作簿方法;最终合并文件以工作簿名命名,适用工作表格式相同;合并文件A列显示原子文件夹名
    Dim dict As Object, fso As Object, old_name As Boolean, write_wb As Workbook, s$, s1$, ss$
    Dim file_path$, save_path$, delimiter$, fd, i&, r&, f, ff, p, pp
    Dim cnn As Object, rs As Object, ex As Object, sqlstr$, fp$, ws, wss
'--------------------参数填写:
    file_path = "E:\测试\拆分表\合并工作簿7\"  'file_path待合并的子文件夹所在文件夹
    save_path = file_path + "合并表\"   '合并后的表格保存路径
    old_name = True    '写入原子文件夹名,是/否
    Application.ScreenUpdating = False  '关闭屏幕更新,加快程序运行
    Application.DisplayAlerts = False   '不显示警告信息
    Set dict = CreateObject("scripting.dictionary"): delimiter = Chr(28)
    Set fso = CreateObject("Scripting.FileSystemObject"): tm = Timer
    If fso.FolderExists(save_path) Then Debug.Print "保存文件夹已存在,会导致错误,请删除": Exit Sub
    For Each f In fso.GetFolder(file_path).SubFolders  '获取所有子文件夹名
        s = s & delimiter & f.Name
    Next
    fd = Split(Mid(s, 2), delimiter)
    If Not fso.FolderExists(save_path) Then fso.CreateFolder (save_path)  '创建文件夹
    Set cnn = CreateObject("ADODB.Connection"): Set rs = CreateObject("ADODB.Recordset")
    For Each p In fd
        For Each f In fso.GetFolder(file_path & p).Files  '空文件夹不影响
            If f.Name Like "*.xlsx" And Not dict.Exists(f.Name) Then
                s = f.Name: Set dict(s) = CreateObject("scripting.dictionary")
                Set write_wb = Workbooks.Add  '新建工作簿,合并文件
                For Each pp In fd  '遍历所有子文件夹同名工作簿
                    For Each ff In fso.GetFolder(file_path & pp).Files
                        If ff.Name = s Then
                            fp = file_path & pp & "\" & s  '文件名含路径
                            cnn.Open "Provider=Microsoft.Ace.OLEDB.12.0;Extended properties='Excel 12.0 Xml;Hdr=yes;IMEX=1';data source=" & fp
                            Set rs = cnn.OpenSchema(20): ss = ""
                            Do Until rs.EOF  '获取所有工作表名称
                                If rs.Fields("TABLE_TYPE") = "TABLE" Then
                                    s1 = Replace(rs("TABLE_NAME").Value, "'", "")
                                    If Right(s1, 1) = "$" Then s1 = Left(s1, Len(s1) - 1): ss = ss & delimiter & s1
                                End If
                                rs.MoveNext
                            Loop
                            rs.Close: wss = Split(Mid(ss, 2), delimiter)  '工作表名称数组
                            For Each ws In wss  '遍历工作表获取数据,并写入
                                sqlstr = "SELECT * FROM [" & ws & "$]"
                                Set ex = cnn.Execute(sqlstr)
                                If Not dict(s).Exists(ws) Then  '工作表不存在
                                    dict(s)(ws) = "": i = 0: ReDim trr(1 To ex.Fields.Count)
                                    For Each x In ex.Fields  '表头
                                        i = i + 1: trr(i) = x.Name
                                    Next
                                    write_wb.Worksheets.Add(after:=Sheets(Sheets.Count)).Name = ws  '最后添加新sheet,并命名
                                    With write_wb.Worksheets(ws)
                                        .[b1].Resize(1, UBound(trr)) = trr
                                        .[b2].CopyFromRecordset ex
                                        .[a1] = "子文件夹": .[a2].Resize(.[b1].End(xlDown).row - 1, 1) = pp
                                    End With
                                Else
                                    With write_wb.Worksheets(ws)
                                        r = .UsedRange.Rows.Count + 1
                                        .Cells(r, 2).CopyFromRecordset ex
                                        .Cells(r, 1).Resize(.[b1].End(xlDown).row - r + 1, 1) = pp
                                    End With
                                End If
                            Next
                            cnn.Close
                        End If
                    Next
                Next
                write_wb.Worksheets(1).Delete  'excel新建wb第1个ws为空表
                If Not old_name Then  '无需写入原子文件夹名
                    For Each sht In write_wb.Worksheets
                        sht.Columns("a:a").Delete
                    Next
                End If
                write_wb.SaveAs filename:=save_path & s
                write_wb.Close (False)
            End If
        Next
    Next
    Set rs = Nothing: Set cnn = Nothing
    Application.ScreenUpdating = True: Application.DisplayAlerts = True
    Debug.Print "文件夹合并完成,用时:" & Format(Timer - tm, "0.00")
End Sub

举例,并与"合并工作簿7"对比

合并与 "合并工作簿7" 举例中同样的数据


共有12个文件夹60个工作簿180个工作表,合并后


运行速度对比

代码版本 合并工作簿7.1 合并工作簿7.2 ADO合并工作簿
耗时秒数 40-60 22.5-29 5.77-6.76

相比 合并工作簿7.2 使用ADO代码行数更少,同时运行速度提升了数倍

相关推荐
阿里云大数据AI技术6 小时前
Hologres AI Function 文本分类实战:从提示词设计到 KV-Cache 调优,全程 SQL 搞定
人工智能·sql
2601_9626838910 小时前
治理遗留系统中的“生肉 SQL”:一次用多模型协作优化慢查询的实战复盘
数据库·人工智能·sql
dexi.Chi 攻城狮12 小时前
SQL层次查询语法
经验分享·笔记·sql
华山令狐虫13 小时前
DBAPI AI 写 SQL:支持动态 SQL 与参数占位符,自然语言一键生成
数据库·人工智能·sql·dbapi
一个天蝎座 白勺 程序猿18 小时前
自动SQL优化实战|吃透调优接口+报告配置+统计+索引全流程落地
数据库·sql·sql优化
隐形的萝莉19 小时前
再回到技术面,研究 T-SQL 的 UNION、EXISTS、EXCEPT、INTERSECT 运算符。
数据库·sql
吴声子夜歌20 小时前
SQL进阶——窗口函数进行行间比较
数据库·sql
Tian_Hang20 小时前
Eclipse Mosquitto 安装及介绍
java·运维·服务器·ide·sql·mysql·eclipse
VBA63371 天前
数组与字典解决方案第二十九讲 数组的创建方法小结及回填的注意事项
vba
要开心吖ZSH2 天前
MVCC 进阶:快照读 vs 当前读、幻读与 Next-Key Lock
java·数据库·sql·mysql·mvcc