代码已做了详细注释:- Sub kagawa_Count() '字典统计 各公司有效发票数 (编号和客户代码相同合并算一单)
- Dim ar, tr, dic, i&, s$, t$, t1$, tms#
- tms = Timer
-
- tr = [a3].CurrentRegion '记录原数据
- [a3].CurrentRegion.Sort [e3], 1, [f3], , 1, , , 1 '按编号、客户代码排序
- ar = [a3].CurrentRegion '读取排序后数据到数组ar
- [a3].CurrentRegion = tr '恢复原数据状态
-
- Set dic = CreateObject("Scripting.Dictionary") '定义字典
- t1 = ar(1, 5) & ar(1, 6) '比较用合并编号和客户代码的初始值
- For i = 2 To UBound(ar)
- s = ar(i, 1) '以第1列公司名作为关键词key
- t = ar(i, 5) & ar(i, 6) '合并编号和客户代码
- If t <> t1 Then '如编号和客户代码不同则算一单
- dic(s) = dic(s) + 1 '统计计入该公司对应字典Item项
- t1 = t '更新合并编号和客户代码
- End If
- Next
- [j4].CurrentRegion = "" '清空统计区域
- [j4].Resize(dic.Count, 2) = WorksheetFunction.Transpose(Array(dic.Keys, dic.Items)) '输出字典统计结果
- [j4].Resize(dic.Count, 2).Sort [j4], 1, , , , , , 2 '按公司名称排序
- MsgBox Format(Timer - tms, "0.000s") '计算耗时
- End Sub
-
- Sub kagawa_Distribute()
- Dim ar, br, h&, i&, j&, m&, n&, s&, t&, tms#
- tms = Timer
-
- [j4].CurrentRegion.Sort [k4], 2, , , , , , 2 '按票数倒序排序
- ar = [j4].CurrentRegion '读取数据到数组ar
- [j4].CurrentRegion.Sort [j4], 1, , , , , , 2 '恢复按公司名称排序状态
-
- m = UBound(ar) '行数m即公司总数
- n = [j2] '指定人数n
- h = WorksheetFunction.Sum([k4].Resize(m)) '总和h
- s = WorksheetFunction.Max([k4].Resize(m)) '所有公司中票数最多公司的最大值s
- t = [k2]: If t = 0 Then t = h \ n + 1 '分配目标值t 可在K2单元格中指定 如无指定则按平均值计算
- If t < s Then MsgBox "最大票数公司 " & s & " > 分配目标值 " & t & vbCr & " 无法分配 请手工调整拆分该公司!": Exit Sub
- [p1] = t: [k2] = ""
-
- ReDim br(m, n + 5)
- For j = 1 To n + 5 '按人数分配
- For i = 1 To m '遍历检查各个公司
- If br(i, 0) = 0 Then '如该公司未被分配则
- If br(0, j) + ar(i, 2) <= t Then '如果分配后不超出目标值则可以分配
- br(i, 0) = ar(i, 1) '第1列记录公司名
- br(i, j) = ar(i, 2) '该业务员对应j列记入
- br(0, j) = br(0, j) + ar(i, 2) '在第1行统计该业务员对应j列的总计
- End If
- End If
- Next
- br(0, 0) = br(0, 0) + br(0, j) '全部已分配数进行统计
- If br(0, 0) = h Then Exit For '全部分配完成后退出
- Next
-
- [m3].CurrentRegion = "" '清空输出区域
- [m3].Resize(1 + m, 1 + j) = br '输出分配结果
- [m3].CurrentRegion.Sort [m3], 1, , , , , , 1 '结果按公司名称排序
- MsgBox Format(Timer - tms, "0.000s ") '计算耗时
- End Sub
复制代码 |