基于复杂团队规则的Excel中十大排序

时间:2008-09-11 23:41:16

标签: excel excel-vba spreadsheet vba

我有一个excel电子表格,其格式类似于以下...

| NAME  | CLUB | STATUS | SCORE |
| Fred  |  a   | Gent   | 145   |
| Bert  |  a   | Gent   | 150   |
| Harry |  a   | Gent   | 195   |
| Jim   |  a   | Gent   | 150   |
| Clare |  a   | Lady   | 99    |
| Simon |  a   | Junior | 130   |
| John  |  b   | Junior | 130   |
   :
   :
| Henry |  z   | Gent   | 200   |

我需要将此表转换为“十大”团队列表。规则是

  • 每支球队得分均取自该俱乐部四名成员的总和。
  • 这些总数应该是最好的四个分数,除了......
    • 每支队伍必须至少包括一名少年或女士

例如,在上表中,A俱乐部的球队得分为625 640,因为您将获得Harry(190),Bert(150),Jim(150)以及西蒙(130)。你不能拿弗雷德(145)的分数,因为这只会给你Gents。

我的问题是,这可以作为一系列Excel公式轻松完成,还是需要使用更多程序化的东西?

理想情况下,解决方案需要在团队选择中自动进行,我不想为每个团队创建单独的手工制作公式。我也不一定有一个整齐排列的每个俱乐部成员名单。虽然我可以通过额外的计算表生成列表。

6 个答案:

答案 0 :(得分:2)

Public Function TopTen(Club As String, Scores As Range)

    Dim i As Long
    Dim vaScores As Variant
    Dim bLady As Boolean
    Dim lCnt As Long
    Dim lTotal As Long

    vaScores = FilterOnClub(Scores.Value, Club)
    vaScores = SortOnScore(vaScores)

    For i = LBound(vaScores, 2) To UBound(vaScores, 2)
        If lCnt = 3 And Not bLady Then
            If vaScores(3, i) <> "Gent" Then
                lTotal = lTotal + vaScores(4, i)
                bLady = True
                lCnt = lCnt + 1
            End If
        Else
            lTotal = lTotal + vaScores(4, i)
            lCnt = lCnt + 1
            If vaScores(3, i) <> "Gent" Then bLady = True
        End If

        If lCnt = 4 Then Exit For
    Next i

    TopTen = lTotal

End Function

Private Function FilterOnClub(vaScores As Variant, sClub As String) As Variant

    Dim i As Long, j As Long
    Dim aTemp() As Variant

    For i = LBound(vaScores, 1) To UBound(vaScores, 1)
        If vaScores(i, 2) = sClub Then
            j = j + 1
            ReDim Preserve aTemp(1 To 4, 1 To j)
            aTemp(1, j) = vaScores(i, 1)
            aTemp(2, j) = vaScores(i, 2)
            aTemp(3, j) = vaScores(i, 3)
            aTemp(4, j) = vaScores(i, 4)
        End If
    Next i

    FilterOnClub = aTemp

End Function

Private Function SortOnScore(vaScores As Variant) As Variant

    Dim i As Long, j As Long, k As Long
    Dim aTemp(1 To 4) As Variant

    For i = 1 To UBound(vaScores, 2) - 1
        For j = i To UBound(vaScores, 2)
            If vaScores(4, i) < vaScores(4, j) Then
                For k = 1 To 4
                    aTemp(k) = vaScores(k, j)
                    vaScores(k, j) = vaScores(k, i)
                    vaScores(k, i) = aTemp(k)
                Next k
            End If
        Next j
    Next i

    SortOnScore = vaScores

End Function

使用=TopTen(H2,$B$2:$E$30) H2包含俱乐部信件。

答案 1 :(得分:2)

  

这可以作为一系列轻松完成   Excel公式

简短回答,是的。 (取决于您对“轻松”的定义)。

答案很长......

(我认为这有效)

这是我的(简要)测试数据:


    A          B    C        D
 1 NAME      CLUB STATUS  SCORE
 2 Kevin    a   Gent    145
 3 Lyle     a   Gent    150
 4 Martin   a   Gent    195
 5 Norm     a   Gent    150
 6 Oonagh   a   Lady    100
 7 Arthur   b   Gent    200
 8 Brian    b   Gent    210
 9 Charlie  b   Gent    190
10 Donald   b   Gent    220
11 Eddie    b   Junior  150
12 Quentin  c   Gent    145
13 Ryan     c   Gent    150
14 Sheila   c   Lady    195
15 Trevor   c   Gent    150
16 Ursula   c   Junior  200

现在,如果我正确理解规则,我们想要最好的四个分数,除非如果一个女士或一个大三的最高分数不是最好的四个,我们使用它而不是第四个最高分。我有点重申,原因可能很明显......

行。数组公式拯救! (我希望)

团队a的最高分应该是

{=LARGE(IF(B2:B16="a",D2:D16,0),1)}

其中{}表示使用Control-Shift-Enter输入公式创建的数组公式。前四名同样创建。对于Lady / Junior位,我们需要更复杂一点。以女士为例,我们需要这个:

{=LARGE(IF($B$2:$B$16=$J3,IF($C$2:$C$16="Lady",$D$2:$D$16,0),0),1)}

我希望,Junior可以安全地留给学生锻炼身体。

我现在正在寻找一张有以下布局的桌子“a”


     J    K      L      M      N      O      P
 1 Club    1      2      3      4   Lady  Junior
 2 a     195    150    150    145    100      0

俱乐部得分应该是前三名“任何人”得分加上最好的女士或者初级如果他们还没有进入前四名

所以在第二季我就是这样说的:

=SUM(K2:M2)+MIN(MAX(O2,P2),N2)

MAX(O2,P2)告诉我最好的女士或者初级分数,必须包括在内。如果它高于第四高的球队得分,那么它已经在列表中,我们只进入前四。否则,我们用最好的女士/初级成绩取代第四高分。

现在我们可以在一个公式中完成所有操作,将部分替换为最终公式:

{=LARGE(IF($B$2:$B$16=$J3,$D$2:$D$16,0),1)+
LARGE(IF($B$2:$B$16=$J3,$D$2:$D$16,0),2)+
LARGE(IF($B$2:$B$16=$J3,$D$2:$D$16,0),3)+
MIN(LARGE(IF($B$2:$B$16=$J3,$D$2:$D$16,0),4),
MAX(LARGE(IF($B$2:$B$18=$J3,IF($C$2:$C$18="Lady",$D$2:$D$18,0),0),1),
LARGE(IF($B$2:$B$18=$J3,IF($C$2:$C$18="Junior",$D$2:$D$18,0),0),1)))}

但我不推荐它......

因此,对于上述数据,我最终得到了这个:


            Anyone                                          Lady        Junior                
Club        1           2           3           4           1           1           Total     
a           195         150         150         145         100         0           595       
b           220         210         200         190         0           150         780       
c           200         195         150         150         195         200         695       

大鼠。令我兴奋的是(我认为)让困难的部分工作我忘了提到

  • 分数列表可以按任何顺序
  • 您可以通过RANK()
  • 获得俱乐部排名
  • 然后,您可以使用MATCH()和INDEX()
  • 将前10名拉到另一个表中

    A               B       C       D           E       F       G               H    
1   club            Sc      Rank    UniqRk              Pos     Club            Score
2   third-equal#1   80      3       79.999980   1       1       best            100  
3   second          90      2       89.999970   2       2       second          90   
4   third-equal#2   80      3       79.999960   3       3       third-equal#1   80   
5   best            100     1       99.999950   4       3       third-equal#2   80   
6   worst           70      5       69.999940   5       5       worst           70   

A列和B列是我们计算的分数,E栏是决赛桌中输出分会的顺序。其他公式如下:

C: =RANK(B2,$B$2:$B$6)      # what it says, with ties both getting the lower number
D: =B2-ROW()*0.00001        # score, modified slightly to ensure uniqueness
F: =SMALL($C$2:$C$6,E2)     # first output column, ranks including ties
G: =INDEX($A$2:$A$6,MATCH(LARGE($D$2:$D$6,E2),$D$2:$D$6,0))
                            # club name for position, using the modified score in D
H: =INDEX($B$2:$B$6,MATCH(LARGE($D$2:$D$6,E2),$D$2:$D$6,0))
                            # as G, but indexes into scores

答案 2 :(得分:1)

我做的是跛脚,但它有效。

只需创建一个新列,然后插入此公式=If(a1=N,b1,0),其中A1为条件列,N为条件,B1位于您要获取的列中来自的大。然后我就在另一栏中做大公式。

有时候我会得到所有的幻想,而不是推出N,我会说出$C$1,然后拼出那个单元格中的标准。

完美的答案是让Microsoft添加largeifs(请阅读此Microsoft)

答案 3 :(得分:0)

使用数据透视表,它将充当您拥有的数据的数据库查询。透视,以便团队沿着列,团队成员及其状态类型进入数据透视表。我不确定2003年,但Excel 2007让你排序,所以最高分出现在左边。然后你的第一笔金额可以简单地取得每支球队的前三个得分。然而,要获得最后一个人的总和,您必须确定是否可以使用第4个分数,或者如果您必须使用初级或女士类型的最大值。这可以使用复杂而强力的公式来完成:

如果(职位1的类型是初级或女士或......或2或3 ...)然后使用位置4,如果位置5是初级或女士,则使用5其他如果p 6是...等等。

答案 4 :(得分:0)

在VBA中编写解决方案将是我的首选,特别是如果规则有可能变得更加复杂。

答案 5 :(得分:0)

除非以某种方式对表进行排序,否则我认为不能这样做。大多数Excel的查找函数都需要有序列表。这肯定可以通过VBA功能完成。