并肩作战的好兄弟实现快速汇总:字典 数组

文章作者:taller

图文整理:看见星光


前言

VBA开发者经常讨论的一个话题就是:字典和数组哪个效率更高?使得很多VBA初学者懵懂的认为,这两者非此即彼,水火不容。其实很多应用场景中,它们是并肩作战的好兄弟。

实例需求

已有生产排程数据如下所示。
需要整理为如下格式。
数据合并的要点有三个:
  • 料号和机种号为统计的关键字段

  • 未交数量求和

  • 交期汇总,包含时间和数量


示例代码

    Sub LoadData()    Dim aData, aRes(), lst, iRow, iCol, iKeyCol, Dic    Const COLUMNS_QTY = 21    With Sheets('交货排程')        iKeyCol = 5        lst = .Cells(.Rows.Count, iKeyCol).End(xlUp).Row        aData = .Cells(2, 1).Resize(lst, COLUMNS_QTY).Value    End With    Set Dic = CreateObject('Scripting.Dictionary')    For iRow = 3 To UBound(aData, 1)        skey = aData(iRow, 5) & '|' & aData(iRow, 6)        If Len(skey) > 1 Then            If Dic.exists(skey) Then                Dic(skey) = Array(Val(aData(iRow, 9)) + Dic(skey)(0), Dic(skey)(1))            Else                Dic(skey) = Array(Val(aData(iRow, 9)), '')            End If            For iCol = 11 To UBound(aData, 2)                If Val(aData(iRow, iCol)) > 0 Then                    sdate = VBA.Replace(Format(aData(2, iCol), 'm-d'), '-', '/')                    Debug.Print Dic(skey)(1) & ',' & sdate & '*' & aData(iRow, iCol)                    Dic(skey) = Array(Dic(skey)(0), Dic(skey)(1) & ',' & sdate & '*' & aData(iRow, iCol))                End If            Next iCol        End If    Next iRow    ReDim aRes(1 To Dic.Count, 1 To 4)    n = 1    For Each d In Dic.keys        akey = Split(d, '|')        aRes(n, 1) = akey(0)        aRes(n, 2) = akey(1)        aRes(n, 3) = Dic(d)(0)        aRes(n, 4) = Mid(Dic(d)(1), 2)        n = n + 1    Next    ' 结果数组aRes回写到工作表中    With Sheets('结果')        .Range('2:10000').ClearContents        .Cells(2, 1).Resize(Dic.Count, 4).Value = aRes        .Range('a1').CurrentRegion.Borders.LineStyle = xlContinuous    End With    Set Dic = NothingEnd Sub

    代码解析

    对于需要进行排重统计的应用,使用数组就可以实现,对于每个数据行都需要循环对比数组的全部元素,然而字典对象元素具有唯一性,因此对于排重统计有着独到的优势。
    对于每个关键字段组合,需要保存的信息有:两个关键字段,数量和相应的日期,此时数组就可以方便保存多个数据。因此使用字典和数组组合的双剑合璧,功力无敌!
    将工作表数据加载到数组的代码,不需要多讲。
      aData = .Cells(2, 1).Resize(lst, COLUMNS_QTY).Value
      将关键字段进行组合,确定字典的键值。
        skey = aData(iRow, 5) & '|' & aData(iRow, 6
        下面代码将一个 1 x 2的数组保存在字典对象中,如果skey是一个新的键值,那么将未交数量aData(iRow, 9)做为数组第一个元素,第二元素暂时留空。
        如果skey是一个在字典中已经存在的键值,那么Val(aData(iRow, 9)) + Dic(skey)(0)将未交数量进行累加,并保留已有的交期信息Val(aData(iRow, 9)) + Dic(skey)(0)
          If Dic.exists(skey) Then    Dic(skey) = Array(Val(aData(iRow, 9)) + Dic(skey)(0), Dic(skey)(1))Else    Dic(skey) = Array(Val(aData(iRow, 9)), '')End If
          与此类似,下面代码将汇总交期信息。注意更新字段对象的数组元素时,只能全部重新赋值,而不能使用Dic(skey)(0)='xxx'的形式
            For iCol = 11 To UBound(aData, 2)    If Val(aData(iRow, iCol)) > 0 Then        sdate = VBA.Replace(Format(aData(2, iCol), 'm-d'), '-', '/')        Debug.Print Dic(skey)(1) & ',' & sdate & '*' & aData(iRow, iCol)        Dic(skey) = Array(Dic(skey)(0), Dic(skey)(1) & ',' & sdate & '*' & aData(iRow, iCol))    End IfNext iCol
            对于字典中保存的数组元素,无法直接回写到工作表中,因此需要先构建回写的二维数组。Mid(Dic(d)(1), 2)用于去掉交期信息中的第一个逗号。
              For Each d In Dic.keys akey = Split(d, '|') aRes(n, 1) = akey(0) aRes(n, 2) = akey(1) aRes(n, 3) = Dic(d)(0) aRes(n, 4) = Mid(Dic(d)(1), 2) n = n + 1Next


              后记

              对于这个实例,只用数组可以实现吗?肯定可以实现,而且在数据量不大的情况下,效率差距也不大。不是只用保存数组的字典对象,而使用字典对象嵌套也可以实现。条条大路通罗马,希望大家能够灵活运用字典和数组组合。
              (0)

              相关推荐

              • 什么叫做『棋盘法』汇总?

                言归正传,今天我们要聊的是VBA中字典+数组的一种综合应用,多组数据汇总方案,我们称之为"棋盘法",主要的数据是二维交叉,类似棋盘! 比如,我们下面的销售明细,想按照销售名称,对数 ...

              • Excel VBA 字典的常用方式

                运用字典的时候,对比数组.主要是运用字典的去重效果. 最常用的两种应用: 一:统计相同人名的销售额 二:统计系统人名出现的次数(唱票) 统计销售额的示例: 先看一下运行代码: 运行的结果与H.I列数据 ...

              • 4.Python列表/元组/集合/字典

                碧茂大数据 前天 4.1 Python列表 · 列表用 [ ] 标识,是Python 最通用的复合数据类型. · 列表用 [ ] 表示,列表具有可嵌套性 4.1.1 Python列表截取 · 列表可以 ...

              • Excel巧设公式(字典+数字)

                有个网友提了这样的一个需求:A中有包含重复值的数据,现在需要将重复值所在单元格的值改为公式引用.例如:A6单元格值为3,第一个出现3的单元格为A5,所以将A6公式设置为=$A$5,其他单元格依次类推. ...

              • 【Excel VBA】字典+数组实现快速汇总

                数据合并的要点有三个: 料号和机种号为统计的关键字段 未交数量求和 交期汇总,包含时间和数量示例代码Sub LoadData() Dim aData, aRes(), lst, iRow, iCol, ...

              • 菜鸟记200—如果快速汇总各专业的核心课?

                关键词:EXCEL2016:组合工作表:LOOKUP函数:操作难度*** 期中教学检查开始了,咱们如果想掌握本学期开设核心课情况,怎么能从各专业教学进程表中快速获取这个信息呢? 图 1:教学进程表示例 ...

              • Excel如何快速汇总一年的数据?

                版权所有 转载须经Excel技巧网/Office学吧允许 [ Excel ]:快速输入1-1000的序列

              • 视频 | 批量合并Excel数据-3:多个文件数据快速汇总!

                      前面我梳理了关于<年终必用!批量汇总多Excel表:从入门到处理各种特殊情况>的相关文章,现陆续对其中的内容录制成系列视频,供大家参考.今天是第3个:        批量汇总E ...

              • 快速汇总销量和,用数据透视表,比函数更简单

                快速汇总数据,很多伙伴可能想到的是用函数进行汇总求和,其实还可以用数据透视表,比函数简单,又实用多了.下面一起来看个例子. 如图是原数据和汇总后的结果,这是怎么做的呢? 图为原数据 图为汇总后的结果 ...

              • Excel多工作表快速汇总,简单才是硬道理

                西门怡红超市,一个月每一天的销售报表存放在同一工作簿内: 现在要汇总1个月的销售数据,也就是将1~31日的工作表全部进行汇总. 效果如所示: 步骤1     新建一个汇总工作簿,依次单击[数据]→[新 ...

              • 玩转WPS表格 - 快速汇总销售数据

                想必年度.季度.月度总结时的你总是加班吧,一起来学习如何快速汇总销售数据吧!提高工作效率,早日摆脱OT. 图 7 - 41 所示的数据透视表中,通过对"出库日期"字段按年. 月.季 ...

              • 快速汇总销售数据,除了用Sumifs函数外,还可以用透视表

                对于下图的销售数据,如果要快速地进行汇总,一般情况下就是求和,除了运用Sumif或Sumifs函数外,还可以用数据透视表. 一.数据透视表法. 方法: 1.选定数据源的任意目标单元格区域. 2.[插入 ...

              • 快速汇总多个表格,用数据透视表吧!一学就会!#excel #excel技巧 #学习 #办公技巧 #职...

                快速汇总多个表格,用数据透视表吧!一学就会!#excel #excel技巧 #学习 #办公技巧 #职...