Forum Discussion

matt0020190's avatar
matt0020190
Brass Contributor
Feb 10, 2025
Solved

Two way sum lookup (by month & name)

Hi all

 

I am trying to perform a two way lookup from a source table. 

Basically I have names of colleagues with a number of days per week recorded.

I want to then in another table using a formula sum the total amount of days by colleague for each month.

I tried using SUMIFS, but it throws a VALUE error as I think the SUM range is not accepted across multiple columns/rows.

Any ideas? 

I attach a sample spreadsheet.

 

Thank you in advance

 

 

  • Another option for modern Excel:

    =LET(
        rϑws, MAP(A12:A15, LAMBDA(v, LET(x, XLOOKUP(v, A4:A7, B4:W7, B2:W2), LAMBDA(x)))),
        cϑls, MAP(B11:G11, EOMONTH(+B11:G11, 0), LAMBDA(s,e, LAMBDA(n, CHOOSE(n, s, e)))),
        MAP(IFNA(rϑws, cϑls), IFNA(cϑls, rϑws), LAMBDA(r,c, SUMIFS(r(), B3:W3, ">=" & c(1), B3:W3, "<=" & c(2))))
    )

    This method uses the concept of "thunks" to store the applicable row of data for each name, as well as the applicable start and end dates for each period, inside a separate LAMBDA function. The two resulting vectors of "thunks" are then broadcast both across and down to fill an array for the entire output grid, and MAP loops through both arrays together, applying SUMIFS to each applicable row for each applicable period.

    Alternatively, GROUPBY could also be used, but the order of names will not be exactly the same as the desired output table shown in your sample file:

    =LET(
        tbl, TRANSPOSE(A3:W7),
        mth, IFERROR(EOMONTH(TAKE(tbl,, 1), 0), "Name"),
        arr, TRANSPOSE(GROUPBY(mth, DROP(tbl,, 1), SUM, 3, 0)),
        VSTACK(TEXT(TAKE(arr, 1), "mmm-yy"), DROP(arr, 1))
    )

    Cheers!

  • djclements's avatar
    djclements
    Bronze Contributor

    Another option for modern Excel:

    =LET(
        rϑws, MAP(A12:A15, LAMBDA(v, LET(x, XLOOKUP(v, A4:A7, B4:W7, B2:W2), LAMBDA(x)))),
        cϑls, MAP(B11:G11, EOMONTH(+B11:G11, 0), LAMBDA(s,e, LAMBDA(n, CHOOSE(n, s, e)))),
        MAP(IFNA(rϑws, cϑls), IFNA(cϑls, rϑws), LAMBDA(r,c, SUMIFS(r(), B3:W3, ">=" & c(1), B3:W3, "<=" & c(2))))
    )

    This method uses the concept of "thunks" to store the applicable row of data for each name, as well as the applicable start and end dates for each period, inside a separate LAMBDA function. The two resulting vectors of "thunks" are then broadcast both across and down to fill an array for the entire output grid, and MAP loops through both arrays together, applying SUMIFS to each applicable row for each applicable period.

    Alternatively, GROUPBY could also be used, but the order of names will not be exactly the same as the desired output table shown in your sample file:

    =LET(
        tbl, TRANSPOSE(A3:W7),
        mth, IFERROR(EOMONTH(TAKE(tbl,, 1), 0), "Name"),
        arr, TRANSPOSE(GROUPBY(mth, DROP(tbl,, 1), SUM, 3, 0)),
        VSTACK(TEXT(TAKE(arr, 1), "mmm-yy"), DROP(arr, 1))
    )

    Cheers!

    • djclements's avatar
      djclements
      Bronze Contributor

      One more dynamic array option, using MMULT:

      =MMULT(--(A12:A15=TOROW(A4:A7)),MMULT(--B4:W7,--(EOMONTH(+B11:G11,0)=TOCOL(EOMONTH(+B3:W3,0)))))

      Plus, an improved variation of my previous GROUPBY suggestion:

      =LET(
          tbl, TRANSPOSE(A3:W7),
          arr, TRANSPOSE(GROUPBY(EOMONTH(TAKE(tbl,, 1), 0), DROP(tbl,, 1), SUM, 3, 0)),
          VSTACK(IFERROR(TEXT(TAKE(arr, 1), "mmm-yy"), "Name"), DROP(arr, 1))
      )
  • p45cal's avatar
    p45cal
    Copper Contributor

    Try in cell B12:

    =SUM(FILTER(FILTER($B$4:$W$7,(MONTH($B$3:$W$3)=MONTH(B$11))*(YEAR($B$3:$W$3)=YEAR(B$11))),$A$4:$A$7=$A12))

    and copy down and across.

  • Patrick2788's avatar
    Patrick2788
    Silver Contributor

    This task becomes a lot easier when the data is flattened out. In this example we start with "pivoted" data.

    Two different ways to do this:

    1. Load data into PowerQuery, unpivot to flatten out (and set date column to be treated as dates), and then create pivot table.

    Unpivot columns - Power Query | Microsoft Learn

    2.  UnPivot with a Lambda and then use PIVOTBY to aggregate the data.

    =LET(
        flat, UnPivotMλ(names, weeks, data),
        name_col, TAKE(flat, , 1),
        dates, CHOOSECOLS(flat, 2),
        month_year, DATE(YEAR(dates), MONTH(dates), 1),
        val, TAKE(flat, , -1),
        PIVOTBY(name_col, month_year, val, SUM, , 0, , 0)
    )

    Where UnPivotMλ is a generalized Lambda which unpivots a matrix by providing rows, columns, and values:

    UnPivotMλ = LAMBDA(rows, columns, values,
            LET(
                i, ROWS(rows),
                j, COLUMNS(rows),
                c, COLUMNS(columns),
                s, TOCOL(SEQUENCE(, j) * SEQUENCE(c, , 1, 0)),
                row_labels, WRAPROWS(TOCOL(CHOOSECOLS(rows, s)), j),
                attribute, TOCOL(CHOOSEROWS(columns, SEQUENCE(i, , 1, 0))),
                v, TOCOL(values),
                HSTACK(row_labels, attribute, v)
            )
        );

    I know some will say this is too much but if you encounter data that needs to be fixed before analyzing, I think it makes sense to have a function in your library on hand to flatten out data. It takes a lot of the leg work. No need to repeat common cleanup tasks.

    • matt0020190's avatar
      matt0020190
      Brass Contributor

      Thanks very much for your detailled and quick reply.

      This may be a stupid question but what is "pivoted" data that needs "flattening out"?

      • Patrick2788's avatar
        Patrick2788
        Silver Contributor

        Flattend data:

        "Pivoted" data:

        Flattened data is much easier to summarize because we know the dates are in column 2 and the values are in column 3.  PIVOTBY and a PivotTable can make quick work of vertically arranged data.  The screen cap of "pivoted" data shows an actual pivot table with ungrouped dates.

Resources