ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: 彭希仁

[讨论] 复杂的多表汇总(难度有点大,做出来有分加哦)

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2010-1-25 06:26 | 显示全部楼层
本帖已被收录到知识树中,索引项:多表合并和汇总
原帖由 ldy 于 2010-1-25 05:22 发表
这个表的格式算是相当规范的了,按照关键字 两个“合计” 可以定位区域。
就是设置总表格式很烦人。


656082

相当不错,汇总表中表头已经处理好了,A列只要加入一下合并相同内容单元格语句就可以了。希望给代码加注解。

TA的精华主题

TA的得分主题

发表于 2010-1-25 08:00 | 显示全部楼层
占位,学习ldy版主的代码

TA的精华主题

TA的得分主题

发表于 2010-1-25 11:19 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
原帖由 wenwen000424 于 2010-1-25 06:26 发表

相当不错,汇总表中表头已经处理好了,A列只要加入一下合并相同内容单元格语句就可以了。希望给代码加注解。


简单点说, 就是先通过代码规范数据,然后把双表头组成字符串,用字典记录行号 、列标,再根据行号 、列标累加到总表中。

总之通用性越强,代码量越大,通用性多1点,代码量起码要多 3 点。


  1. '引用 Microsoft Scripting Runtime  C:\WINDOWS\system32\scrrun.dll
  2. Sub 汇总()
  3.     Dim colDIC As New Dictionary, rowDIC As New Dictionary
  4.     '列字典 与 行字典 分别是这样的字符串  :"V360|白色"  "广东|GZ02",用以确定唯一性。
  5.     Dim rg As Range
  6.     Dim a As Variant, b As Variant, brr() As Variant
  7.     ' a 是 汇总后的数组 , b 是每个月的数据数组,通过 "确定区域" 函数取值并规范。brr 把b 装在一起,便于引用
  8.     Dim k As Long, i As Long, j As Long, shcount As Integer

  9. Application.ScreenUpdating = False  '关闭屏幕刷新 提高运行速度

  10.     t = Timer ' 开始计时
  11.    
  12.     '取得每月销售表的数据区域 ,装到brr 中,并确定唯一的行标志("广东|GZ02") 和列标志("V360|白色")
  13.     For k = 1 To Sheets.Count
  14.         If Sheets(k).Name Like "*销量" Then
  15.             shcount = shcount + 1
  16.             b = 确定区域(Sheets(k))
  17.             ReDim Preserve brr(1 To shcount)
  18.             brr(shcount) = b
  19.             For i = 3 To UBound(b, 2)
  20.                 colDIC(b(1, i) & "|" & b(2, i)) = 0
  21.             Next
  22.             For i = 3 To UBound(b, 1)
  23.                 rowDIC(b(i, 1) & "|" & b(i, 2)) = 0
  24.             Next
  25.         End If
  26.     Next
  27.     ' 取数据完成
  28.     '    根据列字典 与 行字典设置总表 ,设置总表格式
  29.     Dim temp1 As Range, temp2 As Range
  30.     With Sheets("总表")
  31.         Sheets("总表").Cells.Delete
  32.         crr = colDIC.Keys              '取得列标志数组
  33.         rrr = Application.WorksheetFunction.Transpose(rowDIC.Keys)    '取得行标志数组
  34.         Set temp1 = .Range("d2").Resize(1, colDIC.Count)
  35.         temp1 = crr                    '        填写列标志
  36.         For Each rg In temp1           ' 把列标志拆分成两行
  37.             rg.Cells(2, 1) = Split(rg, "|")(1)
  38.             rg = Split(rg, "|")(0)
  39.         Next
  40.         temp1.Resize(2).Sort Key1:=.Range("D2"), Orientation:=xlSortRows    ' 利用Excel排序功能进行 列标志 横向排序
  41.         Set temp2 = .Range("b4").Resize(rowDIC.Count, 1)
  42.         temp2 = rrr '        填写行标志
  43.         
  44.         For Each rg In temp2 ' 把列标志拆分成两列
  45.             rg.Cells(1, 2) = Split(rg, "|")(1)
  46.             rg = Split(rg, "|")(0)
  47.         Next
  48.         temp2.Resize(, 2).Sort Key1:=.Range("b4"), Orientation:=xlSortColumns  ' 利用Excel排序功能进行 行标志 纵向排序
  49.         
  50.         Range(.Range("b2"), .Cells(temp2.Rows.Count + 4, temp1.Columns.Count + 4)).Borders.Weight = 2 '总表区域画上框框边线
  51.         .Range("b2:b3").Merge ' 合并单元格 并填上 表头
  52.         .Range("c2:c3").Merge
  53.         .Range("b2") = "省份"
  54.         .Range("c2") = "销售网点"
  55.         With .Cells(2, temp1.Columns.Count + 4).Resize(2)
  56.             .Merge
  57.             .Value = "合计"
  58.         End With
  59.         With .Cells(temp2.Rows.Count + 4, 2).Resize(, 2)
  60.             .Merge
  61.             .Value = "合计"
  62.         End With

  63.         Set v = temp1(1, 1)
  64.         For Each rg In temp1.Resize(, temp1.Columns.Count + 1) ' 扩展一列 把相同型号的单元格合并
  65.             If v <> rg Then
  66.                 s = v.Value
  67.                 Range(v, rg.Cells(1, 0)) = Empty
  68.                 Range(v, rg.Cells(1, 0)).Merge
  69.                 Range(v, rg.Cells(1, 0)) = s
  70.                 Set v = rg
  71.             End If
  72.         Next

  73.         Set v = temp2(1, 1)
  74.         For Each rg In temp2.Resize(temp2.Rows.Count + 1)  ' 扩展一行 把相同地区的单元格合并  90 楼的附件中忘了这一步
  75.             If v <> rg Then
  76.                 s = v.Value
  77.                 Range(v, rg.Cells(0, 1)) = Empty
  78.                 Range(v, rg.Cells(0, 1)).Merge
  79.                 Range(v, rg.Cells(0, 1)) = s
  80.                 Set v = rg
  81.             End If
  82.         Next
  83.         
  84.     End With
  85.     '  ''''''''  设置总表格式结束
  86.     a = 确定区域(Sheets("总表"), rg) ' 取得设置好的总表区域 数组 a
  87.     For i = 3 To UBound(a, 1)
  88.         rowDIC(a(i, 1) & "|" & a(i, 2)) = i ' 记录列标志 在数组 a 中的列序号
  89.     Next
  90.     For i = 3 To UBound(a, 2)
  91.         colDIC(a(1, i) & "|" & a(2, i)) = i ' 记录行标志 在数组 a 中的行序号
  92.     Next

  93.     For Each b In brr '把brr中的每一项 传到 合并过程,进行合并、累加完成汇总
  94.         进行合并 a, b, colDIC, rowDIC
  95.     Next

  96.     rg.Value = a                       '填写汇总结果
  97.     '    填写合计公式,以便验证

  98.     Set rg = rg.Resize(rg.Rows.Count + 1, rg.Columns.Count + 1)
  99.    
  100.     For i = 3 To rg.Rows.Count
  101.         rg.Cells(i, rg.Columns.Count) = "=SUM(RC[-" & rg.Columns.Count - 3 & "]:RC[-1])"
  102.     Next
  103.     For i = 3 To rg.Columns.Count
  104.         rg.Cells(rg.Rows.Count, i) = "=SUM(R[-" & rg.Rows.Count - 3 & "]C:R[-1]C)"
  105.     Next
  106. Application.ScreenUpdating = True
  107. MsgBox Timer - t ' 运行耗时 约0.4秒, 关闭屏幕刷新后0.18秒
  108.    
  109. End Sub

  110. Function 确定区域(sh As Worksheet, Optional c As Range) As Variant
  111.     '这个表的格式算是相当规范的了,按照关键字 两个“合计” 可以定位区域
  112.     Dim a As Range, b As Range
  113.     Dim arr As Variant, v As Variant, x As Integer, y As Integer
  114.     Set a = sh.Cells.Find(What:="合*计", After:=sh.[a1])    ' 合*计 预防 “ 合 计 ”这类非规范写法
  115.     Set b = sh.Cells.FindNext(After:=a)
  116.     Set c = sh.Range(sh.Cells(a.Row, b.Column), sh.Cells(b.Row - 1, a.Column - 1))
  117.     arr = c.Value
  118.     x = c.Row
  119.     y = c.Column
  120.    
  121.     '规范输入,合并的单元格中都填上相同内容
  122.     For i = 1 To c.Columns.Count
  123.         If c.Cells(1, i).MergeCells Then
  124.             If c.Cells(1, i).MergeArea.Count > 1 Then
  125.                 v = c.Cells(1, i).MergeArea
  126.                 For Each rg In c.Cells(1, i).MergeArea
  127.                     arr(rg.Row - x + 1, rg.Column - y + 1) = v(1, 1)
  128.                 Next
  129.                 i = i + c.Cells(1, i).MergeArea.Columns.Count - 1
  130.             End If
  131.         End If
  132.     Next
  133.     For i = 2 To c.Rows.Count
  134.         If c.Cells(i, 1).MergeCells Then
  135.             If c.Cells(i, 1).MergeArea.Count > 1 Then
  136.                 v = c.Cells(i, 1).MergeArea
  137.                 For Each rg In c.Cells(i, 1).MergeArea
  138.                     arr(rg.Row - x + 1, rg.Column - y + 1) = v(1, 1)
  139.                 Next
  140.                 i = i + c.Cells(i, 1).MergeArea.Rows.Count - 1
  141.             End If
  142.         End If
  143.     Next
  144.     确定区域 = arr
  145. End Function
  146. Sub 进行合并(a As Variant, b As Variant, colDIC As Dictionary, rowDIC As Dictionary)
  147.     Dim colstr As String, rowstr As String
  148.     '根据销售表( b )中的行标志 和列标志 ,通过 行字典和列字典 找到 总表(a)中的 行号 与 列号,并累加到 总表中
  149.     For i = 3 To UBound(b, 1)
  150.         rowstr = b(i, 1) & "|" & b(i, 2) '组成行标志 "广东|GZ02"
  151.         For j = 3 To UBound(b, 2)
  152.             colstr = b(1, j) & "|" & b(2, j) '组成 列标志("V360|白色")
  153.             r = rowDIC(rowstr) ' r  行号
  154.             c = colDIC(colstr) '  c 列号
  155.             a(r, c) = a(r, c) + b(i, j) ' 累加
  156.         Next
  157.     Next
  158. End Sub


复制代码

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-1-25 11:33 | 显示全部楼层
哈哈,所以这题的难度其实非常大,可以说是无上限的难题。

TA的精华主题

TA的得分主题

发表于 2010-1-25 12:11 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
原帖由 彭希仁 于 2010-1-25 11:33 发表
哈哈,所以这题的难度其实非常大,可以说是无上限的难题。


严重同意,程序员考虑的再细致,也不能囊括所有用户输入时犯的错误。
比如同义词的问题 合计-累计-统计  ,咖啡色-褐色-土黄色 ,黑色-纯黑-黑
再比如繁简体 广东-廣東 ,有些数字用汉字表示 12 - 一打,10 -拾
还有其他更离谱的,如果都能想到并加以处理,程序员怕要吐血而亡了。

TA的精华主题

TA的得分主题

发表于 2010-1-25 12:55 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
原帖由 彭希仁 于 2010-1-23 11:09 发表



这题的有两个意义
一、是送点分,现在竟赛那边没有分捞了,总得让大家增收吧。
二、引导大家开发插件的思路。这是最难的。要写成通用插件要走的路还很远,各件乱七八糟的情况都要想办法去解决,如在没有“汇 ...


才看到这个,最近家里装修,乱的很,电脑都很少开。
彭兄的工作写代码多,遇到的问题花样也多,彭兄自己也可以在竞赛区出题目,呵呵 辛苦辛苦

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-1-25 15:29 | 显示全部楼层
原帖由 ldy 于 2010-1-25 12:11 发表


严重同意,程序员考虑的再细致,也不能囊括所有用户输入时犯的错误。
比如同义词的问题 合计-累计-统计  ,咖啡色-褐色-土黄色 ,黑色-纯黑-黑
再比如繁简体 广东-廣東 ,有些数字用汉字表示 12 - 一打,10 -拾 ...



所以啊,程序员要学会取舍。那些该要,那些不该要。

[ 本帖最后由 彭希仁 于 2010-1-25 15:31 编辑 ]

TA的精华主题

TA的得分主题

发表于 2010-1-25 16:03 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
继续扩展成可选择多个文件含有多个这样工作表汇总可能更通用些。

TA的精华主题

TA的得分主题

 楼主| 发表于 2010-1-25 17:31 | 显示全部楼层
原帖由 wenwen000424 于 2010-1-25 16:03 发表
继续扩展成可选择多个文件含有多个这样工作表汇总可能更通用些。


是的,这是最基本的一个要求

TA的精华主题

TA的得分主题

发表于 2010-1-25 19:58 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
没用字典试一下

销量汇总.rar

24.98 KB, 下载次数: 88

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-23 23:15 , Processed in 0.042925 second(s), 6 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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