分享

Excel教程:合并多工作簿数据成总表?只需一键!

 痕迹资料库 2020-02-13

作者:看见星光

来源:Excel星球(ID:AhaExcel)


朋友们好,我是星光,今天给大家分享的Excel技巧是如何使用VBA将多个工作簿的数据合并成一张总表。

不懂VBA?摆摆手,没有关系,会复制代码运行就OK了。

合并指定文件夹下多工作簿数据动画演示如下:

VBA代码如下:

Sub CollectWorkBookDatas()
    Dim shtActive As Worksheet, rng As Range, shtData As Worksheet
    Dim nTitleRow As Long, k As Long, nLastRow As Long
    Dim i As Long, j As Long, nStartRow As Long
    Dim aData, aResult, nStarRng As Long
    Dim strPath As String, strFileName As String
    Dim strKey As String, nShtCount As Long
    With Application.FileDialog(msoFileDialogFolderPicker)
    '取得用户选择的文件夹路径
        If .Show Then strPath = .SelectedItems(1) Else Exit Sub
    End With
    If Right(strPath, 1) <> '\' Then strPath = strPath & '\'
    strKey = InputBox('请输入需要合并的工作表所包含的关键词:' & vbCrLf & '如未填写关键词,则默认汇总全部表格数据', '提醒')
    If StrPtr(strKey) = 0 Then Exit Sub '如果点击了取消或者关闭按钮,则退出程序
    nTitleRow = Val(InputBox('请输入标题的行数,默认标题行数为1', '提醒', 1))
    If nTitleRow < 0 Then MsgBox '标题行数不能为负数。', 64, '警告': Exit Sub
    Set shtActive = ActiveSheet
    With Application
        .ScreenUpdating = False
        .DisplayAlerts = False
        .AskToUpdateLinks = False
    End With
    ReDim aResult(1 To 80000, 1 To 1) '声明结果数组
    Cells.ClearContents '清空当前表格数据
    Cells.NumberFormat = '@' '设置单元格为文本格式
    strFileName = Dir(strPath & '*.xls*') '使用Dir函数遍历excel文件
    Do While strFileName <> ''
        If strFileName <> ThisWorkbook.Name Then '避免同名文件重复打开出错
            With GetObject(strPath & strFileName)
            '以只读'形式读取文件时,使用getobject会比workbooks.open稍快
                For Each shtData In .Worksheets '遍历表
                    If InStr(1, shtData.Name, strKey, vbTextCompare) Then
                    '如果表中包含关键字则进行汇总(不区分关键词字母大小写)
                        Set rng = shtData.UsedRange
                        If rng.Count > 1 Then '判断工作表是否存在数据……
                            nShtCount = nShtCount + 1 '汇总工作表的数量
                            nStartRow = IIf(nShtCount = 1, 1, nTitleRow + 1) '判断遍历数据源是否应该扣掉标题行
                            aData = rng.Value '数据区域读入数组arr
                            If UBound(aData, 2) + 2 > UBound(aResult, 2) Then '动态调整结果数组brr的最大列数
                                ReDim Preserve aResult(1 To UBound(aResult), 1 To UBound(aData, 2) + 2)
                            End If
                            For i = nStartRow To UBound(aData) '遍历行
                                k = k + 1
                                aResult(k, 1) = strFileName '数组第一列放工作簿名称
                                aResult(k, 2) = shtData.Name '数组第二列放工作表名称
                                For j = 1 To UBound(aData, 2) '遍历列
                                    aResult(k, j + 2) = aData(i, j)
                                Next
                                If k > UBound(aResult) - 1 Then
                                '如果数据行数到达结果数组的上限,则将数据导入汇总表,并清空结果数组
                                    With shtActive
                                        nLastRow = .Cells(Rows.Count, 1).End(xlUp).Row '获取放置来源数据的位置
                                        If nLastRow = 1 Then '判断是否扣除标题行
                                            nStarRng = IIf(nTitleRow = 0, 1, 0)
                                            .Range('a1').Offset(nStarRng).Resize(k, UBound(aResult, 2)) = aResult
                                            .Range('a1:b1') = Array('来源工作簿名称', '来源工作表名称')
                                            '前两列放来源工作簿和工作表名称
                                        Else
                                            .Range('a1').Offset(nLastRow).Resize(k, UBound(aResult, 2)) = aResult
                                            '放结果数组的数据
                                        End If
                                    End With
                                    k = 0
                                    ReDim aResult(1 To UBound(aResult), 1 To UBound(aResult, 2))
                                    '重新设置结果数组
                                End If
                            Next
                        End If
                    End If
                Next
                .Close False '关闭工作簿
            End With
        End If
        strFileName = Dir '下一个excel文件
    Loop
    If k > 0 Then
        shtActive.Select '激活汇总表
        nLastRow = Cells(Rows.Count, 1).End(xlUp).Row '放置数据的位置
        If nLastRow = 1 Then '如果汇总表数据为空,说明需要汇总的数据没有超过结果数组的上限
             nStarRng = IIf(nTitleRow = 0, 1, 0)
             Range('a1').Offset(nStarRng).Resize(k, UBound(aResult, 2)) = aResult
             Range('a1:b1') = Array('来源工作簿名称', '来源工作表名称')
         Else
             Range('a1').Offset(nLastRow).Resize(k, UBound(aResult, 2)) = aResult
         End If
    End If
    With Application
        .ScreenUpdating = True
        .DisplayAlerts = True
        .AskToUpdateLinks = True
    End With
    MsgBox '一共汇总完成。' & nShtCount & '个工作表', , 'Excel星球'
End Sub

代码解析见注释,运行过程描述如下。

1.代码运行后,首先会弹出一个选择文件夹的对话框,选中目标文件夹后,单击【确定】按钮即可。


2.尔会后出现一个设置汇总工作表关键字的对话框。这里的关键字不区分大小写;如果需要汇总全部工作表的数据,可以不设置关键字,直接单击【确定】按钮即可。


3.下一步设置工作表标题行的行数,默认为1行,可以根据实际情况设置为任意行,比如0行、2行等。


4.数据合并完成后会弹出一个对话框,告知汇总了几张工作表的数据。


 小贴士:

小代码支持处理分表的列数不一致的情况。比如A表有4列数据,B表有5列数据,则汇总表为5列数据;但每张工作表的标题排列顺序应当一致,否则会出现错位的问题。

示例文件下载,百度网盘:

https://pan.baidu.com/s/1ddPZX_mBKW0snIJ4K4tIGA

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多