ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 1999|回复: 6

[求助] 多个工作簿下多个工作表汇总代码求优化

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-1-22 13:01 | 显示全部楼层 |阅读模式
本帖最后由 nmghrt 于 2019-1-22 14:46 编辑

首先非常感谢您能阅读我的帖子。我的工作是每月需要各分公司给我报一个Excel工作簿,每个工作簿中有数十个工作表。
当然,各分公司报来的工作簿中工作表格式、名称都是统一的,只是内容不同。
自打我接触VBA以来,就发现以前的复制粘贴简直是在浪费生命,像这种重复性的工作VBA肯定能解决,于是我各种百度,终于在网上找到了这样一段代码:
  1. Sub Collectwks()
  2. Dim Sht As Worksheet, rng As Range, Sh As Worksheet
  3. Dim Trow&, k&, arr, brr, i&, j&, book&, a&
  4. Dim p$, f$, Headr, Keystr
  5. With Application.FileDialog(msoFileDialogFolderPicker)
  6. '取得用户选择的文件夹路径
  7. .AllowMultiSelect = False
  8. If .Show Then p = .SelectedItems(1) Else Exit Sub
  9. End With
  10. If Right(p, 1) <> "" Then p = p & ""
  11. Keystr = InputBox("请输入需要合并的工作表所包含的关键词:", "提醒")
  12. If StrPtr(Keystr) = 0 Then Exit Sub '如果点击了inputbox的取消或者关闭按钮,则退出程序
  13. Trow = Val(InputBox("请输入标题的行数", "提醒"))
  14. If Trow < 0 Then MsgBox "标题行数不能为负数。", 64, "警告": Exit Sub
  15. Set Sht = ActiveSheet
  16. Application.ScreenUpdating = False '关闭屏幕更新
  17. Cells.ClearContents
  18. Cells.NumberFormat = "@" '清空当前表数据并设置为文本格式
  19. ReDim brr(1 To 200000, 1 To 2) '定义装汇总结果的数组brr,最大行数为20万行,2列是临时的
  20. f = Dir(p & "*.xls*") '开始遍历工作簿
  21. Do While f <> ""
  22. If f <> ThisWorkbook.Name Then '避免同名文件重复打开出错
  23. With GetObject(p & f)  '以'只读'形式读取文件时,使用getobject方法会比workbooks.open稍快
  24. For Each Sh In .Worksheets '遍历表
  25. If InStr(1, Sh.Name, Keystr, vbTextCompare) Then '如果表中包含关键词则进行汇总(不区分关键词字母大小写)
  26. Set rng = Sh.UsedRange
  27. If rng.Count > 1 Then  '如果rng的单元格数量大于1……
  28. book = book + 1 '标记一下是否首个Sheet,如果首个sheet,BOOK=1
  29. a = IIf(book = 1, 1, Trow + 1) '遍历读取arr数组时是否扣掉标题行
  30. arr = rng.Value '数据区域读入数组arr
  31. If UBound(arr, 2) + 2 > UBound(brr, 2) Then  '动态调整结果数组brr的最大列数,避免明细表列数不一的情况。
  32. ReDim Preserve brr(1 To 200000, 1 To UBound(arr, 2) + 2)
  33. End If
  34. For i = a To UBound(arr) '遍历行
  35. k = k + 1 '累加记录条数
  36. brr(k, 1) = f '数组第一列放工作簿名称
  37. brr(k, 2) = Sh.Name '数组第二列放工作表名称
  38. For j = 1 To UBound(arr, 2) '遍历列
  39. brr(k, j + 2) = arr(i, j)
  40. Next
  41. Next
  42. End If
  43. End If
  44. Next
  45. .Close False '关闭工作簿
  46. End With
  47. End If
  48. f = Dir '下一个表格
  49. Loop
  50. If k > 0 Then
  51. Sht.Select
  52. [a1].Offset(IIf(Trow = 0, 1, 0)).Resize(k, UBound(brr, 2)) = brr '放数据区域
  53. [a1].Resize(1, 2) = [{"来源工作簿名称","来源工作表名"}]
  54. MsgBox "汇总完成。"
  55. End If
  56. Application.ScreenUpdating = True '恢复屏幕更新
  57. End Sub
复制代码
但是这段代码在运行过程中,出了两个小问题:
1. 源表格数据量较大时提示我“运行错误‘7‘’:内存溢出”(附件中表格由于数据量较小,没出现这个问题)。
2. 这段代码是将所有工作簿内的所有工作表都汇总到一张表格上,有没有什么办法能让不同的工作簿下的工作表分别汇总呢?例如各工作簿下的sheet1都汇总到汇总表的sheet1中,sheet2都汇总到汇总表的sheet2中…以此类推。
注:各分公司报来的工作簿中各工作表顺序都是固定的,名称也是固定的。
请各位大神帮忙优化一下,或者有前辈有过此类教程,帮忙贴个链接,小弟在论坛内搜了好久,均没找到……
对您的帮助万分感谢!

test.rar

118.21 KB, 下载次数: 94

TA的精华主题

TA的得分主题

发表于 2019-1-22 20:58 | 显示全部楼层
本帖最后由 cqcbc 于 2019-1-22 21:13 编辑

运行一次宏,然后保存,出现提醒窗口:请输入需要合并的工作表所包含的关键词:输入如:Sheet1 (2),这样只汇总Sheet1 (2);更换输入的表名,再保存,直到结束。

TA的精华主题

TA的得分主题

发表于 2019-1-22 21:15 | 显示全部楼层
试试这个,应该可以。
Sub tt()
Dim sht As Worksheet, p$, f$, d As Object, arr, brr, i&, j&, k&
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set d = CreateObject("scripting.dictionary")
For Each sht In Worksheets
    If sht.Name <> ActiveSheet.Name Then sht.Delete
Next
Set Sh = ActiveSheet
ReDim brr(1 To 200000, 1 To 20)
p = ThisWorkbook.Path & "\"
f = Dir(p & "*.xls")
Do While f <> ""
    If f <> ThisWorkbook.Name Then
        With GetObject(p & f)
            For Each sht In .Worksheets
                shtname = sht.Name
                arr = sht.[a1].CurrentRegion
                For i = 2 To UBound(arr)
                    k = k + 1
                    For j = 1 To UBound(arr, 2)
                        brr(k, j) = arr(i, j)
                    Next
                    brr(k, UBound(arr, 2) + 1) = Split(f, ".xls")(0)
                    If Not d.exists(shtname) Then
                        Set d(shtname) = CreateObject("scripting.dictionary")
                        For n = 1 To UBound(arr, 2)
                            s = s & "," & arr(1, n)
                        Next
                        d(shtname)(shtname) = Mid(s, 2)
                        s = ""
                    End If
                    d(shtname)(k) = ""
                Next
            Next
            .Close False
        End With
    End If
    f = Dir()
Loop
kr = d.keys
For i = 0 To UBound(kr)
    With Worksheets.Add(, Sheets(Sheets.Count))
        .Name = kr(i)
        r = d(kr(i)).keys
        ReDim drr(1 To UBound(r) + 1, 1 To UBound(brr, 2))
        For x = 1 To UBound(r)
            For y = 1 To UBound(brr, 2)
                drr(x, y) = brr(r(x), y)
            Next
        Next
        ar = Split(d(kr(i))(kr(i)), ",")
        .[a1].Resize(1, UBound(ar) + 1) = ar
        .[a2].Resize(UBound(r) + 1, UBound(brr, 2)) = drr
    End With
Next
Sh.Activate
Set d = Nothing
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

TA的精华主题

TA的得分主题

发表于 2019-1-22 21:18 | 显示全部楼层
Sub 多薄同名表重组为一薄多表()
Dim d As Object, p$, f$, h&, sh As Worksheet, nm$, n As Name
bm = ActiveSheet.Name
btzmh = Val(Application.InputBox("请输入 标题最末行的行号:", "默认值", "1"))
bwh = Val(Application.InputBox("请输入 表尾占据的总行数:", "默认值", "0"))
Application.ScreenUpdating = False
Set d = CreateObject("scripting.dictionary")
p = ThisWorkbook.Path & "\"
f = Dir(p & "*.xls*")
Application.DisplayAlerts = False
Do While f <> ""
    If f <> ThisWorkbook.Name Then
        With Workbooks.Open(p & f)
            For Each sh In .Worksheets
                nm = sh.Name
                If Not d.exists(nm) Then
                    d(nm) = ""
                    sh.Copy after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
                    h2 = ThisWorkbook.Sheets(nm).UsedRange.Rows.Count + ThisWorkbook.Sheets(nm).UsedRange.Row - 1
                    If bwh > 0 Then
                      ThisWorkbook.Sheets(nm).Rows(h2 - bwh + 1 & ":" & h2).Delete
                    End If
                Else
                    With sh
                        h = sh.UsedRange.Rows.Count + sh.UsedRange.Row - 1 - btzmh - bwh
                        qsl = sh.UsedRange.Column
                        h1 = ThisWorkbook.Sheets(nm).UsedRange.Rows.Count + ThisWorkbook.Sheets(nm).UsedRange.Row
                        .UsedRange.Offset(btzmh).Resize(h).Copy ThisWorkbook.Sheets(nm).Cells(h1, qsl)
                    End With
                End If
            Next
            .Close 0
        End With
    End If
    f = Dir
Loop
On Error Resume Next
For Each n In ThisWorkbook.Names
    n.Delete
Next
Err.Clear
Sheets(bm).Delete
Set d = Nothing
Application.DisplayAlerts = True
Application.ScreenUpdating = True
MsgBox "提取完毕!"
End Sub

TA的精华主题

TA的得分主题

发表于 2019-1-22 21:39 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
留下记号。谢谢

TA的精华主题

TA的得分主题

发表于 2019-1-22 21:43 | 显示全部楼层
多簿多表的汇总例子坛里非常多。

TA的精华主题

TA的得分主题

发表于 2022-5-12 13:55 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-19 15:46 , Processed in 0.046902 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表