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

您所在的位置:网站首页 数组字典vba 【Excel VBA】字典+数组实现快速汇总

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

2024-01-18 22:26| 来源: 网络整理| 查看: 265

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("ing.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 = Nothing

End 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 I

与此类似,下面代码将汇总交期信息。注意更新字段对象的数组元素时,只能全部重新赋值,而不能使用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 If

Next 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 + 1

Next

后记

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

图文作者:taller

ExcelHome论坛版主返回搜狐,查看更多



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3