楼主 liuguansky |
字典笔记.rar
源数据为编号和数量两列,编号为1-100的随机数,数量为1-10000的随机数。 首先是字典最简单也是最根本的一个运用 ,获取编号的不重复清单:
- Sub test1() '不重复清单
- Rem
- ' 相同代码行未作注释,请参照理解
- Rem
- Dim dic As Object, i% ' 定义相关变量
- Set dic = CreateObject("scripting.dictionary") ' 创建字典项目
- For i = 2 To Cells(Rows.Count, 1).End(3).Row '循环编号内容区域
- dic(Cells(i, 1).Value) = "" '赋值数组,因为没有使用ITEM,所以可以赋值"",书写方便
- Next i
- Range("c:D").Clear '清空结果返回区域
- Cells(1, 3) = "编号" '设置标题行
- Cells(2, 3).Resize(dic.Count, 1) = Application.Transpose(dic.keys) '依dic.keys的不重复性,返回不重复清单
- Rem DIC.KEYS是一维的行向量,需通过转置返回于列区间
- Set dic = Nothing '清空字典,释放内存
- End Sub
第二步,添加了各编号记录个数的统计 这里是ITEM常量构造的一个例子。代码如下:- Sub test2() '不重复清单及对应个数
- Dim dic As Object, i%
- Set dic = CreateObject("scripting.dictionary")
- For i = 2 To Cells(Rows.Count, 1).End(3).Row
- If dic.exists(Cells(i, 1).Value) Then dic(Cells(i, 1).Value) = dic(Cells(i, 1).Value) + 1 Else: dic(Cells(i, 1).Value) = 1
- Rem 构造ITEM
- '求个数,这里用了构造ITEM为1,进行EXISTS判断后累加处理
- Next i
- Range("e:G").Clear
- Cells(1, 5).Resize(1, 2) = Array("编号", "个数")
- Cells(2, 5).Resize(dic.Count, 1) = Application.Transpose(dic.keys)
- Cells(2, 6).Resize(dic.Count, 1) = Application.Transpose(dic.items)
- Set dic = Nothing
- End Sub
第三步,按编号进行汇总数量。代码如下:- Sub test3() '不重复清单并汇总
- Dim dic As Object, i%
- Set dic = CreateObject("scripting.dictionary")
- For i = 2 To Cells(Rows.Count, 1).End(3).Row
- If dic.exists(Cells(i, 1).Value) Then dic(Cells(i, 1).Value) = dic(Cells(i, 1).Value) + Cells(i, 2).Value Else: dic(Cells(i, 1).Value) = Cells(i, 2).Value
- Rem 构造ITEM
- '求数量,这里用了构造ITEM为数量,进行EXISTS判断后累加处理
- Next i
- Range("H:J").Clear
- Cells(1, 8).Resize(1, 2) = Array("编号", "数量")
- Cells(2, 8).Resize(dic.Count, 1) = Application.Transpose(dic.keys)
- Cells(2, 9).Resize(dic.Count, 1) = Application.Transpose(dic.items)
- Set dic = Nothing
- End Sub
思维同第二步。 |
2楼 liuguansky |
第四步,返回编号小于40,数量总计大于10000的汇总结果。代码如下- Sub test4() '数量大于10000,且编号小于40的记录汇总
- Dim dic As Object, i&, j&, arr
- Set dic = CreateObject("scripting.dictionary")
- For i = 2 To Cells(Rows.Count, 1).End(3).Row
- If dic.exists(Cells(i, 1).Value) Then dic(Cells(i, 1).Value) = dic(Cells(i, 1).Value) + Cells(i, 2).Value Else: dic(Cells(i, 1).Value) = Cells(i, 2).Value
- Next i
- ' 先返回各编号数量汇总
- arr = dic.keys
- For j = 0 To dic.Count - 1
- If arr(j) >= 40 Or dic(arr(j)) <= 10000 Then dic.Remove arr(j)
- Next j
- '再进行条件判断,把不符记录REMOVE,剩余即为所求记录
- Range("K:N").Clear
- Cells(1, 11).Resize(1, 2) = Array("编号", "数量")
- If dic.Count > 0 Then
- Cells(2, 11).Resize(dic.Count, 1) = Application.Transpose(dic.keys)
- Cells(2, 12).Resize(dic.Count, 1) = Application.Transpose(dic.items)
- End If
- Set dic = Nothing
- End Sub
第五步:编号大于30小于70且数量大于15000,小于45000的汇总结果和记录个数,代码如下:- Sub test5() '编号大于30小于70且数量大于15000,小于45000的记录
- Dim dic, i&, j&, m&, arr, arr1
- Set dic = CreateObject("scripting.dictionary")
- For i = 2 To Cells(Rows.Count, 1).End(3).Row
- If dic.exists(Cells(i, 1).Value) Then
- dic(Cells(i, 1).Value) = Split(dic(Cells(i, 1).Value), vbTab)(0) + Cells(i, 2).Value & vbTab & Split(dic(Cells(i, 1).Value), vbTab)(1) + 1
- Else: dic(Cells(i, 1).Value) = Cells(i, 2).Value & vbTab & 1
- End If
- Next i
- Rem ITEM构造
- '在之前基础上,多统计个数,此时构造ITEM时,可以把两个需统计记录用分隔符隔开,EXISTS累加的时,先用SPLIT取两段再累加。
- arr = dic.keys
- For j = 0 To dic.Count - 1
- If Not (arr(j) > 30 And arr(j) < 70 And Split(dic(arr(j)), vbTab)(0) < 45000 And Split(dic(arr(j)), vbTab)(0) > 15000) Then dic.Remove arr(j)
- Next j
- '再进行条件判断,把不符记录REMOVE,剩余即为所求记录
- Range("O:R").Clear
- arr1 = dic.items
- Cells(1, 14).Resize(1, 3) = Array("编号", "数量", "个数")
- If dic.Count > 0 Then
- '防止未有符合条件记录,返回错误。
- Cells(2, 14).Resize(dic.Count, 1) = Application.Transpose(dic.keys)
- For m = 0 To dic.Count - 1
- Cells(2 + m, 15).Resize(1, 2) = Application.Transpose(Application.Transpose((Split(arr1(m), vbTab))))
- Next m
- '转置两次,返回数值结果。
- End If
- Set dic = Nothing
- End Sub
难点: 1.对ITEM多个返回值和构造:<相同编号,其他文本项目连接,数字项目累加> [quote][上式中如果是文本连接用&,如果是数值相加就用+][/quote]
2.求差集
3.如果是差集,或其他返回满足条件记录,为防止DIC.COUNT为0,对返回值处理出错,就对DIC.COUNT进行判断
4.返回值如果是经SPLIT处理的。建议用两次Application.Transpose防止返回数据类型出错 第六步:返回数量大于编号*50,小于编号*200的汇总结果
- Sub test6() '数量大于编号*50,小于编号*200的记录
- Dim dic, i&, j&, m&, arr, arr1
- Set dic = CreateObject("scripting.dictionary")
- For i = 2 To Cells(Rows.Count, 1).End(3).Row
- If dic.exists(Cells(i, 1).Value) Then
- dic(Cells(i, 1).Value) = Split(dic(Cells(i, 1).Value), vbTab)(0) + Cells(i, 2).Value & vbTab & Split(dic(Cells(i, 1).Value), vbTab)(1) + 1
- Else: dic(Cells(i, 1).Value) = Cells(i, 2).Value & vbTab & 1
- End If
- Next i
- arr = dic.keys
- For j = 0 To dic.Count - 1
- If Val(Split(dic(arr(j)), vbTab)(0)) <= arr(j) * 50 Or Val(Split(dic(arr(j)), vbTab)(0)) >= arr(j) * 200 Then dic.Remove arr(j)
- Next j
- '条件判断,可以KEY与ITEM进行比较
- Range("S:V").Clear
- arr1 = dic.items
- Cells(1, 18).Resize(1, 3) = Array("编号", "数量", "个数")
- If dic.Count > 0 Then
- Cells(2, 18).Resize(dic.Count, 1) = Application.Transpose(dic.keys)
- For m = 0 To dic.Count - 1
- Cells(2 + m, 19).Resize(1, 2) = Application.Transpose(Application.Transpose((Split(arr1(m), vbTab))))
- Next m
- End If
- Set dic = Nothing
- End Sub
第七步,返回单行记录满足编号大于25,数量大于2500的编号与数量汇总结果及记录个数。代码如下:
- Sub test7() '判断单行记录是否满足编号大于25,数量大于2500,返回满足条件的编号与数量汇总清单
- Dim dic, i&, j&, m&, arr, arr1
- Set dic = CreateObject("scripting.dictionary")
- For i = 2 To Cells(Rows.Count, 1).End(3).Row
- If Val(Cells(i, 1).Value) > 25 And Cells(i, 2).Value > 2500 Then
- If dic.exists(Cells(i, 1).Value) Then
- dic(Cells(i, 1).Value) = Split(dic(Cells(i, 1).Value), vbTab)(0) + Cells(i, 2).Value & vbTab & Split(dic(Cells(i, 1).Value), vbTab)(1) + 1
- Else: dic(Cells(i, 1).Value) = Cells(i, 2).Value & vbTab & 1
- End If
- End If
- Next i
- Rem 判断记录后再进行字典处理
- Range("w:z").Clear
- arr1 = dic.items
- Cells(1, 22).Resize(1, 3) = Array("编号", "数量", "个数")
- If dic.Count > 0 Then
- '防止未有符合条件记录,返回错误。
- Cells(2, 22).Resize(dic.Count, 1) = Application.Transpose(dic.keys)
- For m = 0 To dic.Count - 1
- Cells(2 + m, 23).Resize(1, 2) = Application.Transpose(Application.Transpose((Split(arr1(m), vbTab))))
- Next m
- '转置两次,返回数值结果。
- End If
- Set dic = Nothing
- End Sub
|