分享

多条件汇总,汇总结果排序,多种方法,思路详解!

 冷茶视界 2024-05-14 发布于江苏

内容提要

  • 多条件汇总
  • VBA排序:工作表排序,SortedList排序
大家好,我是冷水泡茶。
今天在论坛上看到一个求助贴:[求助] 字典数组多条件多列汇总

详细需求:

字典数组多条件多列汇总

1.以部门和员工姓名为条件

2.以销售额、奖金、和提成的列求和

3.写入[j10]单元格 

具体数据表格:

1、Sheet1工作表,左边,原始数据

2、Sheet1工作表,右边,汇总结果

我们发现他的表头有点奇怪,真正的字段名称是在括号里面的,也许他是为了说明汇总的规则吧。看着这样的标题,我是浑身难受,一定要处理一下,这个后面再说,我们默认是表头经过处理后的数据。

多条件汇总,我们分享过一个案例【多条件查询统计:数据量太大,不想用SumProduct!】,跟今天的案例不太一样。

今天这个案例本身比较简单,但从学习VBA的角度来说,还是可以说道说道的

他的要求是采用字典数组来汇总,后来他又提出要按照部门、员工进行排序

说到排序,我们可以想到工作表排序SortedList排序数组排序等。

我按照前两种方法写了代码,我们一起来看一下:

基本思路1(字典、数组、工作表排序):

1、我们把数据读入数组arr,包括表头
2、我们循环数组arr,以部门+"|"+员工为key把数据添加到字典dic,itme为一个二级字典。
3、我们重定义一个数组temp,行数为字典的计数+1,列与arr相同。
4、我们循环arr第一行,把标题写入temp的第一行。
5、我们循环dic的所有key(dKey1),用m来计数,作为temp的行标,把key以“|”为分隔符分列到一个字符串数组str,得到两个元素,部门和员工,写入temp 的第1、2列,再以temp第一行,第3~5列字段为key(dKey2),从dic中提取数据,写入temp :
temp(m, i) = dic(dKey1)(dKey2)
6、以工作表的J1单元格为起点,设置一个与temp大小一致的区域rng,把temp的数据写入rng。
7、对rng按照第1列、第2列进行排序,本着【模块化编程】的思想,我们自定义一个Range排序过程SortRange
Sub SortRange( _        rng As Range, _        primarySortKey As Range, _        secondarySortKey As Range, _        Optional IncludeHeader As Boolean = True)    '//按两列排序,默认数据包含标题    Dim ws As Worksheet    Set ws = rng.Parent    With ws.Sort        .SortFields.Clear        .SortFields.Add _            Key:=primarySortKey, _            SortOn:=xlSortOnValues, _            Order:=xlAscending, _            DataOption:=xlSortNormal        .SortFields.Add _            Key:=secondarySortKey, _            SortOn:=xlSortOnValues, _            Order:=xlAscending, _            DataOption:=xlSortNormal        .SetRange rng        If IncludeHeader Then            .Header = xlYes        Else            .Header = xlNo        End If        .MatchCase = False        .Orientation = xlTopToBottom        .SortMethod = xlPinYin        .Apply    End WithEnd Sub

基本思路2(数组、SortedList排序):

1、我们把数据读入数组arr,包括表头
2、我们循环数组arr,以部门+"|"+员工为key把数据添加到SortedList,lst,其itme为一个二级SortedList,其实,这里的二级SortedList也可以换成字典,因为销售额、奖金、提成不需要排序。
3、我们重定义一个数组temp,行数为lst的计数+1,列与arr相同。
4、我们循环arr第一行,把标题写入temp的第一行。
5、我们循环lst的所有key(Key1),把key1以“|”为分隔符分列到一个字符串数组str,得到两个元素,部门和员工,写入temp 的第1、2列,再以temp第一行,第3~5列字段为key(Key2),从lst中提取数据,写入temp :
temp(i + 2, j) = lst.Item(key1).Item(key2)
6、以工作表的J1为起点,设置一个与temp大小一致的区域rng,把temp的数据写入rng。

VBA代码

代码详见第二条推文

后记

1、还有一种方法,就是数组排序,我们把dic的dkey1存到一个数组,对这个数组进行排序,然后再写入temp的第1、2列,然后再循环temp,把第1、2列组成dKey1,第1行第3~5列为dKey2,到dic中提取相应的数值,时间关系,我们就不再写代码了,关于数组排序的自义定函数、过程,公众号前期文章中应该分享过很多次,感兴趣的朋友可以搜一搜
2、在SortedList赋值、取值的过程中,“标准”格式是这样的:
lst.Item(key1).Item(key2) = lst.Item(key1).Item(key2) + arr(i, j)temp(i + 2, j) = lst.Item(key1).Item(key2)
后来我特发奇想,把“.Item”去掉试试,参照字典的使用方法:
lst(key1)(key2) = lst(key1)(key2) + arr(i, j)temp(i + 2, j) = lst(key1)(key2)
居然也能正常运行,我们可以发现,SortedList的用法,跟字典真是非常相似!
3、SortRange自定义过程,在Excel2003版中可能不能运行。
4、二级字典、SortedList,也可以换成一个数组来汇总存放销售额、奖金、提成数据,后面的代码也需要相应修改。
5、今天虽然是一个简单的案例,但我们可以从多个角度来寻求解决方案,从学习VBA的角度来说,就要这样多想、多练。
6、前文提到的表头字段问题,我们在第三条文章中讨论讨论,顺便写两个自定义过程。
好,今天就到这里,我们下期再会!
~~~~~~End~~~~~~

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多