【发布时间】:2020-05-18 15:30:06
【问题描述】:
我每月收到大量任务,我想将这些任务分配给 6 个组,以便他们以均匀分布的方式进行评估。每个任务都有一个排名/优先级,所以如果一个小组收到第一名的任务,我不想也给同一个小组前 100 个优先级。我想应用蛇形/之字形分布。
这使我走上了使用公式=MIN(MOD(ROW()-2,12),MOD(-ROW()+1,12)) 的道路。我得到了我正在寻找的分布,尽管在这个阶段我不知道如何解释我需要添加到我的逻辑中的任何标准。
在上图中,我试图将column F 中的组应用到Column D。 Column E 显示了 =MOD() 公式的示例,我可以使用查找将 Mod 值 0-5 替换为我的组 1-6。
我遇到障碍的地方是第 21 行,这是我想说明一些标准或例外情况的地方。我添加了一个二进制column A 用于可视化,但本质上,我想说C 列(任务位置)= Loc4 的位置从不将任务分配给Group 4。在我不想将任务分配给位于 Loc 4 的第 4 组的情况下,我希望跳过 Group 4 进行单个分配,直到它可以应用于下一个可能的排名任务。简单的解决方案是在最后删除所有这些事件,但它确实扭曲了我想要的均匀分布。
我尝试将求解器应用于此作业,寻找最低标准偏差,但我的数据点太多。
这导致我使用一些 vba 逻辑写到另一篇文章,我真的很喜欢这个概念,但我不知道如何修改它以解决一些例外情况。 enter link description here
理想情况下,我很想使用创建我的组的单个数组的概念,只要在这个简短的任务列表中满足条件,将每个组应用于任务,将组写入列表,重置并移动到下一个任务子集。因此,每次我选择接下来的 6 个任务时,它们都会分配到我的 6 个组中的一个,这将保持我希望的分布。
这是我试图应用的用户 K.Davis 帖子中的代码:
Sub assignEmployeeTasks()
Dim ws As Worksheet, i As Long
Set ws = ThisWorkbook.Worksheets(1)
Dim employeeList() As Variant
With ws
For i = 2 To lastRow(ws, 2)
If (Not employeeList) = -1 Then
'rebuild employeelist / array uninitialized
employeeList = buildOneDimArr(ws, "F", 2, lastRow(ws, "F"))
End If
.Cells(i, 4) = randomEmployee(employeeList)
Next
End With
End Sub
这些是允许您的程序完成工作的“支持”功能:
Function randomEmployee(ByRef employeeList As Variant) As String
'Random # that will determine the employee chosen
Dim Lotto As Long
Lotto = randomNumber(LBound(employeeList), UBound(employeeList))
randomEmployee = employeeList(Lotto)
'Remove the employee from the original array before returning it to the sub
Dim retArr() As Variant, i&, x&, numRem&
numRem = UBound(employeeList) - 1
If numRem = -1 Then 'array is empty
Erase employeeList
Exit Function
End If
ReDim retArr(numRem)
For i = 0 To UBound(employeeList)
If i <> Lotto Then
retArr(x) = employeeList(i)
x = x + 1
End If
Next i
Erase employeeList
employeeList = retArr
End Function
' This will take your column of employees and place them in a 1-D array
Function buildOneDimArr(ByVal ws As Worksheet, ByVal Col As Variant, _
ByVal rowStart As Long, ByVal rowEnd As Long) As Variant()
Dim numElements As Long, i As Long, x As Long, retArr()
numElements = rowEnd - rowStart
ReDim retArr(numElements)
For i = rowStart To rowEnd
retArr(x) = ws.Cells(i, Col)
x = x + 1
Next i
buildOneDimArr = retArr
End Function
' This outputs a random number so you can randomly assign your employee
Function randomNumber(ByVal lngMin&, ByVal lngMax&) As Long
'Courtesy of https://stackoverflow.com/a/22628599/5781745
Randomize
randomNumber = Int((lngMax - lngMin + 1) * Rnd + lngMin)
End Function
' This gets the last row of any column you specify in the arguments
Function lastRow(ws As Worksheet, Col As Variant) As Long
lastRow = ws.Cells(ws.Rows.Count, Col).End(xlUp).Row
End Function
任何帮助将不胜感激!我愿意走任何更接近我想要的解决方案、公式或 vba 的路径。如果您有任何问题,请告诉我。
谢谢!
【问题讨论】:
-
你可以检查 Solver 和 assignment 模型 - 可能比 vba 更容易...
-
谢谢!我将再次查看围绕 Solver 的选项并查看一些分配模型。我的数据集有超过 150,000 条记录/任务,所以我假设我有太多变量,但也许我可以将数据分成子集。
标签: excel vba loops excel-formula