Reputation: 20761
I'm trying to SUM multiple columns of every rows that match a criteria.
I've a table with the time planned of multiple people over several tasks over the years:
In another table in the same file(let's admit in the same sheet), I'm trying to say, for every months, what is the time planned for every task, no matter the user, for the current month and the following ones.
Typically, for the cell for "January - Task 1", I would like to have 2+4+4+5+2+5 = 22 But for the same task, in July, I only expect to have 4+5+2+5 = 16, in august only 5+2+5=12, ...
When several people worked on the same task, their time should be also summed up.
I could, manually, for each task, summing the July->December for all the rows I know are assigned to this task, but there is a lot of tasks, I might add a task to some people, ... I would like, for each task to automatically search for all the assignement.
I tried to assemble some "SUMIF", but I didn't managed to have something working. I could see some way to make it work, by adding a column after each month that provide the sum of the next ones, but in my real case, I've 36 months, and that makes a lot of columns and noise.
Upvotes: 1
Views: 351
Reputation: 2614
SCAN
ning the monthly times for each task over the years , DROP
ping each column:
Using structured reference
=LET(
people, TEXTSPLIT("Henry,Francis,Georges", ","),
comment_1, "Assuming tasks <> people",
tasks, SORT(
FILTER(
Table1[Column1],
(LEN(TRIM(Table1[Column1])) > 0) * NOT(ISNUMBER(XMATCH(Table1[Column1], people)))
)
),
current_and_remaining, DROP(
REDUCE(
"",
tasks,
LAMBDA(acc, cur_task,
VSTACK(
acc,
SCAN(
0,
SEQUENCE(, COLUMNS(Table1) - 1),
LAMBDA(acc, cur, SUM(DROP(FILTER(Table1, Table1[Column1] = cur_task), , cur)))
)
)
)
),
1
),
VSTACK(
HSTACK("Current and remaining time", DROP(Table1[#Headers], , 1)),
HSTACK(tasks, current_and_remaining)
)
)
Just ranges
=LET(
people, TEXTSPLIT("Henry,Francis,Georges", ","),
people_tasks, $A$2:$A$15,
header, $A$1:$M$1,
data, $B$2:$M$15,
comment_1, "Assuming tasks <> people",
tasks, SORT(
FILTER(
people_tasks,
(LEN(TRIM(people_tasks)) > 0) *
NOT(ISNUMBER(XMATCH(people_tasks, people)))
)
),
times_for_current_and_remaining, DROP(
REDUCE(
"",
tasks,
LAMBDA(acc, cur_task,
VSTACK(
acc,
TRANSPOSE(
SCAN(
0,
SEQUENCE(COLUMNS(data)),
LAMBDA(acc, cur,
SUM(
DROP(
FILTER(
data,
people_tasks =
cur_task
),
,
cur - 1
)
)
)
)
)
)
)
),
1
),
VSTACK(
header,
HSTACK(tasks, times_for_current_and_remaining)
)
)
Upvotes: 0
Reputation: 1312
Instead of outputting the results to a structured table via calculated columns, or having to drag down and across with relative cell references, you could try the following single-cell dynamic array formula using MAP
to loop through 2 arrays at once:
=LET(
task_list, SORT(UNIQUE(TOCOL(IFS(DROP(Table1,, 1)<>"", Table1[Column1]), 2))),
cols, COLUMNS(Table1),
col_nums, SEQUENCE(, cols - 1, 2),
results, MAP(IF(col_nums, task_list), IF(SEQUENCE(ROWS(task_list)), col_nums),
LAMBDA(task,num,
SUM((Table1[Column1]=task) * INDEX(Table1,, num):INDEX(Table1,, cols))
)
),
HSTACK(
VSTACK("Remaining time planned", task_list),
VSTACK(DROP(Table1[#Headers],, 1), results)
)
)
Alternatively, SUM(FILTER(FILTER(...)))
can be used with the same method:
=LET(
values, DROP(Table1,, 1),
task_list, SORT(UNIQUE(TOCOL(IFS(values<>"", Table1[Column1]), 2))),
col_nums, SEQUENCE(, COLUMNS(values)),
results, MAP(IF(col_nums, task_list), IF(SEQUENCE(ROWS(task_list)), col_nums),
LAMBDA(task,num,
SUM(FILTER(FILTER(values, Table1[Column1]=task), col_nums>=num))
)
),
HSTACK(
VSTACK("Remaining time planned", task_list),
VSTACK(DROP(Table1[#Headers],, 1), results)
)
)
Upvotes: 0
Reputation: 11628
This could also be achieved with "old" Excel functions:
Paste this in the January-column and drag along:
=SUMPRODUCT(INDEX(Table1,,COLUMN(B:B)):INDEX(Table1,,13)*(Table1[[Column1]:[Column1]]=Table2[@[Remaining time planned]:[Remaining time planned]]))
(Or using absolute reference: =SUMPRODUCT(B$2:$M$15*($A$2:$A$15=$A18))
)
Upvotes: 3
Reputation: 6271
The formula in cell A10 to create the list of Tasks
=TOCOL(IF(LEFT(UNIQUE($A$3:$A$6),4)="Task",UNIQUE($A$3:$A$6),1/0),3)
The formula in cell B10 and drag to the right and down
=SUM(TAKE(FILTER($A$3:$M$6,$A$3:$A$6=$A10),,-(COLUMN($M$1)-COLUMN()+1)))
Upvotes: 2
Reputation: 1994
Hopefully you have office365. Then you can use FILTER
and DROP
.
In cell B19, formula is:
=IFERROR(SUM(DROP(FILTER($B$2:$M$15,$A$2:$A$15=$A19,0),0,B$17)),0)
FILTER($B$2:$M$15,$A$2:$A$15=$A19,0)
filter out rows with "Task1".
DROP(FILTER(), 0, B$17)
remove "previous months".
e.g For January, no columns are dropped, in February, the first column is dropped etc.
Finally, SUM
sums up the number.
In B17, I use =SEQUENCE(1,12,0,1)
Upvotes: 6