Primi dieci ordinamenti in Excel basati su regole complesse del team
-
09-06-2019 - |
Domanda
Ho un foglio di calcolo Excel in un formato simile al seguente...
| 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 |
Devo convertire questa tabella in un elenco delle squadre "Top Ten".Le regole sono
- Il punteggio di ogni squadra viene preso dalla somma di quattro membri di quel club.
- Questi totali dovrebbero corrispondere ai migliori quattro punteggi, tranne...
- Ogni squadra dovrà essere composta da almeno un Junior o Lady
Ad esempio, nella tabella sopra il punteggio della squadra per il club A sarebbe 625 non 640 come prenderesti i punteggi di Harry(190), Bert(150), Jim(150) e Simon(130).Non potresti prendere il punteggio di Fred (145) perché ti darebbe solo Gents.
La mia domanda è: è possibile farlo facilmente con una serie di formule Excel o dovrò ricorrere a qualcosa di più procedurale?
Idealmente la soluzione deve essere automatica nelle selezioni della squadra, non voglio dover creare formule separate e realizzate a mano per ogni squadra.Inoltre, non avrò necessariamente un elenco ben ordinato dei membri di ciascun club.Anche se probabilmente potrei generare l'elenco tramite un foglio di calcolo aggiuntivo.
Soluzione
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
Usare come =TopTen(H2,$B$2:$E$30)
Dove H2
contiene la lettera del club.
Altri suggerimenti
Questo può essere fatto facilmente come una serie di formula Excel
Risposta breve, SI.(A seconda della tua definizione di "facilmente").
Risposta lunga...
(IO pensare funziona)
Ecco i miei (brevi) dati di 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
Ora, se ho capito bene le regole, vogliamo i migliori quattro punteggi, tranne che se il punteggio più alto di una donna o di un junior non è tra i migliori quattro, usiamo quello invece del quarto più alto.L'ho in qualche modo ribadito, per ragioni che potrebbero diventare evidenti...
OK.Formule di matrice in soccorso!(Spero)
Dovrebbe essere il punteggio più alto della squadra A
{=LARGE(IF(B2:B16="a",D2:D16,0),1)}
dove {} indica una formula di matrice creata utilizzando Control-Shift-Invio per inserire la formula.I primi quattro vengono creati in modo simile.Per la parte Lady/Junior, abbiamo bisogno di un po' più di complessità.Prendendo la Signora, abbiamo bisogno di questo:
{=LARGE(IF($B$2:$B$16=$J3,IF($C$2:$C$16="Lady",$D$2:$D$16,0),0),1)}
Spero che Junior possa tranquillamente essere lasciato come esercizio per lo studente.
Ora sto guardando una tabella con il seguente layout per il 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
Il punteggio del club dovrebbe essere costituito dai primi tre punteggi di "chiunque" più la migliore donna o junior se non sono già tra i primi quattro.
Quindi nella Q2 inserisco questo:
=SUM(K2:M2)+MIN(MAX(O2,P2),N2)
MAX(O2,P2) mi dice il punteggio migliore femminile o junior, che deve essere incluso.Se è superiore al quarto punteggio più alto della squadra, è già nell'elenco e prendiamo solo i primi quattro.Altrimenti sostituiremo il quarto punteggio più alto con quello della migliore lady/junior.
Ora potremmo fare tutto in un'unica formula, sostituendo le parti nella formula 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)))}
Ma non lo consiglio...
Quindi, per i dati di cui sopra, finisco con questo:
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
Ratti.Nella mia eccitazione per (credo) riuscire a far funzionare la parte difficile, ho dimenticato di dirlo
- L'elenco dei punteggi può essere in qualsiasi ordine
- Puoi ottenere la classifica del club con RANK()
- Puoi quindi inserire i primi 10 in un'altra tabella utilizzando MATCH() e 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
Le colonne A e B sono i nostri punteggi calcolati, la colonna E è l'ordine in cui i club verranno inseriti nel tavolo finale.Le altre formule sono le seguenti:
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
Quello che faccio è noioso, ma funziona.
Crea semplicemente una nuova colonna, quindi inserisci questa formula =If(a1=N,b1,0)
Dove A1
è la colonna dei criteri, N
è criteri e B1
è nella colonna da cui stai cercando di ottenere il valore grande.Quindi eseguo semplicemente la formula grande in un'altra colonna.
A volte divento tutto fantasioso e invece di stendere un N
, lo farò dire $C$1
, quindi specifica i criteri in quella cella.
La risposta perfetta sarebbe che Microsoft aggiungesse un file largeifs
(si prega di leggere questo Microsoft)
Scrivere una soluzione in VBA sarebbe la mia prima scelta, soprattutto se le regole hanno la possibilità di diventare più complesse.
Utilizza una tabella pivot che fungerà da query del database sui dati in tuo possesso.Ruota in modo che i team scendano nelle colonne e i membri del team insieme al loro tipo di stato attraversino la tabella pivot.Non sono sicuro per il 2003, ma Excel 2007 ti consente di ordinare in modo che i punteggi più alti vengano visualizzati a sinistra.Quindi la tua prima somma può semplicemente prendere i primi tre punteggi per ciascuna squadra.Tuttavia per ottenere la somma delle ultime persone, devi determinare se puoi utilizzare il 4° punteggio, o se devi utilizzare il massimo dei tipi junior o lady.Ciò potrebbe essere fatto utilizzando una formula complessa e di forza bruta simile a questa:
se (tipo di posizione 1 è junior o lady oppure...2 o 3...) quindi usa la posizione 4 altrimenti se la posizione 5 è junior o lady allora usa 5 altrimenti se p 6 è...e così via.
Non penso che ciò possa essere fatto a meno che la tabella non sia ordinata in qualche modo.La maggior parte delle funzioni di ricerca di Excel richiedono elenchi ordinati.Questo potrebbe sicuramente essere fatto con una funzione VBA.