Десять лучших заказов в Excel на основе сложных командных правил

StackOverflow https://stackoverflow.com/questions/57927

Вопрос

У меня есть таблица 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   |

Мне нужно преобразовать эту таблицу в список «десятки лучших» команд.Правила

  • Очки каждой команды снимаются из суммы четырех членов этого клуба.
  • Эти суммы должны состоять из четырех лучших результатов, за исключением...
    • Каждая команда должна состоять как минимум из одного юниора или леди.

Например, в таблице выше командный счет клуба А составит 625. нет 640, как если бы вы взяли баллы Гарри (190), Берта (150), Джима (150) и Саймона (130).Вы не можете принять результат Фреда (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

Теперь, если я правильно понял правила, нам нужны четыре лучших результата, за исключением того, что если наивысший балл женщины или юниора не входит в четверку лучших, мы используем его вместо четвертого по величине результата.Я несколько переформулировал это по причинам, которые могут стать очевидными...

ХОРОШО.Формулы массива вам в помощь!(Я надеюсь)

Наивысший балл команды А должен быть

{=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)}

Я надеюсь, что Джуниора можно смело оставить в качестве упражнения для ученика.

Я сейчас смотрю на стол со следующей раскладкой для клуба «а»


     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().
  • Затем вы можете перенести 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, затем укажите критерии в этой ячейке.

Идеальным ответом было бы, чтобы Microsoft добавила largeifs (пожалуйста, прочитайте это Microsoft)

Написание решения на VBA было бы моим первым выбором, особенно если правила могут усложниться.

Используйте сводную таблицу, которая будет выполнять функцию запроса к базе данных по имеющимся у вас данным.Поверните так, чтобы команды двигались вниз по столбцам, а члены команды вместе со своим типом статуса перемещались по сводной таблице.Я не уверен насчет 2003 года, но Excel 2007 позволяет выполнить сортировку таким образом, чтобы самые высокие баллы отображались слева.Тогда ваша первая сумма может просто состоять из первых трех очков каждой команды.Однако, чтобы получить сумму последнего человека, вам необходимо определить, можете ли вы использовать 4-й балл или вам нужно использовать максимум юниоров или леди.Это можно сделать, используя сложную и грубую формулу, примерно такую:

если (тип позиции 1 - юниор или дама или...2 или 3...) затем используйте позицию 4, иначе, если позиция 5 — юниор или леди, тогда используйте 5, иначе, если позиция 6 — ...и так далее.

Я не думаю, что это можно сделать, если таблица не отсортирована каким-либо образом.Большинству функций поиска Excel требуются упорядоченные списки.Это, безусловно, можно сделать с помощью функции VBA.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top