Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel OL_组和“2”).Resize(countGrp,1).Value Dim plan()作为字符串 ReDim计划(countGrp*尺寸,2) Dim itry作为整数,res iBlockStart=1 在iBlockStartUBound(grp)_Excel_Vba_Loops_Excel Formula - Fatal编程技术网

Excel OL_组和“2”).Resize(countGrp,1).Value Dim plan()作为字符串 ReDim计划(countGrp*尺寸,2) Dim itry作为整数,res iBlockStart=1 在iBlockStartUBound(grp)

Excel OL_组和“2”).Resize(countGrp,1).Value Dim plan()作为字符串 ReDim计划(countGrp*尺寸,2) Dim itry作为整数,res iBlockStart=1 在iBlockStartUBound(grp),excel,vba,loops,excel-formula,Excel,Vba,Loops,Excel Formula,OL_组和“2”).Resize(countGrp,1).Value Dim plan()作为字符串 ReDim计划(countGrp*尺寸,2) Dim itry作为整数,res iBlockStart=1 在iBlockStartUBound(grp),则 r=UBound(玻璃钢) 步骤=-1 如果r

OL_组和“2”).Resize(countGrp,1).Value Dim plan()作为字符串 ReDim计划(countGrp*尺寸,2) Dim itry作为整数,res iBlockStart=1 在iBlockStartUBound(grp),则 r=UBound(玻璃钢) 步骤=-1 如果r<1,则 r=1 步骤=1 如果结束 下一个 端接头 "洗牌计划", 子洗牌(计划作为变量,i作为整数) Dim tmp为字符串,n为整数,j为整数,k为整数 对于n=1到i '随机选择要洗牌的元素 重试: k=Int(1+Rnd()*UBound(平面)) j=Int(1+Rnd()*UBound(平面)) 如果k=j,则转到重试 tmp=计划(k,2) 计划(k,2)=计划(j,2) 计划(j,2)=tmp 下一个 端接头 '生成测试数据 子测试数据() 将ws设置为工作表,我设置为长 设置ws=ThisWorkbook.Sheets(“Sheet1”) 对于i=2至150001 ws.Cells(i,2)=i-1 ws.Cells(i,3)=“Loc”&1+Int(Rnd()*6) 下一个 端接头
您可以签出解算器和分配模型-可能比vba更简单…谢谢!我将再看一看围绕解算器的选项,并回顾一些分配模型。我的数据集有超过150K条记录/任务,所以我假设我有太多的变量,但也许我可以将数据分成子集。谢谢!很抱歉反应太慢。期待在周末尝试一下这段代码。感谢您的投入@记住,没关系,使用最新版本,因为我已经纠正了shuffle sub中的一个潜在错误。太棒了,谢谢!这太棒了!我可以将它作为一个表添加到我的数据库中,以保持程序的速度并保持数据输入的简单。我也很欣赏这些评论,这样我就可以跟进,因为我需要挑战自己,从零开始开发解决方案,而不是将其他解决方案拼凑在一起。
    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
Count of Task                               
Row     Loc1    Loc2    Loc3    Loc4    Loc5    Loc6    Gand Total
Gp1     4013    3975    3926    5082    3986    4018    25000
Gp2     4021    3992    4077    4928    3975    4007    25000
Gp3     3976    3952    4027    5023    4049    3973    25000
Gp4     5050    4915    4936            5035    5064    25000
Gp5     4072    3996    4034    4890    3969    4039    25000
Gp6     3964    4087    3986    5018    3996    3949    25000                               
Grand  25096    24917   24986   24941   25010   25050   150000
Option Explicit
Sub assignEmployeeTasks()


    Dim ws As Worksheet, t0 As Single, t1 As Single
    Set ws = ThisWorkbook.Sheets("Sheet1")
    t0 = Timer

    Const COL_GROUP = "F"
    Const COL_LOCN = "C"
    Const SIZE As Integer = 2 ' plan size =  2 * group count

    Const MAXTRY = 50 ' no of tries to validate

    Dim bOK As Boolean
    Dim grp As Variant, iBlockStart As Long, i As Integer, r As Integer, step As Integer

     'initialize grps and location
    Dim countGrp As Integer, lastLocn As Long
    lastLocn = ws.Range(COL_LOCN & Rows.Count).End(xlUp).Row

    countGrp = ws.Range(COL_GROUP & Rows.Count).End(xlUp).Row - 1
    grp = ws.Range(COL_GROUP & "2").Resize(countGrp, 1).Value
    Dim plan() As String
    ReDim plan(countGrp * SIZE, 2)

    Dim itry As Integer, res
    iBlockStart = 1

    Do While iBlockStart < lastLocn

        ' initialize plan
        Call zigzag(plan, grp)
        For i = 1 To UBound(plan)
            plan(i, 1) = ws.Range("C" & iBlockStart + i).Value
        Next

        ' save 1st attempt
        For i = 1 To UBound(plan)
            ws.Range("D" & iBlockStart + i).Value = plan(i, 2)
        Next

        ' validate
        bOK = validLocn(plan, 0)

retry:

        ' retry to validate
        itry = 0
        While bOK = False And itry < MAXTRY
            Call shuffle(plan, 1)
            bOK = validLocn(plan, itry)
            itry = itry + 1
        Wend

        ' write new plan to sheet
        For i = 1 To UBound(plan)
            ws.Range("D" & iBlockStart + i).Value = plan(i, 2)
        Next

        ' check rule again
        If itry = MAXTRY Then
            ws.Range(COL_LOCN & iBlockStart).Select
            res = MsgBox("Failed to vaidate after " & MAXTRY & " attempts", vbAbortRetryIgnore, iBlockStart)
            If res = vbRetry Then GoTo retry
            If res = vbAbort Then Exit Sub
        End If
        iBlockStart = iBlockStart + UBound(plan)
    Loop
    t1 = Timer
    MsgBox "Assigned " & lastLocn - 1 & " tasks in " & Int(t1 - t0) & " secs"

End Sub

 ' valid plan against rules
Function validLocn(plan As Variant, itry) As Boolean
    Dim sLocn As String, sGrp As String, i As Integer

    validLocn = True
    For i = 1 To UBound(plan)
        sLocn = plan(i, 1)
        sGrp = plan(i, 2)
        ' rule 1
        If sGrp = "Gp4" And sLocn = "Loc4" Then
            validLocn = False
            'Debug.Print itry, i, "Fail Rule 1", sGrp, sLocn
        Else
            'Debug.Print itry, i, "Pass Rule 1", sGrp, sLocn
        End If
    Next
End Function

' populate plan groups
Sub zigzag(plan As Variant, grp As Variant)
    Dim i As Integer, r As Integer, step As Integer
    r = 1: step = 1
    For i = 1 To UBound(plan)
        plan(i, 2) = grp(r, 1)
        r = r + step
        If r > UBound(grp) Then
            r = UBound(grp)
            step = -1
        ElseIf r < 1 Then
           r = 1
           step = 1
        End If
    Next
End Sub

' shuffle plan
Sub shuffle(plan As Variant, i As Integer)
    Dim tmp As String, n As Integer, j As Integer, k As Integer
    For n = 1 To i
       ' random choose elements to shuffle
retry:
        k = Int(1 + Rnd() * UBound(plan))
        j = Int(1 + Rnd() * UBound(plan))
        If k = j Then GoTo retry
        tmp = plan(k, 2)
        plan(k, 2) = plan(j, 2)
        plan(j, 2) = tmp
    Next
End Sub


' generate test data
Sub testdata()
    Dim ws As Worksheet, i As Long
    Set ws = ThisWorkbook.Sheets("Sheet1")
    For i = 2 To 150001
        ws.Cells(i, 2) = i - 1
        ws.Cells(i, 3) = "Loc" & 1 + Int(Rnd() * 6)
    Next
End Sub