ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > E问E答 > Excel VBA > 如何用vba代码对进销数据进行汇总和排名?

如何用vba代码对进销数据进行汇总和排名?

作者:绿色风 分类: 时间:2022-08-17 浏览:122
楼主
kevinchengcw
Q: 如何用vba代码对进销数据进行汇总和排名?
A: 实现代码如下:
  1. Sub test()
  2. Dim Dic As Object, Arr(), Arrt(), Arr2(), Result(), N&, I&, T&, A&, D#, C&, Str$, Str2$
  3. Set Dic = CreateObject("scripting.dictionary")  '创建字典项目,用于快速汇总数据结果
  4. With Worksheets("进货数据")  '将进货数据区内容读取到数组中
  5.     Arr = .[a1].Resize(.Cells(.Rows.Count, 2).End(3).Row, 12).Value
  6. End With
  7. For N = LBound(Arr) + 1 To UBound(Arr)  '循环进货数据各行进行数据汇总
  8.     Str = Arr(N, 2) & vbTab & Arr(N, 4)
  9.     Str2 = Str & vbTab & "总进货数量"  '组合不同的key来储存不同的数据内容
  10.     If Dic.exists(Str2) Then Dic(Str2) = Dic(Str2) + Arr(N, 7) Else Dic(Str2) = Arr(N, 7)
  11.     Str2 = Str & vbTab & Arr(N, 1) & vbTab & 1  '后面的数字代表结果表中对应区下方的不同列,以克服文本的不统一(使用前提:表格格式固定且有规律)
  12.     If Dic.exists(Str2) Then Dic(Str2) = Dic(Str2) + Arr(N, 7) Else Dic(Str2) = Arr(N, 7)
  13.     Str2 = Str & vbTab & Arr(N, 1) & vbTab & 3
  14.     If Dic.exists(Str2) Then Dic(Str2) = Dic(Str2) + Arr(N, 7) Else Dic(Str2) = Arr(N, 7)
  15. Next N
  16. With Worksheets("销售数据")  '将销售数据区内容读取到数组中
  17.     Arr = .[a1].Resize(.Cells(.Rows.Count, 2).End(3).Row, 11).Value
  18. End With
  19. For N = LBound(Arr) + 1 To UBound(Arr)  '循环销售数据各行进行数据汇总
  20.     Str = Arr(N, 7) & vbTab & Arr(N, 9)  '组合不同的key来储存不同的数据内容
  21.     Str2 = Str & vbTab & Arr(N, 1) & vbTab & 2  '后面的数字代表结果表中对应区下方的不同列,以克服文本的不统一(使用前提:表格格式固定且有规律)
  22.     If Dic.exists(Str2) Then Dic(Str2) = Dic(Str2) + Arr(N, 11) Else Dic(Str2) = Arr(N, 11)
  23.     Str2 = Str & vbTab & "总销售数量"  '另添加当前区域总销售量数据统计
  24.     If Dic.exists(Str2) Then Dic(Str2) = Dic(Str2) + Arr(N, 11) Else Dic(Str2) = Arr(N, 11)
  25. Next N
  26. With Worksheets("跟踪模板")  '到跟踪模板工作表来处理结果数据
  27.     .Range("e3", .Cells.SpecialCells(xlCellTypeLastCell)).ClearContents  '清空结果数据区内容(因本例仅要求替代公式效果,故未添加自动获取销售商品清单功能)
  28.     ReDim Arr(1 To .Cells(.Rows.Count, 3).End(3).Row - 2, 1 To 1)  '初始化结果数据数组
  29.     For N = 5 To .Cells(1, .Columns.Count).End(1).Column   '循环数据区首行
  30.         If .Cells(1, N) <> "" Then  '如果单元格不为空(因有合并单元格,合并区域除首单元格外,其余都会是空)
  31.             For I = 3 To .Cells(.Rows.Count, 3).End(3).Row  '循环下方对应的数据行单元格
  32.                 If N = 5 Then Arr(I - 2, 1) = .Cells(I, 2).Value  '当处理第一列时添加男女分类到数组中,用于后期排名统计
  33.                 Str = .Cells(I, 3).Value & vbTab & .Cells(I, 4).Value & vbTab & .Cells(1, N).Value  '组合关键字
  34.                 If .Cells(1, N).Value Like "*区" Then  '判断所处区域,如果是各区列表区,则
  35.                     If I = 3 Then ReDim Preserve Arr(LBound(Arr) To UBound(Arr), LBound(Arr, 2) To UBound(Arr, 2) + 1)  '第一次处理当前区数据时在数组中添加对应数据区
  36.                     With .Cells(I, N)  '开始相对当前循环到的单元格区域进行数据处理
  37.                         For T = 1 To 3  '循环各列
  38.                             Str2 = Str & vbTab & T
  39.                             If Dic.exists(Str2) Then  '如果对应数据存在,则提取
  40.                                 .Offset(, T - 1).Value = Dic(Str2)
  41.                                 If T = 2 Then Arr(I - 2, UBound(Arr, 2)) = Dic(Str2)  '如果是销售量列,则将数据添加到数组中
  42.                             End If
  43.                         Next T
  44.                         .Offset(, 3).Value = .Value - .Offset(, 1).Value - .Offset(, 2).Value  '统计库存
  45.                     End With
  46.                 Else  '如果不是各区数据区,则
  47.                     If Dic.exists(Str) Then  '如果存在对应字典项目
  48.                         .Cells(I, N).Value = Dic(Str)  '对应数据写入当前循环到的单元格
  49.                         If .Cells(1, N).Value = "总销售数量" Then  '如果第一行当前循环到的列数据内容是"总销售数量",则
  50.                             If I = 3 Then ReDim Preserve Arr(LBound(Arr) To UBound(Arr), LBound(Arr, 2) To UBound(Arr, 2) + 1)  '第一次循环到时添加对应数组列
  51.                             Arr(I - 2, UBound(Arr, 2)) = Dic(Str)  '对应数据写入数组
  52.                         End If
  53.                     End If
  54.                 End If
  55.             Next I
  56.         End If
  57.         If .Cells(1, N).Value = "总销售数量" Then  '总销售量处理完成后,记录下下一列的列号,退出数据区循环
  58.             C = N + 1
  59.             Exit For
  60.         End If
  61.     Next N
  62.     For N = LBound(Arr, 2) + 1 To UBound(Arr, 2)  '循环数组第二列开始的各列,进行排名统计
  63.         Dic.RemoveAll  '清空字典内容
  64.         For I = LBound(Arr) To UBound(Arr)  '统计男女分类数据
  65.             If Dic.exists(Arr(I, 1)) Then
  66.                 Arrt = Dic(Arr(I, 1))
  67.                 ReDim Preserve Arrt(LBound(Arrt) To UBound(Arrt) + 1)
  68.                 Arrt(UBound(Arrt)) = Arr(I, N)
  69.                 Dic(Arr(I, 1)) = Arrt
  70.             Else
  71.                 ReDim Arrt(1 To 1)
  72.                 Arrt(1) = Arr(I, N)
  73.                 Dic(Arr(I, 1)) = Arrt
  74.             End If
  75.         Next I
  76.         Arr2 = Dic.keys  '提取字典项目
  77.         For I = LBound(Arr2) To UBound(Arr2)  '循环字典中各项(实际只男女两个分类)
  78.             Arrt = Dic(Arr2(I))  '提取对应的数据数组
  79.             If UBound(Arrt) > 1 Then  '如果数组内容多于一项,则进行排序
  80.                 For T = LBound(Arrt) To UBound(Arrt) - 1
  81.                     For A = T + 1 To UBound(Arrt)
  82.                         If Val(Arrt(A)) > Val(Arrt(T)) Then
  83.                             A = Val(Arrt(A))
  84.                             Arrt(A) = Val(Arrt(T))
  85.                             Arrt(T) = A
  86.                         End If
  87.                     Next A
  88.                     Str = Arr2(I) & vbTab & Arrt(T)  '排充结果与性别组合添加到字典,并记录对应的排名
  89.                     Dic(Str) = T
  90.                 Next T
  91.                 Dic(Arr2(I) & vbTab & Arrt(T)) = T
  92.             Else
  93.                 Dic(Arr2(I) & vbTab & Arrt(1)) = 1
  94.             End If
  95.         Next I
  96.         For I = LBound(Arr) To UBound(Arr)  '循环将数组中对应的数值转换为排名
  97.             Str = Arr(I, 1) & vbTab & Arr(I, N)
  98.             Arr(I, N) = Dic(Str)
  99.         Next I
  100.     Next N
  101.     ReDim Arrt(LBound(Arr) To UBound(Arr), LBound(Arr, 2) To UBound(Arr, 2) - 1)  '重写义最终排名结果数组Arrt,比预处理数组Arr少了姓名一列
  102.     For N = LBound(Arr) To UBound(Arr)  '将排名结果写入最终排名结果数组Arrt
  103.         For I = LBound(Arr, 2) + 1 To UBound(Arr, 2)
  104.             Arrt(N, I - 1) = Arr(N, I)
  105.         Next I
  106.     Next N
  107.     .Cells(3, C).Resize(UBound(Arrt), UBound(Arrt, 2)) = Arrt  '排名结果写入数据区
  108. End With
  109. Set Dic = Nothing  '清空字典项目
  110. End Sub
详见附件及素材源帖。



模版 - 副本.rar
2楼
xmyjk
唉,不容易啊,体力活,辛苦K哥了
3楼
清风不语
谢谢老师!
4楼
老糊涂
下载学习

免责声明

有感于原ExcelTip.Net留存知识的价值及部分知识具有的时间限定性因素, 经与ExcelTip.Net站长Apolloh商议并征得其同意, 现将原属ExcelTip.Net的知识帖采集资料于本站点进行展示, 供有需要的人士查询使用,也慰缅曾经的论坛时代。 所示各个帖子的原作者如对版权有异议, 可与本人沟通提出,或于本站点留言,我们会尽快处理。 在此,感谢ExcelTip.Net站长Apolloh的支持,感谢本站点所有人**绿色风(QQ:79664738)**的支持与奉献,特此鸣谢!
------本人网名**KevinChengCW(QQ:1210618015)**原ExcelTip.Net总版主之一

评论列表
sitemap