Pivot table, Excel Online, show all months in time period as columns even if values are empty? (recreating Query from Google Sheets) - excel

I have a Google Sheets spreadsheet with a query formula and I'm trying to recreate this in Excel. I thought Power Query would be the right place, but it doesn't seem to be available in 365 online.
I tried building a pivot table and got some what close, but it's missing months that have no data.
This is my Google Sheets formula
where F != 0
group by E
order by sum(F) desc
label sum(F) ''",0)
The formula spits out something like this:
(I included the headers in my screenshot, but they are not part of the query formula)
In my pivot table, this is the output
I have a helper table of all the months in the time period selected (they're dynamic based on the starting month the user selects), but I don't see a way of referencing that in my sheet.
Before I go buy a subscription to get the desktop version of Excel to work with Power Query, is there something I can do here to get the pivot table to do what I want?
Any help is appreciated.

Interesting approach... see if this is what you are looking for:
Assume you are given data set like this:
Formula:
=LAMBDA(RANGE,
LAMBDA(REVENUE,DATE,VALUE,
LAMBDA(UREVENUE,UDATE,VALUE,
LAMBDA(PIVOT,
HSTACK(
VSTACK("REVENUE",UREVENUE),
BYROW(PIVOT,LAMBDA(ROW,IF(NOT(ISNUMBER(INDEX(ROW,1))),"TOTAL",SUM(ROW)))),
PIVOT
)
)(
MAKEARRAY(COUNTA(UREVENUE)+1,COUNTA(UDATE),LAMBDA(ROW,COL,
IFS(
ROW=1,INDEX(UDATE,COL),
TRUE,SUM(FILTER(VALUE,(REVENUE=INDEX(UREVENUE,ROW-1))*(DATE=INDEX(UDATE,COL)),0))
)
))
)
)(UNIQUE(REVENUE),UNIQUE(DATE),IF(VALUE="",0,VALUE))
)(INDEX(RANGE,,1),INDEX(RANGE,,2),INDEX(RANGE,,3))
)($A$2:$C$19)
This formula mainly uses MAKEARRAY() with INDEX() to recreate the output of google QUERY().
name $A$2:$C$19 as RANGE with LAMBDA(),
name Col1,Col2,Col3 of RANGE as REVENUE,DATE,VALUE with LAMBDA(),
get unique values of REVENUE and DATE with UNIQUE(),
fill in 0 for empty values in VALUE with IF(),
name the unique values as UREVENUE and UDATE, and update the values of VALUE with LAMBDA(),
get pivot sum of REVENUE and DATE with MAKEARRAY(), which COUNTA(UREVENUE)+1 as number of ROW, and COUNTA(UDATE) as number of COL,
the reason why we need to +1 in ROW count, is because that we have to add a header row for the pivoted data,
inside MAKEARRAY(), fill in every CELL with IFS() according to some conditions,
when ROW index is 1, it should be the header row, so return the value of UDATE as header, INDEX() here determines which value of UDATE should be shown according to the COL index,
when ROW index is not 1, FILTER() the data of VALUE according to UREVENUE and UDATE, same as step 9, we use INDEX() to determines which value of the given data sets are we referencing, SUM() the result of FILTER() to form a single value for each CELL,
name the result of MAKEARRAY() as PIVOT with LAMBDA(),
get SUM() of each ROW in PIVOT with BYROW(),
stack the outputs with VSTACK() and HSTACK() to form the result.
Just noticed that you have mentioned about there is another table to select the data you would like to display according to months, so I updated the formula, and also separated the header part from MAKEARRAY() so the whole thing may hopefully looks logically easier to understand:
=LAMBDA(DATARANGE,SELECTED,HEADERS,
LAMBDA(REVENUE,DATE,VALUE,SELECTED,
LAMBDA(UREVENUE,VALUE,
LAMBDA(PIVOT,HEADERS,
LAMBDA(TOTAL,
VSTACK(HEADERS,HSTACK(UREVENUE,TOTAL,PIVOT))
)(BYROW(PIVOT,LAMBDA(ROW,SUM(ROW))))
)(
MAKEARRAY(COUNTA(UREVENUE),COUNTA(SELECTED),LAMBDA(ROW,COL,
SUM(FILTER(VALUE,(REVENUE=INDEX(UREVENUE,ROW))*(DATE=INDEX(SELECTED,COL)),0))
)),
HSTACK(HEADERS,TRANSPOSE(SELECTED))
)
)(UNIQUE(REVENUE),IF(VALUE="",0,VALUE))
)(INDEX(DATARANGE,,1),INDEX(DATARANGE,,2),INDEX(DATARANGE,,3),TRIM(TEXTSPLIT(SELECTED,,",")))
)($A$2:$C$19,$F$1,HSTACK("REVENUE","TOTAL"))
name $A$2:$C$19 as DATARANGE, $F$1 as SELECTED, HSTACK("REVENUE","TOTAL") as HEADERS with LAMBDA(), which the two texts inside HEADERS would be the titles of output column 1 and 2,
name Col1,Col2,Col3 of DATARANGE as REVENUE,DATE,VALUE, and TEXTSPLIT() SELECTED into an ARRAY, apply TRIM() on the ARRAY to get rid of extra spacing if there is any, and update it as values of SELECTED with LAMBDA(),
get unique values of REVENUE with UNIQUE(), and fill in 0 for empty values in VALUE with IF(),
name the unique values as UREVENUE, and update the values of VALUE with LAMBDA(),
update values of HEADERS, HSTACK() it with TRANSPOSE(SELECTED) to form the complete HEADERS,
get pivot sum of REVENUE and DATE with MAKEARRAY(), which COUNTA(UREVENUE) as number of ROW, and COUNTA(SELECTED) as number of COL,
inside MAKEARRAY(), fill in every CELL with FILTER(), filter the data of VALUE according to UREVENUE and SELECTED, uses INDEX() to determines which value of the given data are we referencing as criteria, SUM() the result of FILTER() to form a single value for each CELL, name the result of MAKEARRAY() as PIVOT with LAMBDA(),
get SUM() of each ROW in PIVOT with BYROW(), name the result of BYROW() as TOTAL with LAMBDA(),
stack the outputs with VSTACK() and HSTACK() to form the final result.
Some SORT() is added to help rearrange the output data if needed, controlled by the value of SORTREVENUE,SORTTOTAL,SORTPIVOT.
In the 1st LAMBDA(), pass ASC or DESC to activate related SORT(), or leave it blank to turn that SORT() off.
Be noticed, sort result of SORTTOTAL will overwrite sort result of SORTREVENUE.
=LAMBDA(DATARANGE,SELECTED,HEADERS,SORTREVENUE,SORTTOTAL,SORTPIVOT,
LAMBDA(REVENUE,DATE,VALUE,SELECTED,MONTHS,
LAMBDA(UREVENUE,SELECTED,
LAMBDA(PIVOT,HEADERS,
LAMBDA(TOTAL,
VSTACK(
HEADERS,
LAMBDA(OUTPUT,ASC,DESC,
IF(OR(ASC,DESC),SORT(OUTPUT,2,IF(DESC,-1,ASC)),OUTPUT)
)(HSTACK(UREVENUE,TOTAL,PIVOT),SORTTOTAL="ASC",SORTTOTAL="DESC")
)
)(BYROW(PIVOT,LAMBDA(ROW,SUM(ROW))))
)(
MAKEARRAY(COUNTA(UREVENUE),COUNTA(SELECTED),LAMBDA(ROW,COL,
SUM(FILTER(VALUE,(REVENUE=INDEX(UREVENUE,ROW))*(DATE=INDEX(SELECTED,COL)),0))
)),
HSTACK(HEADERS,TRANSPOSE(SELECTED))
)
)(
LAMBDA(REVENUE,ASC,DESC,
IF(OR(ASC,DESC),SORT(REVENUE,,IF(DESC,-1,ASC)),REVENUE)
)(UNIQUE(REVENUE),SORTREVENUE="ASC",SORTREVENUE="DESC"),
LAMBDA(TEXT,NUM,ASC,DESC,
IF(OR(ASC,DESC),
XLOOKUP(SORT(XLOOKUP(SELECTED,TEXT,NUM),,IF(DESC,-1,ASC)),NUM,TEXT),
SELECTED
)
)(INDEX(MONTHS,,1),INDEX(MONTHS,,2),SORTPIVOT="ASC",SORTPIVOT="DESC")
)
)(
INDEX(DATARANGE,,1),
INDEX(DATARANGE,,2),
INDEX(DATARANGE,,3),
TRIM(TEXTSPLIT(UPPER($F$1),,",")),
HSTACK({"JAN";"FEB";"MAR";"APR";"MAY";"JUN";"JUL";"AUG";"SEP";"OCT";"NOV";"DEC"},SEQUENCE(12))
)
)($A$2:$C$19,$F$1,HSTACK("REVENUE","TOTAL"),"DESC","DESC","DESC")

Related

To return the last value in a row for Date and Person to Action (VBA)

I wish to construct 2 current status columns so as find the last values in each row in Excel:
one for the last Date and the other for the last person who needs to act.
Please see the attached jpg To return the last values in a row for Date and Person to Act
I have tried to use the excel functions, namely, INDEX or LOOKUP but to no avail because of the 3 Remarks columns within the table.
I would appreciate it if you could advise me how to craft a VBA code to the above query.
From LC TAN 2020-02-13
You're on the right track.
you can use LOOKUP to return the last element in an array
BUT you have to ensure your array only has the elements that you want to consider
There is a variation of the INDEX function where you can enter an array for the column (or row) argument and return selected items. You enter the array, or arra constant, in a format like:
N(IF(1,*array or arrayConstant*))
So, a formula that would work for your requirements would be:
L6: =LOOKUP(2,1/LEN(INDEX($B6:$J6,N(IF(1,{2,5,8})))),INDEX($B6:$J6,N(IF(1,{2,5,8}))))
and fill down.
You can use MAX for the date to find the latest date in that row.
You can then use IFERROR and VLOOKUP to find the action with that date. i.e. lookup the date that MAX has returned in the first set of columns, and if that returns an error, look in the second. If the second returns an error, look in the third.
As per your sheet, the formula for L6 would be =MAX(B5:I5)
The formula for M6 would be =IFERROR(VLOOKUP(L5,B5:C5,2,FALSE),IFERROR(VLOOKUP(L5,E5:F5,2,FALSE),VLOOKUP(L5,H5:I5,2,FALSE)))
You can then drag the cells down to populate the date and action for every row. You could achieve the same with VBA if you wanted to, but I would have thought that this is the easiest way to get the the desired result.

Calculated Fields in excel pivot

I have column ('CSAT') in a sheet that has numbers 1 and 0 in each cell. '1' represents 'Satisfied' and '0' represents 'Disatisfied'. I want to make a pivot from this sheet and have a new calculated field in it ('CSAT %') that will give me the score by dividing (Total 'Satisfied') count by (Total 'Dissatisfied + Total 'Satisfied') * 100.
I tried with COUNTIF but i dont think we can use this formula in pivot
Calculated Fields and Items in PivotTables are tricky. The main tripping point is understanding that Calculated Fields and Items operate on the totals, not on the individual values in the underlying data.
For example, if you created a new Field that was equal to Field1 * Field2 and data is being summarized by SUM, Excel doesn't multiply all of the respective values in each field and then sum the results. It first sums the fields for each category and then multiplies those results. What it's really doing is SUM(Field1) * SUM(Field2) for each category.
You can use some worksheet functions in the calculated fields, but you have to remember you're still operating on the totals. So if you created a new Field that was equal to Count(Field1) * Count(Field2), you're (almost) always just going to get an answer of 1. This is because the calculation is actually doing Count(SUM(Field1)) * Count(SUM(Field2)) for each category. The sum of each field is a single number, so the calculation is just doing 1*1 for each category.
So for this reason, you can't use aggregating functions like SUMIF or COUNTIF which need to look at each individual elements. Since you need to look at individual elements, you actually can't use a Calculated Field for your solution at all.
What you can do is use a Calculated Item!
The main catch here is you can't use any field in more than 1 location when calculated items are involved. Excel just throws an error message saying you're not allowed.
So if you have a category column as well as the CSAT column, you need to create another dummy column full of 1's to operate on.
You can then set up pivot table as follows:
Category field to Rows.
Dummy field to Data area, summarized by Sum
CSAT field to Columns
Click on the CSAT column headers in the pivot table and choose: PivotTable Tools > Fields, Items, & Sets > Calculated Item
Set Name for your new Item to CSAT%
Enter the formula: ='1'/('0'+'1')
On the CSAT field, hide items 1 and 0, so only the CSAT% field is visible
Result:
A couple of notes:
When entering fields and items in calculated fields and items, do so by placing the cursor where you want in the Formula then double clicking on the field/item name from the lists below. This will add brackets and quotes as required in the correct format.
Note that the formula doesn't need SUM around the item names, because calculated fields/items always work on the total of values. They are totalled according to how the data is summarized in the pivot table.
The dummy column was added with all values of 1 so that summing these values gives you the count, from which the percentage can be calculated using the formula specified.
Answer without using calculated fields:
Assuming you have categories in the row fields, you can put CSAT as a column field as well as a data field then choose to summarize values by Count and show values as a percentage of row totals:
After putting CSAT in column and data fields, right click on the data and select Summarize Values By > More Options...
First choose to Summarize Values By Count:
Then click Show Values As tab and select % of Row Total:
You'll then have percentage of 1's under the CSAT=1 column:

How to do a range index and match or vlookup in power pivot excel?

These are the individual data points of the data model:
These are the monthly salaries of the employees (obtained using the pivot table from the data model's data):
Each cell will then be used as the Lookup value which will be run through a table.
The lookup value is to be looked up in column A and column B of the table below and if it is matched (within the range), it will return the corresponding value under column C.
I am unable to find any index and match or vlookup functions in the power pivot functionality of excel using measures--which are used to get some analytics on aggregated values on report objects such as pivot tables.
I have found LOOKUPVALUE( <result_columnName>, <search_columnName>, <search_value>[, <search_columnName>, <search_value>]…) which is a DAX function however, the issue here is that I am doing a range lookup and as shown below, I don't know if you can have an array as an argument to the function.
Traditional calculated fields also do not allow arrays in the formulas.
Lookupvalue() only works on a single column lookups because it will return an empty cell if it cannot find a match as shown below:
But when it does find a match using the table below:
It will work just fine:
First, you need to create a measure for Pay:
Total Pay = SUM(Table1[Pay])
It's important to do it as a measure instead of just dropping 'Pay' into a pivot table (this is called an 'implicit measure' and is concidered a bad practice).
Then, let's say your table with pay ranges is named "Pay Ranges". Create another measure:
Returned Value =
CALCULATE(
VALUES('Pay Ranges'[Value To Return]),
FILTER( 'Pay Ranges',
[Total Pay] >= 'Pay Ranges'[Lower Bound] &&
[Total Pay] < 'Pay Ranges'[Upper Bound]
))
Make sure that all these formulas are Measures, not calculated columns.
Also, the formula relies on the correct construction of the ranges. If they overlap, you will get an error.

How can I use structured references to identify column and use row values in the identified column as criteria?

I have an Excel 2013 table, called 'student_courses' with columns: stu_id, stu_major, stu_course, and a calculated column named validated_crs.
I am trying to create a formula for the calculated column named validated_crs that evaluates every record.
In this calculated column, I need to reference the value in the stu_major column to find a column in a second table, 'qualified_courses'. The headers in the 'qualified_courses' table correlate with the stu_major values.
I need to check to see if any of the values in the correlated column in 'qualified_courses' match the 'stu_course' value in the record being evaluated in the 'student_courses' table.
If any of the values in the correlated column match the stu_course value for any given record in the first table, then it should return a value of "validated" in the calculated column.
So far, I have found out how to return the second table column values using =INDIRECT("qualified_courses"&"["&[#[stu_major]]&"]"), but I'm not sure how to use the returned set of values to check against the stu_course value to see if there is a match.
Many thanks,
Lindsay
student_courses table:
stu_id stu_major stu_course validated_crs
5432 MULTE BIOL1102 validated
5432 MULTE MUSC1303 NULL
5432 MULTE ENGL2303 validated
6737 MULTM HIST1104 validated
6737 MULTM BIOL1222 NULL
6737 MULTM EDUC2303 validated
6737 MULTM EDUC1302 validated
qualified_courses table:
MULTA MULTB MULTE MULTM
ART1301 HIST1301 BIOL1102 HIST1104
BIOL1322 POLS2210 ENGL2303 EDUC2303
ENGL1440 IS3340 ART3303 EDUC1302
BIOL2302 BIOL1222 MUSC1303
This formula builds on yours:
=IF(ISNUMBER(MATCH([#[stu_course]],INDIRECT("qualified_courses"&"["&[#[stu_major]]&"]"),0)),"Validated","")
We use the MATCH function to search the returned column for the course. If there is one then it returns a number, otherwise an error.
The ISNUMBER returns TRUE/FALSE which the IF uses to determine which outcome.
But I do not like the INDIRECT() Formula as it is a VOLATILE formula. I prefer the INDEX Formula:
=IF(ISNUMBER(MATCH([#[stu_course]],INDEX(qualified_courses,0,MATCH([#[stu_major]],qualified_courses[#Headers],0)),0)),"Validated","")
Which will return the same.
Instead of the INDIRECT to find the correct column we use INDEX/MATCH. Once again the MATCH returns a number, this time of the column in the second table.
The INDEX() uses this nubmer to return the full column at that position. The 0 at the second criterion states that we want the full column.
Then it is just like the first.
VOLATILE formulas are those that recalculate every time Excel recalculates whether the data to which it is tied changed or not.
Non Volatile formulas only recalculate if the data to which they refer changes.
The validated_cs column in the picture is the top formula and the next column is the bottom:

Selecting the max with a condition in excel

I have a range in excel with dates and values
http://lh4.ggpht.com/_i-hI_3gfy08/SoSIopeZUZI/AAAAAAAABEk/KjFnq57VTUc/table.png
EDIT:image added
I want to select the MAX value from the HIGH column for each YEAR (2009 would return 404, 2008 would return 390)
I've done something similar but it's using SUMIF, not MAX.
Any excel people in here that can help me out?
The equivalent of SUMIF in Excel is something like this:
{=MAX(IF(CategoryColumn="High",ValueColumn,"")}
Where
CategoryColumn is the column containing your categories (e.g., "Low", "Med", "High")
ValueColumn is the column containing the data you want to get the max of
NOTE: This is an array formula so you must press Ctrl-Shift-Enter when entering this formula instead of just Enter. Also, don't actually type in the braces {}. The braces show up automatically to indicate that you've entered an array formula.
NOTE 2: You can actually name a range of data. For example, select the range A1:A20. Right-Click and select "Name a Range..." So, for this example, you can select your category column and name it CategoryColumn. Same with ValueColumn.
Array formulas allow you to do IF statements and other functions on a whole range of data instead of just a single value.
This example checks if the value in the "category column" is "High". If it is, it puts the neighboring "value" into the MAX function, otherwise it puts a blank. This gives you the maximum of all the "High" values.
P.S. I don't think the img tag works on this site...can't see your image.
There are three options available.
My preferred option is to create a pivot table without a helper column.
Option 1: Use a pivot table
Create a pivot table of your data.
Set the row to the date field and group it by year.
Alternately a 'Year' helper column could be used by adding a column with this formula.
=YEAR(A2)
Set the data items value portion of the pivot table to be the MAX of your 'High' field
Option 2: Use the DMAX function
Add a helper column titled year with the formula
=YEAR(A2)
Then add a formula for each year
=DMAX(A1:C21,"High",F13:F14)
Option 3: Use an array formula
Enter an array formula for each year using the Ctrl-Shift-Enter keys.
{=MAX(IF(YEAR(A2:A21)=2008,B2:B21))}

Resources