Dez principais pedidos no Excel com base em regras de equipe complexas
-
09-06-2019 - |
Pergunta
Eu tenho uma planilha Excel em um formato semelhante ao seguinte ...
| 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 |
Preciso converter esta tabela em uma lista das equipes "Top Ten".As regras são
- A pontuação de cada equipe é obtida da soma de quatro membros daquele clube.
- Esses totais devem ser das quatro melhores pontuações, exceto...
- Cada equipe deve ser composta por pelo menos um Junior ou Lady
Por exemplo, na tabela acima, a pontuação da equipe para o clube A seria 625 não 640 como você faria com as pontuações de Harry (190), Bert (150), Jim (150) e Simon (130).Você não poderia pegar a pontuação de Fred (145), pois isso lhe daria apenas cavalheiros.
Minha dúvida é: isso pode ser feito facilmente como uma série de fórmulas do Excel ou precisarei recorrer a algo mais processual?
O ideal é que a solução seja automática nas seleções das equipes, não quero ter que criar fórmulas separadas e elaboradas à mão para cada equipe.Também não terei necessariamente uma lista ordenada dos membros de cada clube.Embora eu provavelmente pudesse gerar a lista por meio de uma planilha de cálculo extra.
Solução
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
Usar como =TopTen(H2,$B$2:$E$30)
onde H2
contém a carta do clube.
Outras dicas
isso pode ser feito facilmente como uma série de fórmula do Excel
Resposta curta, SIM.(Dependendo da sua definição de "facilmente").
Resposta longa...
(EU pensar isso funciona)
Aqui estão meus (breves) dados de teste:
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
Agora, se entendi as regras corretamente, queremos as quatro melhores pontuações, exceto que se a pontuação mais alta de uma senhora ou de um júnior não estiver entre as quatro melhores, usaremos essa pontuação em vez da quarta maior.Eu reformulei um pouco, por razões que podem se tornar aparentes...
OK.Matriz de fórmulas para o resgate!(Espero)
A pontuação mais alta da equipe a deve ser
{=LARGE(IF(B2:B16="a",D2:D16,0),1)}
onde {} indica uma fórmula de matriz criada usando Control-Shift-Enter para inserir a fórmula.Os quatro primeiros são criados de forma semelhante.Para a parte Lady/Junior, precisamos de um pouco mais de complexidade.Levando a Senhora, precisamos disso:
{=LARGE(IF($B$2:$B$16=$J3,IF($C$2:$C$16="Lady",$D$2:$D$16,0),0),1)}
Junior pode ser deixado com segurança como um exercício para o aluno, espero.
Agora estou olhando para uma mesa com o seguinte layout para o clube "a"
J K L M N O P
1 Club 1 2 3 4 Lady Junior
2 a 195 150 150 145 100 0
A pontuação do clube deve ser as três primeiras pontuações de "qualquer um" mais a melhor dama ou júnior se eles ainda não estiverem entre os quatro primeiros.
Então, no segundo trimestre, estou colocando isto:
=SUM(K2:M2)+MIN(MAX(O2,P2),N2)
MAX(O2,P2) me diz a pontuação da melhor senhora ou júnior, que deve ser incluída.Se for superior à quarta maior pontuação da equipe, então já está na lista e ficamos apenas com os quatro primeiros.Caso contrário, substituímos a quarta pontuação mais alta pela melhor senhora/júnior.
Agora poderíamos fazer tudo em uma fórmula, substituindo as partes na fórmula final:
{=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)))}
Mas não recomendo...
Então, para os dados acima, acabo com isto:
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
Ratos.Na minha empolgação por (eu acho) conseguir fazer a parte difícil funcionar, esqueci de mencionar isso
- A lista de pontuações pode estar em qualquer ordem
- Você pode obter as classificações do clube com RANK()
- Você pode então colocar os 10 primeiros em outra tabela usando 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
As colunas A e B são as nossas pontuações calculadas, a coluna E é a ordem em que os clubes serão apresentados na mesa final.As outras fórmulas são as seguintes:
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
O que eu faço é ridículo, mas funciona.
Basta criar uma nova coluna e inserir esta fórmula =If(a1=N,b1,0)
onde A1
é a coluna de critérios, N
são critérios e B1
está na coluna da qual você está tentando obter o tamanho grande.Então eu apenas faço a fórmula grande em outra coluna.
Às vezes fico todo chique e em vez de lançar um N
, vou fazer dizer $C$1
, e, em seguida, especifique os critérios nessa célula.
A resposta perfeita seria fazer com que a Microsoft adicionasse um largeifs
(por favor leia isto Microsoft)
Escrever uma solução em VBA seria minha primeira escolha, principalmente se as regras tiverem a possibilidade de se tornarem mais complexas.
Use uma tabela dinâmica que atuará como uma consulta ao banco de dados sobre os dados que você possui.Gire para que as equipes desçam nas colunas e os membros da equipe junto com seu tipo de status percorram a tabela dinâmica.Não tenho certeza para 2003, mas o Excel 2007 permite classificar para que as pontuações mais altas apareçam à esquerda.Então, sua primeira soma pode simplesmente levar as três primeiras pontuações de cada equipe.No entanto, para obter a soma das últimas pessoas, você deve determinar se pode usar a 4ª pontuação ou se deve usar o máximo dos tipos Junior ou Lady.Isso poderia ser feito usando uma fórmula complexa e de força bruta mais ou menos assim:
if (tipo de posição 1 é júnior ou senhora ou ...2 ou 3...) então use a posição 4 senão se a posição 5 for júnior ou senhora então use 5 senão se p 6 for ...e assim por diante.
Não acho que isso possa ser feito a menos que a tabela esteja ordenada de alguma forma.A maioria das funções de pesquisa do Excel requer listas ordenadas.Isso certamente poderia ser feito com uma função VBA.