Excel中基于复杂团队规则的前十名排序
-
09-06-2019 - |
题
我有一个类似于以下格式的 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) 和 Simon(130) 的分数一样。您不能接受 Fred(145)的分数,因为那只能给您男士。
我的问题是,这是否可以通过一系列 Excel 公式轻松完成,或者我是否需要诉诸于使用更程序化的东西?
理想情况下,解决方案需要在团队选择中自动进行,我不想为每个团队创建单独的手工公式。我也不一定有每个俱乐部成员的整齐排列的名单。尽管我可能可以通过额外的计算表生成列表。
解决方案
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
包含俱乐部信件。
其他提示
可以轻松地作为一系列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输入公式创建的数组公式。前四名的创建方式类似。对于女士/青少年,我们需要更复杂一点。以这位女士为例,我们需要这个:
{=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
我所做的很蹩脚,但很有效。
只需创建一个新列然后插入此公式 =If(a1=N,b1,0)
在哪里 A1
是标准列, N
是标准并且 B1
位于您试图从中获取大数据的列中。然后我就在另一列中做大公式。
有时我会变得很花哨,而不是推出一个 N
, ,我会说 $C$1
, ,然后阐明该单元格中的条件。
完美的答案是让微软添加一个 largeifs
(请阅读此微软)
用 VBA 编写解决方案将是我的第一选择,特别是如果规则有可能变得更加复杂的话。
使用数据透视表,它将充当您拥有的数据的数据库查询。进行透视,以便团队沿着列向下移动,并且团队成员及其状态类型沿着数据透视表移动。我不确定 2003 年的情况,但 Excel 2007 允许您进行排序,以便最高分数显示在左侧。然后你的第一个总和可以简单地取每支球队的前三个分数。然而,要获得最后一人的总和,您必须确定是否可以使用第四个分数,或者是否必须使用初级或女士类型的最大值。这可以使用复杂且强力的公式来完成,如下所示:
if(位置 1 的类型是初级或女士或...2 或 3...)然后使用位置 4,否则如果位置 5 是初级或女士,则使用 5,否则如果 p 6 是...等等。
我认为除非以某种方式对表进行排序,否则这是不可能完成的。大多数 Excel 查找函数都需要有序列表。这当然可以通过 VBA 函数来完成。