Top dix des classements dans Excel basés sur des règles d'équipe complexes
-
09-06-2019 - |
Question
J'ai une feuille de calcul Excel dans un format similaire au suivant...
| 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 |
Je dois convertir ce tableau en une liste des équipes « Top Ten ».Les règles sont
- Le score de chaque équipe est tiré de la somme de quatre membres de ce club.
- Ces totaux doivent correspondre aux quatre meilleurs scores, sauf...
- Chaque équipe doit être composée d'au moins un Junior ou un Lady
Par exemple, dans le tableau ci-dessus, le score de l'équipe du club A serait de 625. pas 640 comme vous prendriez les scores de Harry (190), Bert (150), Jim (150) et Simon (130).Vous ne pouviez pas prendre le score de Fred (145), car cela vous donnerait uniquement des hommes.
Ma question est la suivante : cela peut-il être fait facilement sous la forme d'une série de formules Excel, ou dois-je recourir à quelque chose de plus procédural ?
Idéalement, la solution doit être automatique dans la sélection des équipes, je ne veux pas avoir à créer une formule artisanale distincte pour chaque équipe.Je n’aurai pas non plus nécessairement une liste bien ordonnée des membres de chaque club.Même si je pourrais probablement générer la liste via une feuille de calcul supplémentaire.
La solution
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
Utilisé comme =TopTen(H2,$B$2:$E$30)
où H2
contient la lettre du club.
Autres conseils
Cela peut-il être fait facilement comme une série de formules Excel
Réponse courte, OUI.(Selon votre définition de « facilement »).
Longue réponse...
(JE pense cela marche)
Voici mes (brèves) données de test :
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
Maintenant, si j'ai bien compris les règles, nous voulons les quatre meilleurs scores, sauf que si le score le plus élevé d'une dame ou d'un junior ne fait pas partie des quatre meilleurs, nous l'utilisons au lieu du quatrième.Je l'ai quelque peu reformulé, pour des raisons qui peuvent devenir évidentes...
D'ACCORD.Les formules matricielles à la rescousse !(J'espère)
Le score le plus élevé de l'équipe A devrait être
{=LARGE(IF(B2:B16="a",D2:D16,0),1)}
où le {} indique une formule matricielle créée en utilisant Control-Shift-Enter pour saisir la formule.Les quatre premiers sont créés de la même manière.Pour le bit Lady/Junior, il nous faut un peu plus de complexité.En prenant la Dame, nous avons besoin de ceci :
{=LARGE(IF($B$2:$B$16=$J3,IF($C$2:$C$16="Lady",$D$2:$D$16,0),0),1)}
J'espère que Junior peut être laissé en toute sécurité comme exercice pour l'élève.
Je regarde maintenant une table avec la disposition suivante pour le club "a"
J K L M N O P
1 Club 1 2 3 4 Lady Junior
2 a 195 150 150 145 100 0
Le score du club doit être constitué des trois meilleurs scores « n'importe qui » plus le meilleur score féminin ou junior. s'ils ne sont pas déjà dans le top quatre.
Donc au T2 je mets ceci :
=SUM(K2:M2)+MIN(MAX(O2,P2),N2)
MAX(O2,P2) m'indique le meilleur score féminin ou junior, qui doit être inclus.S'il est supérieur au quatrième score d'équipe le plus élevé, alors il est déjà dans la liste et nous prenons simplement les quatre premiers.Sinon, nous remplaçons le quatrième score le plus élevé par le meilleur score dame/junior.
Maintenant, nous pourrions tout faire en une seule formule, en remplaçant les parties dans la formule finale :
{=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)))}
Mais je ne le recommande pas...
Donc pour les données ci-dessus, j'obtiens ceci :
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
Les rats.Dans mon enthousiasme à l'idée (je pense) de faire la partie la plus difficile du travail, j'ai oublié de mentionner que
- La liste des scores peut être dans n'importe quel ordre
- Vous pouvez obtenir le classement des clubs avec RANK()
- Vous pouvez ensuite extraire le top 10 dans une autre table en utilisant MATCH() et INDEX()
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
Les colonnes A et B sont nos scores calculés, la colonne E est l'ordre dans lequel les clubs figureront dans le tableau final.Les autres formules sont les suivantes :
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
Ce que je fais est nul, mais ça marche.
Créez simplement une nouvelle colonne puis insérez cette formule =If(a1=N,b1,0)
où A1
est la colonne des critères, N
est un critère et B1
se trouve dans la colonne à partir de laquelle vous essayez d'obtenir le plus grand.Ensuite, je fais juste la grande formule dans une autre colonne.
Parfois, je suis très fantaisiste et au lieu de déployer un N
, je vais lui faire dire $C$1
, puis épelez les critères dans cette cellule.
La réponse parfaite serait que Microsoft ajoute un largeifs
(veuillez lire ceci Microsoft)
Écrire une solution en VBA serait mon premier choix, surtout si les règles risquent de devenir plus complexes.
Utilisez un tableau croisé dynamique qui agira comme une requête de base de données sur les données dont vous disposez.Pivotez pour que les équipes descendent dans les colonnes et que les membres de l'équipe ainsi que leur type de statut traversent le tableau croisé dynamique.Je ne suis pas sûr pour 2003, mais Excel 2007 vous permet ensuite de trier afin que les scores les plus élevés apparaissent à gauche.Ensuite, votre première somme peut simplement prendre les trois premiers scores de chaque équipe.Cependant pour obtenir la somme des dernières personnes, vous devez déterminer si vous pouvez utiliser le 4ème score, ou si vous devez utiliser le maximum des types junior ou Lady.Cela pourrait être fait en utilisant une formule complexe et brutale comme celle-ci :
si (type de poste 1 est une junior ou une dame ou...2 ou 3...) puis utilisez la position 4 sinon si la position 5 est une junior ou une dame puis utilisez 5 sinon si p 6 est ...et ainsi de suite.
Je ne pense pas que cela puisse être fait à moins que le tableau ne soit trié d'une manière ou d'une autre.La plupart des fonctions de recherche d'Excel nécessitent des listes ordonnées.Cela pourrait certainement être fait avec une fonction VBA.