【问题标题】:VBA sorting - expand code for 6 columnsVBA 排序 - 扩展 6 列的代码
【发布时间】:2012-03-14 17:13:48
【问题描述】:

我想知道是否有人可以帮助我扩展以下代码以处理 6 列。它已经适用于任意数量的行。如何为列添加相同的构造?用户名:assylias 构建了这段代码,我正在尝试调整它以满足我的排序需求。

问题: 我需要对这样的东西进行排序

X A 3
X B 7
X C 2
X D 4
Y E 8
Y A 9
Y B 11
Y F 2

需要进行如下排序: X 和 Y 所在的列代表组。字母:A、B、C、D、E、F 代表该组的成员。这些数字是我们用来比较它们的一些指标。获得该数字的最高数字和相关成员是该组的“领导者”,我想对数据进行排序,以便按以下方式将每个组的每个领导者与该组的每个成员进行比较:

X  B A 3
X  B C 2
X  B D 4
Y  B E 8
Y  B A 9
Y  B F 2

解释:B 恰好是两个组的领导者。我需要将他与所有其他成员进行比较,在他们单元格的右侧,有一列显示他们获得的数字。

问题:配备了 Assylias 的代码,我现在正尝试将其扩展到我的数据集。我的数据集有 6 列,因此有一堆定性列来描述每个成员(如 State、ID# 等),我需要帮助扩展代码以包含此内容。此外,如果可能的话,对某些步骤的解释(可能以 cmets 的形式)将使我能够更好地真正连接这些点。 (大多数情况下,我不明白 dict1/dict2 是什么以及它们到底在做什么......(dict1.exists(data(i,1)) 例如对我来说并不明显。

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
doIt
End Sub
Public Sub doIt()

Dim data As Variant
Dim result As Variant
Dim i As Long
Dim j As Long
Dim dict1 As Variant
Dim dict2 As Variant

Set dict1 = CreateObject("Scripting.Dictionary")
Set dict2 = CreateObject("Scripting.Dictionary")
data = Sheets("Sheet1").UsedRange

For i = LBound(data, 1) To UBound(data, 1)
    If dict1.exists(data(i, 1)) Then
        If dict2(data(i, 1)) < data(i, 3) Then
            dict1(data(i, 1)) = data(i, 2)
            dict2(data(i, 1)) = data(i, 3)
        End If
    Else
        dict1(data(i, 1)) = data(i, 2)
        dict2(data(i, 1)) = data(i, 3)
    End If
Next i

ReDim result(LBound(data, 1) To UBound(data, 1) - dict1.Count, 1 To 4) As Variant

j = 1
For i = LBound(data, 1) To UBound(data, 1)
    If data(i, 2) <> dict1(data(i, 1)) Then
        result(j, 1) = data(i, 1)
        result(j, 2) = dict1(data(i, 1))
        result(j, 3) = data(i, 2)
        result(j, 4) = data(i, 3)
        j = j + 1
    End If
Next i

With Sheets("Sheet2")
    .Cells(1, 5).Resize(UBound(result, 1), UBound(result, 2)) = result
End With

结束子

【问题讨论】:

标签: excel vba sorting


【解决方案1】:

我已对代码进行了注释并对其进行了修改以获得 6 列。现在它是一个快速的镜头,因此它可能会被改进、优化等。

Public Sub doIt()

    Dim inputData As Variant
    Dim result As Variant
    Dim thisGroup As String
    Dim thisMember As String
    Dim thisScore As String
    Dim i As Long
    Dim j As Long
    Dim membersWithHighestScore As Variant 'Will store the member with highest score for each group
    Dim highestScore As Variant 'Will store the highest score for each group

    Set membersWithHighestScore = CreateObject("Scripting.Dictionary")
    Set highestScore = CreateObject("Scripting.Dictionary")
    inputData = Sheets("Sheet1").UsedRange

    'First step: populate the dictionaries
    'At the end of the loop:
    '   - membersWithHigestScore will contain the member with the highest score for each group, for example: X=B, Y=B, ...
    '   - highestScore will contain for example: X=7, Y=11, ...
    For i = LBound(inputData, 1) To UBound(inputData, 1)
        thisGroup = inputData(i, 1) 'The group for that line (X, Y...)
        thisMember = inputData(i, 2) 'The member for that line (A, B...)
        thisScore = inputData(i, 3) 'The score for that line
        If membersWithHighestScore.exists(thisGroup) Then 'If there already is a member with a high score in that group
            If highestScore(thisGroup) < thisScore Then 'if this new line has a higher score
                membersWithHighestScore(thisGroup) = thisMember 'Replace the member with highest score for that group with the current line
                highestScore(thisGroup) = thisScore 'This is the new highest score for that group
            End If 'If the line is not a new high score, skip it
        Else 'First time we find a member of that group, it is by definition the highest score so far
            membersWithHighestScore(thisGroup) = thisMember
            highestScore(thisGroup) = thisScore
        End If
    Next i

    ReDim result(LBound(inputData, 1) To UBound(inputData, 1) - membersWithHighestScore.Count, 1 To 7) As Variant

    j = 1
    For i = LBound(inputData, 1) To UBound(inputData, 1)
        thisGroup = inputData(i, 1) 'The group for that line (X, Y...)
        thisMember = inputData(i, 2) 'The member for that line (A, B...)
        If thisMember <> membersWithHighestScore(thisGroup) Then 'If this is a line containing the highest score for that group, skip it
            result(j, 1) = thisGroup
            result(j, 2) = membersWithHighestScore(thisGroup)
            'Copy the rest of the data as is
            result(j, 3) = inputData(i, 2)
            result(j, 4) = inputData(i, 3)
            result(j, 5) = inputData(i, 4)
            result(j, 6) = inputData(i, 5)
            result(j, 7) = inputData(i, 6)
            j = j + 1
        End If
    Next i

    With Sheets("Sheet2")
        .Cells(1, 5).Resize(UBound(result, 1), UBound(result, 2)) = result
    End With

End Sub

【讨论】:

  • 这是一个非常清晰且非常有用的代码。这完全回答了我的问题,并为我提供了一个学习这种逻辑是如何构建的平台——我真诚地感谢你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 2022-06-14
相关资源
最近更新 更多