excel 如何在vba中按关键字优先排序顶级组

ckx4rj1h  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(110)

目前的执行结果都有分组和置顶的功能,但我希望能够间接地按照列v的顺序对结果进行排序
我希望处决的结果能像图片一样排序。请帮助我如何进行调整,使功能完整。Compare the two pictures, hoping to sort the results

Sub RETEAM()
    Dim Data_list() As String
    Dim BIG_name() As String
    Dim BIG_Team() As String
    Dim Data_dic As Object
    Set Data_dic = CreateObject("Scripting.Dictionary")
    Dim NUM_pos As Integer
    Dim Name_pos As Integer
    Dim Team_pos As Integer
    Dim BIG_pos As Integer
    Dim pos2 As Integer
    Dim pos4 As Integer
    Dim pos6 As Integer
    Dim pos8 As Integer
    Dim pos10 As Integer
    Dim pos12 As Integer
    Dim n As Integer
    Dim row As Integer
    Dim BIG_val As String
    Dim a_val As String
    Dim b_val As String
    Dim c_val As String
    Dim x As Integer
    Dim y As Variant
    Dim write_data() As String
    Dim num As Integer
    Dim key As Variant
    Dim value As Variant
    
    ReDim Data_list(1 To 100)
    ReDim BIG_name(1 To 100)
    ReDim BIG_Team(1 To 100)
    
    NUM_pos = 3
    Name_pos = 2
    Team_pos = 1
    BIG_pos = 22
    pos2 = 2
    pos4 = 2
    pos6 = 2
    pos8 = 2
    pos10 = 2
    pos12 = 2
    
    For n = 1 To 100
        row = n + 1
        BIG_val = CStr(Worksheets("team0").Cells(row, BIG_pos).value)
        If row >= 2 And BIG_val = "None" Then
            Exit For
        End If
        If row >= 2 Then
            BIG_name(n) = BIG_val
        End If
    Next n
    
    For n = 1 To 100
        row = n + 1
        a_val = CStr(Worksheets("team0").Cells(row, Team_pos).value)
        b_val = CStr(Worksheets("team0").Cells(row, Name_pos).value)
        c_val = CStr(Worksheets("team0").Cells(row, NUM_pos).value)
        
        For x = LBound(BIG_name) To UBound(BIG_name)
            If BIG_name(x) = b_val Then
                BIG_Team(x) = c_val
            End If
        Next x
        
        If row >= 2 And a_val = "None" Then
            Exit For
        End If
        
        If row >= 2 Then
            Data_list(n) = c_val & "," & b_val & "," & a_val
            
            If Data_dic.Exists(c_val) Then
                Data_dic(c_val) = Data_dic(c_val) & "," & a_val & "," & b_val
            Else
                Data_dic.Add c_val, a_val & "," & b_val
            End If
        End If
    Next n
    
    For Each value In BIG_Team
        write_data = Split(Data_dic(value), ",")
        num = UBound(write_data) + 1
        
        If num = 2 Then
            Worksheets("team0").Cells(pos2, Int(3 * (num / 2) + 1)).value = write_data(0)
            Worksheets("team0").Cells(pos2, Int(3 * (num / 2) + 2)).value = write_data(1)
            Worksheets("team0").Cells(pos2, Int(3 * (num / 2) + 3)).value = value
            pos2 = pos2 + 1
        ElseIf num = 4 Then
            For i = 0 To 1
                Worksheets("team0").Cells(pos4, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos4, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos4, Int(3 * (num / 2)) + 3).value = value
                pos4 = pos4 + 1
            Next i
        ElseIf num = 6 Then
            For i = 0 To 2
                Worksheets("team0").Cells(pos6, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos6, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos6, Int(3 * (num / 2)) + 3).value = value
                pos6 = pos6 + 1
            Next i
        ElseIf num = 8 Then
            For i = 0 To 3
                Worksheets("team0").Cells(pos8, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos8, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos8, Int(3 * (num / 2)) + 3).value = value
                pos8 = pos8 + 1
            Next i
        ElseIf num = 10 Then
            For i = 0 To 4
                Worksheets("team0").Cells(pos10, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos10, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos10, Int(3 * (num / 2)) + 3).value = value
                pos10 = pos10 + 1
            Next i
        ElseIf num = 12 Then
            For i = 0 To 5
                Worksheets("team0").Cells(pos12, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos12, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos12, Int(3 * (num / 2)) + 3).value = value
                pos12 = pos12 + 1
            Next i
        End If
        
        Data_dic.Remove value
    Next value
    
    For Each key In Data_dic.Keys
        write_data = Split(Data_dic(key), ",")
        num = UBound(write_data) + 1
        
        If num = 2 Then
            Worksheets("team0").Cells(pos2, Int(3 * (num / 2) + 1)).value = write_data(0)
            Worksheets("team0").Cells(pos2, Int(3 * (num / 2) + 2)).value = write_data(1)
            Worksheets("team0").Cells(pos2, Int(3 * (num / 2) + 3)).value = key
            pos2 = pos2 + 1
        ElseIf num = 4 Then
            For i = 0 To 1
                Worksheets("team0").Cells(pos4, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos4, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos4, Int(3 * (num / 2)) + 3).value = key
                pos4 = pos4 + 1
            Next i
        ElseIf num = 6 Then
            For i = 0 To 2
                Worksheets("team0").Cells(pos6, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos6, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos6, Int(3 * (num / 2)) + 3).value = key
                pos6 = pos6 + 1
            Next i
        ElseIf num = 8 Then
            For i = 0 To 3
                Worksheets("team0").Cells(pos8, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos8, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos8, Int(3 * (num / 2)) + 3).value = key
                pos8 = pos8 + 1
            Next i
        ElseIf num = 10 Then
            For i = 0 To 4
                Worksheets("team0").Cells(pos10, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos10, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos10, Int(3 * (num / 2)) + 3).value = key
                pos10 = pos10 + 1
            Next i
        ElseIf num = 12 Then
            For i = 0 To 5
                Worksheets("team0").Cells(pos12, Int(3 * (num / 2)) + 1).value = write_data(0 + i * 2)
                Worksheets("team0").Cells(pos12, Int(3 * (num / 2)) + 2).value = write_data(1 + i * 2)
                Worksheets("team0").Cells(pos12, Int(3 * (num / 2)) + 3).value = key
                pos12 = pos12 + 1
            Next i
        End If
    Next key
End Sub

字符串

67up9zun

67up9zun1#

我已经在这方面工作了一段时间,并让它与递归函数一起工作(这是我第一次尝试它,所以它可能不是“最佳”)和ofc与数组一起工作以提高速度。
无论是否使用BIG-sort值,排序都可以正常工作。如果有一个同名的团队,即使他们有BIG值,也要正确排序(最小的团队优先)。具有多个BIG值的团队获得上面排序的第一个大值,如果不同的团队具有相同的BIG值,则最小的团队首先出现(与其他团队一样)。

Option Explicit
Dim hasImportance_dic As Object
Dim funcIteration As Long

Sub RETEAM()
    Dim Data_dic As Object
    Set Data_dic = CreateObject("Scripting.Dictionary")
    Set hasImportance_dic = CreateObject("Scripting.Dictionary")
    Dim lRow As Long, arr, lRowV As Long, arrSort, amtSorted As Long
    Dim ws As Worksheet
    
    Set ws = ActiveWorkbook.Worksheets("team0")
    lRow = ws.Range("B" & Rows.Count).End(xlUp).row
    lRowV = ws.Range("V" & Rows.Count).End(xlUp).row
    arr = ws.Range("A2:C" & lRow).value
    If lRowV > 1 Then arrSort = ws.Range("V2:V" & lRowV).value
    
    Dim i As Long
    For i = 1 To UBound(arr, 1) 'counting the teams
        If Not Data_dic.Exists(arr(i, 3)) Then
            Data_dic.Add arr(i, 3), 1
        Else
            Data_dic(arr(i, 3)) = Data_dic(arr(i, 3)) + 1
        End If
    Next i
    
    'giving the team with importances a dictionary key so all can be sorted to the top later
    If Not IsEmpty(arrSort) Then
        Dim aSortRank As Long
        For i = 1 To UBound(arr, 1)
            aSortRank = aSortNeed(arrSort, arr(i, 2))
            If aSortRank > 0 Then
                If Not hasImportance_dic.Exists(arr(i, 3)) Then
                    hasImportance_dic.Add arr(i, 3), aSortRank
                Else
                    hasImportance_dic(arr(i, 3)) = Application.WorksheetFunction.Min(aSortRank, hasImportance_dic(arr(i, 3)))
                End If
            End If
        Next i
    End If
    
    Dim arrSorted(), dict As Object
    ReDim arrSorted(1 To UBound(arr, 1), 1 To 4)
    arrSorted(1, 1) = Data_dic(arr(1, 3))
    For i = 1 To UBound(arr, 2) 'filling in the first spot of the sorted array
        arrSorted(1, i + 1) = arr(1, i)
    Next i
    For i = 2 To UBound(arr, 1) 'sorting the whole list and placing in front what grouping they belong to
        arrSorted = sortArr(arrSorted, arr(i, 1), arr(i, 2), arr(i, 3), arrSort, Data_dic(arr(i, 3)), i)
    Next i
    Data_dic.RemoveAll
    
    For i = 1 To UBound(arrSorted, 1) 'checking what the size of each group will be
        If Not Data_dic.Exists(arrSorted(i, 1)) Then
            Data_dic.Add arrSorted(i, 1), 1
        Else
            Data_dic(arrSorted(i, 1)) = Data_dic(arrSorted(i, 1)) + 1
        End If
    Next i
    
    Dim arrPrint
    Dim j As Long, currGr As Long, k As Long, p As Long
    j = 1
    For i = 1 To Data_dic.Count 'basically used for offset as well
        currGr = arrSorted(j, 1)
        ReDim arrPrint(1 To Data_dic(arrSorted(j, 1)), 1 To 3) 'print array needs to get the correct size
        p = 1
        Do While currGr = arrSorted(j, 1) 'filling the print array
            For k = 1 To 3
                arrPrint(p, k) = arrSorted(j, k + 1)
            Next k
            j = j + 1
            p = p + 1
            If j > UBound(arrSorted, 1) Then 'exiting while without throwing an error with the array boundries
                j = 1
                currGr = -1
            End If
        Loop
        ws.Range("A2").Offset(0, i * 3).Resize(UBound(arrPrint, 1), UBound(arrPrint, 2)).value = arrPrint 'printing per 3 columns
    Next i
    
    Set Data_dic = Nothing
    Set hasImportance_dic = Nothing
End Sub

Function sortArr(a, gr, name, team, aSort, amt, amtSorted) As Variant()
    Dim j As Long, Sorted As Boolean, recursiveNeeded As Boolean
    Dim temp1, temp2, temp3, temp4
    funcIteration = funcIteration + 1
    Debug.Print "Going into the function " & funcIteration
    If Not IsEmpty(aSort) Then
        j = 1
        Do While (j < amtSorted) And (Not recursiveNeeded)
            If amt < a(j, 1) Then 'grouping needs to come before the one we're comparing with
                recursiveNeeded = True
            Else
                If amt = a(j, 1) Then
                    If team = a(j, 4) Then
                        If aSortNeed(aSort, name) > 0 Then
                            If aSortNeed(aSort, a(j, 3)) > 0 Then
                                If aSortNeed(aSort, a(j, 3)) > aSortNeed(aSort, name) Then 'in case multiple sort-values are in the same team
                                    recursiveNeeded = True
                                End If
                            Else
                                recursiveNeeded = True
                            End If
                        Else
                            If (name < a(j, 3)) And (Not aSortNeed(aSort, a(j, 3)) > 0) Then
                                recursiveNeeded = True
                            End If
                        End If
                    Else
                        If hasImportance_dic.Exists(a(j, 4)) Then
                            If hasImportance_dic.Exists(team) Then
                                If hasImportance_dic(a(j, 4)) > hasImportance_dic(team) Then
                                    recursiveNeeded = True
                                ElseIf hasImportance_dic(a(j, 4)) = hasImportance_dic(team) And team < a(j, 4) Then
                                    recursiveNeeded = True
                                End If
                            End If
                        ElseIf hasImportance_dic.Exists(team) Then
                            recursiveNeeded = True
                        Else
                            If team < a(j, 4) Then
                                recursiveNeeded = True
                            End If
                        End If
                    End If
                End If
            End If
            If recursiveNeeded Then
                temp1 = a(j, 1)
                temp2 = a(j, 2)
                temp3 = a(j, 3)
                temp4 = a(j, 4)
                a(j, 1) = amt
                a(j, 2) = gr
                a(j, 3) = name
                a(j, 4) = team
                a = sortArr(a, temp2, temp3, temp4, aSort, temp1, amtSorted)
            End If
            j = j + 1
        Loop
    Else
        j = 1
        Do While j < amtSorted And Not recursiveNeeded
            If amt < a(j, 1) Then
                recursiveNeeded = True
            ElseIf amt = a(j, 1) Then
                If team = a(j, 4) Then
                    If name < a(j, 3) Then recursiveNeeded = True
                Else
                    If team < a(j, 4) Then recursiveNeeded = True
                End If
            End If
            If recursiveNeeded Then
                temp1 = a(j, 1)
                temp2 = a(j, 2)
                temp3 = a(j, 3)
                temp4 = a(j, 4)
                a(j, 1) = amt
                a(j, 2) = gr
                a(j, 3) = name
                a(j, 4) = team
                a = sortArr(a, temp2, temp3, temp4, aSort, temp1, amtSorted)
            End If
            j = j + 1
        Loop
    End If
    If Not recursiveNeeded Then
        a(j, 1) = amt
        a(j, 2) = gr
        a(j, 3) = name
        a(j, 4) = team
    End If
    sortArr = a
End Function

Function aSortNeed(aSort, val) As Long
    Dim k As Long
    For k = 1 To UBound(aSort, 1)
        If aSort(k, 1) = val Then
            aSortNeed = k
            Exit Function
        End If
    Next k
    aSortNeed = 0
End Function

字符串
希望它足够清楚,如果没有,请随时提问。我对结果很满意(不是它是如何编写的,而是让它/递归函数按预期工作,可能会在代码审查帖子中抛出这个,看看在某个时候可以做得更好)

编辑:

若要使没有值且包含空团队的分组出现在第一个分组中(没有重复团队),请仅调整主子组:

Sub RETEAM_FIXED()
    Dim Data_dic As Object
    Set Data_dic = CreateObject("Scripting.Dictionary")
    Set hasImportance_dic = CreateObject("Scripting.Dictionary")
    Dim lRow As Long, arr, lRowV As Long, arrSort, amtSorted As Long
    Dim ws As Worksheet
    
    Set ws = ActiveWorkbook.Worksheets("team0")
    lRow = ws.Range("B" & Rows.Count).End(xlUp).row
    ws.Range("D2:U" & lRow).ClearContents
    lRowV = ws.Range("V" & Rows.Count).End(xlUp).row
    arr = ws.Range("A2:C" & lRow).value
    If lRowV > 1 Then arrSort = ws.Range("V2:V" & lRowV).value
    
    Dim i As Long
    For i = 1 To UBound(arr, 1) 'counting the teams
        If Not Data_dic.Exists(arr(i, 3)) Then
            Data_dic.Add arr(i, 3), 1
        ElseIf Len(arr(i, 3)) > 0 Then
            Data_dic(arr(i, 3)) = Data_dic(arr(i, 3)) + 1
        End If
    Next i
    
    'giving the team with importances a dictionary key so all can be sorted to the top later
    If Not IsEmpty(arrSort) Then
        Dim aSortRank As Long
        For i = 1 To UBound(arr, 1)
            aSortRank = aSortNeed(arrSort, arr(i, 2))
            If aSortRank > 0 Then
                If Not hasImportance_dic.Exists(arr(i, 3)) Then
                    hasImportance_dic.Add arr(i, 3), aSortRank
                Else
                    hasImportance_dic(arr(i, 3)) = Application.WorksheetFunction.Min(aSortRank, hasImportance_dic(arr(i, 3)))
                End If
            End If
        Next i
    End If
    
    Dim arrSorted(), dict As Object
    ReDim arrSorted(1 To UBound(arr, 1), 1 To 4)
    arrSorted(1, 1) = Data_dic(arr(1, 3))
    For i = 1 To UBound(arr, 2) 'filling in the first spot of the sorted array
        arrSorted(1, i + 1) = arr(1, i)
    Next i
    For i = 2 To UBound(arr, 1) 'sorting the whole list and placing in front what grouping they belong to
        arrSorted = sortArr(arrSorted, arr(i, 1), arr(i, 2), arr(i, 3), arrSort, Data_dic(arr(i, 3)), i)
    Next i
    Data_dic.RemoveAll
    
    For i = 1 To UBound(arrSorted, 1) 'checking what the size of each group will be
        If Not Data_dic.Exists(arrSorted(i, 1)) Then
            Data_dic.Add arrSorted(i, 1), 1
        Else
            Data_dic(arrSorted(i, 1)) = Data_dic(arrSorted(i, 1)) + 1
        End If
    Next i
    
    Dim arrPrint
    Dim j As Long, currGr As Long, k As Long, p As Long
    Dim lastGrouping
    lastGrouping = arrSorted(UBound(arrSorted, 1), 1)
    j = 1
    For i = 1 To lastGrouping 'basically used for offset as well
        currGr = arrSorted(j, 1)
        If currGr <> i Then GoTo skipEmptyColumns
        ReDim arrPrint(1 To Data_dic(arrSorted(j, 1)), 1 To 3) 'print array needs to get the correct size
        p = 1
        Do While currGr = arrSorted(j, 1) 'filling the print array
            For k = 1 To 3
                arrPrint(p, k) = arrSorted(j, k + 1)
            Next k
            j = j + 1
            p = p + 1
            If j > UBound(arrSorted, 1) Then 'exiting while without throwing an error with the array boundries
                j = 1
                currGr = -1
            End If
        Loop
        ws.Range("A2").Offset(0, i * 3).Resize(UBound(arrPrint, 1), UBound(arrPrint, 2)).value = arrPrint 'printing per 3 columns
skipEmptyColumns:
    Next i
    
    Set Data_dic = Nothing
    Set hasImportance_dic = Nothing
End Sub


请注意,我重命名了子,所以现在不能有任何名称问题。这里有一个例子来展示它确实按预期工作:
x1c 0d1x的数据

yqyhoc1h

yqyhoc1h2#

Range(“G1:I9”).Sort Key1:=Range(“H1”),Order1:= xl降序,Header:= xl是
V列中数据的排序不一定完全像我提到的那样。如果V的第一个值是110,第二个值是108,则排序将是不正确的。
as the picture shows

相关问题