У меня есть следующие три таблицы (заголовок таблицы находится в строке 01):

Таблица 1: Подписки по датам

   | A         | B            | C          | D                   |
---|-----------|--------------|------------|---------------------|
01 | ID        | Type         | Start Date | End Date            |
02 | ID1       | T1           | 17.4.1     |                     |
03 | ID2       | T2           | 17.9.1     | 18.5.15             |
04 | ID3       | T1           | 20.6.1     |                     |
...

Таблица 2: Ежемесячная стоимость по типу подписки

   | A           | B
---|-------------|---------------
01 | Type        | Yearly Cost 
02 | T1          | 120
03 | T2          | 144
...

Таблица 3: Прогнозы расходов

   | A         | B
---|-----------|------------
01 | Year      | Expense s
02 | 2017      | 138      (T1 9 months: 90 + T2 4 months: 48)
03 | 2018      | 180      (T1 12 months: 120 + T2 5 months 60)
04 | 2019      | 120      (T1 12 months)
05 | 2020      | 190      (T1 12 months + 7 months)
06 | 2021      | 1240     (T1 24 months)
...

Я хотел бы автоматически вычислить столбец B третьей таблицы (без использования вспомогательных столбцов, в настоящее время это делается с помощью вспомогательной таблицы ...)

Я знаю, что это невозможно сделать с помощью sumif (), но можно ли добиться этого с помощью формулы массива?

У меня есть следующий псевдокод формулы для размещения в таблице 3:

for each line of table 2
  '
  '
  ' case 1: start date in year, end date not in year
  '
  if and(table3[year]=year(table1[startdate]), or(isblank(year(table1[enddate]),table3[year] < year(table1[enddate]))) then 
    '
    ' count months from startdate to end of year then multiply with monthlyrate
    '
    addtosum (12-month(table1[startdate]))*index(Table2,match(Table1[@[Type]],Table2[Type],0),2)
  '
  '
  ' case 2: startdate in year, enddate in year
  '
  elseif and(table3[year]=year(table1[startdate]),table3[year] = year(table1[enddate])) then 
    '
    ' count months between startdate and enddate then multiply with monthlyrate
    '
    addtosum (month(table1[enddate])-month(table1[startdate]))*index(Table2,match(Table1[@[Type]],Table2[Type],0),2)
  '
  '
  ' case 3: year larger than startdate, enddate is not reached
  '
  elseif and(table3[year]>year(table1[startdate]), or(isblank(year(table1[enddate]),table3[year]<year(table1[enddate]))) then 
    '
    ' multiply 12 months with monthlyrate
    '
    addtosum 12*index(Table2,match(Table1[@[Type]],Table2[Type],0),2)
  '
  '
  ' case 4: year larger than startdate, enddate is reached
  '
  elseif and(table3[year]>year(table1[startdate]),table3[year]=year(table1[enddate])) then 
    '
    ' count months from begining of year to enddate then multiply with monthlyrate
    '
    addtosum (month(table1[enddate])) * index(Table2,match(Table1[@[Type]],Table2[Type],0),2)
  end if
end for each

Вот созданная мной вспомогательная таблица:

Таблица 3: Прогнозы расходов

   | J     | K  | L    | M   | N     ... 
---|-------|----|------|-----| ----- ...
01 | Year  |    | ID1  | ID2 | ID3
02 | 2017  |    | 90   | 48  | 
03 | 2018  |    | 120  | 60  |
04 | 2019  |    | 120  | 0   |
05 | 2020  |    | 190  |     |
...

И это формула, которая у меня сейчас есть в ячейке L2 (она скопирована в L2: U5):

' Note: when calling index, column 4 is the Type, 5 is startdate, 6 is enddate)
=IF(NOT(ISBLANK(INDEX(Table1,MATCH(L$1,Table1[ID],0),5))),
    IF(AND($J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), OR(ISBLANK(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)),$J2 < YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)))),
        (12+1-MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),5))),
        IF(AND($J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), $J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))),
            (MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))-MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),5))),
            IF(AND($J2 > YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), OR(ISBLANK(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)),$J2 < YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6)))),
                12,
                IF(AND($J2 > YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),5)), $J2 = YEAR(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))),
                    (MONTH(INDEX(Table1,MATCH(L$1,Table1[ID],0),6))),
                    0
                )
            )
        )
    )*INDEX(Table2,MATCH(INDEX(Table1,MATCH(L$1,Table1[ID],0),4),Table2[Type],0),2)/12,
    0
)

Заранее спасибо за помощь,

0
Kraal 19 Сен 2018 в 19:53

2 ответа

Лучший ответ

Вы просили формулу. Используйте эту формулу массива:

=SUMPRODUCT(((J2>=YEAR($C$2:$C$4))*((J2<=YEAR($D$2:$D$4))+($D$2:$D$4=""))),
SUMIFS($G$2:$G$3,$F$2:$F$3,$B$2:$B$4),
((DATEDIF(IF($C$2:$C$4>DATE(J2,12,31),0,$C$2:$C$4),DATE(J2,12,31),"m")+1>12)*12-IF($D$2:$D$4<>"",MONTH(D1:D3)+2,0))+
(DATEDIF(IF($C$2:$C$4>DATE(J2,12,31),0,$C$2:$C$4),DATE(J2,12,31),"m")+1<=12)*
((DATEDIF(IF($C$2:$C$4>DATE(J2,12,31),0,$C$2:$C$4),DATE(J2,12,31),"m")+1)--IF($D$2:$D$4<>"",MONTH(D1:D3)+2,0)))

Будучи формулой массива, она должна быть подтверждена Ctrl-Shift-Enter вместо Enter при выходе из режима редактирования.

enter image description here

2
Scott Craner 19 Сен 2018 в 19:21

Вот еще одно решение:

=SUM(IF(ISBLANK(Table1[End Date]),IF(YEAR(Table1[Start Date])<Table3[@Year],12,IF(YEAR(Table1[Start Date])=Table3[@Year],13-MONTH(Table1[Start Date]),0)),IF(Table3[@Year]<YEAR(Table1[Start Date]),0,IF(Table3[@Year]=YEAR(Table1[Start Date]),IF(Table3[@Year]<YEAR(Table1[End Date]),13-MONTH(Table1[Start Date]),IF(Table3[@Year]=YEAR(Table1[End Date]),MONTH(Table1[End Date])-MONTH(Table1[Start Date])+1,0)),IF(Table3[@Year]<YEAR(Table1[End Date]),12,IF(Table3[@Year]=YEAR(Table1[End Date]),MONTH(Table1[End Date]),0)))))*SUMIFS(Table2[Monthly Cost],Table2[Type],Table1[Type]))

Это формула массива CTRL-SHIFT-ENTER.

Надеюсь, это поможет

0
xidgel 19 Сен 2018 в 23:54