Google Sheets Function: datatype error when the function already deals with the datatype - arrays

Context: In scheduling our podcast, we release four episodes per month. If there are 5 recording days in a month (Saturday), we record, but don't release that week, so we can build up a buffer.
The purpose of this function is to count the number of Saturdays alongside of the RecordingDates column (named range), setting the value to 1 if:
The current row is the first data row below the column title
OR
The month changes
within the year
OR
year rolls over
I have three custom functions for simplification:
ISFIRSTROW - Checks whether the value above is TEXT. Returns TRUE if so.
=ISTEXT(Index(range,ROW()-1))
LASTROWUP - Returns the value of the previous row in the range of concern
=Index(range,ROW()-1)
NEXTROWDOWN - Returns the value of the next row down in the range of concern
=Index(range,ROW()+1)
Altogether, this is the formula:
=IF(OR(ISFIRSTROW(RecordingDates),OR(MONTH(NEXTROWDOWN(RecordingDates))>MONTH(RecordingDates),AND(MONTH(LASTROWUP(RecordingDates))=12,MONTH(RecordingDates)=1))),1,LASTROWUP(WeekCount)+1)
Every one of those works separately.
They also all work together if I start the fill from below row 2.
Where I'm stuck is that if I start this at row 2, I get this error:
Error
Function MONTH parameter 1 expects number values.
But 'Recording Date (ten)' is a text and cannot be coerced to a number.
The ISFIRSTROW function returns TRUE when run on its own in row 2. So, to my understanding, the OR function in the IF should resolve to TRUE, and the IF should set the cell value to 1 and be done with it. I've tried a bunch of configurations of the formula, and am at wits end. I feel like I'm in a 70's product commercial screaming "There's got to be a better way!"
I know that the MONTH function needs a numerical input. What I don't understand is why that part of the formula is evaluating at all. Or, why I always have to think about what to do with the title if I want a function to start at the top.
A snapshot of the spreadsheet

if you are in row 2 then ROW()-1 will bring data from row 1 and you have a header (text string) in row 1 so that's equal to error as it should because dates starts from row 2
try:
=IFERROR(IF(OR(ISFIRSTROW(RecordingDates),
OR(MONTH(NEXTROWDOWN(RecordingDates))>MONTH(RecordingDates),
AND(MONTH(LASTROWUP(RecordingDates))=12,MONTH(RecordingDates)=1))),1,LASTROWUP(WeekCount)+1))

Related

Long calculation times with XLOOKUP vs INDEX-MIN-COLUMN

I'm using this formula =IF(B24="","",IFERROR(INDEX(Sheet3!$C$3:$EE$3,,MIN(IF(Sheet3!$C$4:$EE$23=(Sheet2!C24&$K$18),COLUMN(Sheet3!$C:$EE)))-2),"NF")) to return a cell value in the top row of an array - a date in this case.
The search criteria is a combination of a unique project number and a 2 digit status alphanumerical code for the project. The array consists of 23 rows where combinations of the unique numbers are found, each with different status codes.
So essentially, I'm building a FILTERED project status dashboard that returns dates linked to the relevant project status.
The code above is inspired from ( LINK ) that uses a very similar layout, but it uses town suburbs linked to postal codes instead of project numbers and status codes. The formula works well (though, not entered as an array formula), but I don't have a single formula in the sheet, I have 3 300 occurrences of this formula.
The problem comes in when the user changes the FILTER - Excel recalculates the entire dashboard and that takes anywhere from 2 to 5 minutes to run. You hit the escape button and cancel the calculation after setting the filter, but Excel just starts calculating again after a few seconds. After that, Excel's response is sluggish and almost unusable. Yes - our hardware is pretty weak ...
I tried XLOOKUP as well, but can't set the "lookup_array" to an array ( Sheet3!$C$4:$EE$23 ) because it doesn't match the "return-array" ( Sheet3!$C$3:$EE$3 ) Concatenating the lookup arrays with & works, but then you'd have to do that for all 23 rows, and again, multiply that by 3 300.
I thought of creating a UDF, but the function will still be called every time Excel recalculates after filtering... 3 300 calls ...
Any ideas on how to make the INDEX version run faster, or make the XLOOKUP accept the lookup_array as Sheet3!$C$4:$EE$23 in the hopes that it'll run faster?
Thank you!
Not really an elegant solution, but it works.
I imported the dataset into a helper sheet, where I combined the cell value with the corresponding value in Column A for each row ( a name in this case ) and the date from row 1 for each column, using underscore as a delimiter.
This new data range was then given a unique name, EE in this case.
On a second helper sheet, using this formula =INDEX(Filtered,1+INT((ROW('Sheet1'!C3)-1)/COLUMNS(Filtered)),MOD(ROW('Sheet1'!C3)-1+COLUMNS(Filtered),COLUMNS(Filtered))+1) and drag it down till it returns an REF! error and going back one row before the error.
This transposes all the data into a single column G. Using =UNIQUE(SORT(FILTER(B3:B3240,B3:B3240<> "",""))) then gives me a filtered list of unique values in column H that I then run
=IF(H3="","",LEFT(H3, SEARCH("_",H3,1)-1)) for the first data value in I, and
=IF(H3="","",MID(H3, SEARCH("_",H3) + 1, SEARCH("_",H3,SEARCH("_",H3)+1) - SEARCH("_",H3) - 1)) for the middle data value in J, and
=IF(H3="","",IFERROR(TEXT(RIGHT(H3,5),"yyyy-mm-dd"),"NF")) for the last data value in K.
Then just run XLOOPUP across columns I, J and K.
Runs quick and easy and solves a few of the other issue I had as well.
The second data set has just over 35 000 rows - still works well and fast.

Issue with a multiple criteria INDEX MATCH formula

so I used this array formula with INDEX MATCH:
{=INDEX(ENTRIES!$F$4:$F$28;MATCH(C4&F4&G4;ENTRIES!$C$4:$C$28&ENTRIES!$G$4:$G$28&ENTRIES!$H$4:$H$28;0))}
Here is the thing, I was trying to display the price of the "entries" sheet on the "sales" sheet, the problem comes up when there are different prices for one "Code" or product over time. I tried to solve it with an Index Match formula (above) that matches the price of the code (product) with the month and the year but it doesn't assign the price or any value on the months between the updates of the price. see picture
example: for month 6 it should assign the price of month 5 because there is not any update or change. and the same for month 9 it should be the same e of the month 8 for that product. How can I do that?
Looks to me like it's throwing those errors because it won't be able to find these months. In all cases these months are missing, at least with your data, you could tell the formula to pick the maximum row from the data that is below or equal to your search month using MAX()
Furthermore, matching multiple criteria through concatenating cells and columns can get tricky once numeric values/dates are involves and could throw back wrong/unexpected results. Try something along these lines instead:
MATCH(1,((Criteria1)*(Criteria2)*(Criteria3))...
So the whole thing would look like:
=INDEX(ENTRIES!$F$1:$F$28;MAX(((ENTRIES!$C$4:$C$28=C4)*(ENTRIES!$G$4:$G$28<=G4)*(ENTRIES!$H$4:$H$28=H4)*ROW(ENTRIES!$F$4:$F$28))))
Entered through CtrlShiftEnter
#JVDV answer was helpful, but it didn't work for me because it gives me a higher value instead of the latest price for the last month known not the next one.
Anyway looking at your formula, I finally came up with this:
{=IFERROR((INDEX(ENTRIES!$F$4:$F$28;MATCH(C8&J8&K8;ENTRIES!$C$4:$C$28&ENTRIES!$G$4:$G$28&ENTRIES!$H$4:$H$28;0)));INDEX(ENTRIES!$F$4:$F$28;MATCH(1;(ENTRIES!$C$4:$C$28=C8)*(ENTRIES!$G$4:$G$28=J8-1)*(ENTRIES!$H$4:$H$28=K8);0)))}
The first part is my original formula but now when it throws an error applies the second INDEX which finds the price of the month before the month with no price in the data. Of course, it's isn't perfect either because I have to "update" the price at least every two months.
I tried another way with a <= sign but it didn't work either.

Get column header of last non-empty cell in unknown row

I have a table in a sheet called "DATA" with the following headers:
Country, Code, Series, 2000, 2001, 2002, 2003, 2004, 2005, 2006.
In each row I have data for all columns always, except for years. Some rows have data for some years only, others all years.
In sheet "DATA AVAILABILITY" I want to build a formula which returns the most recent year for which there is available information in sheet "DATA", given a certain country and code. The relevant country and codes are in cells E2 and A3 of "DATA AVAILABILITY". Let's say, for argument's sake, that these are Country: Angola; Code: 3.
I have first built an array MATCH formula with two criteria:
={MATCH(1,('DATA AVAILABILITY'!E$2=Data!$B$1:$B$104701)*('DATA AVAILABILITY'!$A3=Data!$D$1:$D$104701),0)}
This has successfully given me the row in "DATA" in which there is information for Angola and code 3, which is row 1776.
Now I would like to get the header for the last non-empty cell of row 1776 in sheet "DATA". For this, I started by building a formula that would give me the column number of that cell:
=LOOKUP(2,1/(Data!1776:1776<>""),COLUMN(Data!1776:1776))
It successfully returned the number 53 which, after verifying on sheet "Data" is the correct number. I then added to the formula so that it would return the header, i.e., the year, instead of the column number:
=INDEX(Data!$A$1:$BE$104701,1,LOOKUP(2,1/(Data!1776:1776<>""),COLUMN(Data!1776:1776)))
Finally, I would like to combine both formulas (the MATCH and the INDEX formulas) so that the final result would be returned with one formula only. However, when I try to do it, something goes wrong and an error comes up - I am not even able to enter the formula. When I click ENTER, Excel returns an error that says there is a problem with the formula. what I have tried to do is to replace, in the LOOKUP within the INDEX, "Data!1776:1776" for the array MATCH formula that returns the row in which the information is - in my example, row 1776. The final formula which is not working is as follows:
=INDEX(Data!$A$1:$BE$104701,1,LOOKUP(2,1/(MATCH(1,('DATA AVAILABILITY'!E$2=Data!$B$1:$B$104701)*('DATA AVAILABILITY'!$A3=Data!$D$1:$D$104701)<>""),COLUMN(MATCH(1,('DATA AVAILABILITY'!E$2=Data!$B$1:$B$104701)*('DATA AVAILABILITY'!$A3=Data!$D$1:$D$104701))))
What may I be doing wrong?
Thank you
Hard to tell what is going on without at least some sample data (as a table or linked workbook -- NOT as a screenshot), and I would do it a bit differently.
You can simplify your formula to get the Header of the column that contains the last data in row 1776:
=LOOKUP(2,1/(Data!1776:1776<>""),Data!$1:$1)
To return the column number:
=LOOKUP(2,1/(Data!1776:1776<>""),COLUMN(Data!$1:$1))
To return the Appropriate Row Number (enter with CSE):
=MAX(($E$2=Data!$B$1:$B$104701)*(A3=Data!$D$1:$D$104701)*ROW($A$1:$A$104701))
To return the last filled in value, in the row that matches Country and Code, we make use of the fact that using 0 for the column number in the INDEX function returns all the columns in the designated row:
=LOOKUP(2,1/(INDEX(Data!$B$1:$BE$104701,MAX(($E$2=Data!$B$1:$B$104701)*(A3=Data!$D$1:$D$104701)*ROW($A$1:$A$104701)),0)<>""),INDEX(Data!$B$1:$BE$104701,MAX(($E$2=Data!$B$1:$BE$104701)*(A3=Data!$D$1:$D$104701)*ROW($A$1:$A$104701)),0))
entered with CSE.

How to calculate a cell reference in google sheets?

I'm trying to use a sheet array reference, for example Sheet1!C2:C10, in a filter function in Sheet2 to reference an array in Sheet1 that changes in length from day to day. So, the C10 reference above is actually variable from day to day.
So, the array is in Sheet1 in column C2 down to where ever, growing longer day by day until some point where data collection stops. The array is generated by a form which writes row by row with a time stamp in column A. The reference is used in Sheet2 in a filter function.
So, I'm thinking I should try something like
Sheet1!C2:indirect("C" & counta(Sheet1!A:A))
But, it doesn't work. And it produces ERROR: FILTER has mismatched range sizes. Expected row count: 9. column count: 1. Actual row count: 1, column count: 1.
Can anyone tell me what I'm doing wrong here?
I don't know what you are trying to filter, but try this:
=filter(arrayformula(Sheet1!C2:C),Sheet1!C2:C<>"")
Change the filter to your need.

Sum of one field minus sum of another SSRS Expression

I have a SSRS report I'm working on. What I would like to do is get the value of one field from its own dataset and subtract the value of another field from a different dataset. I can do this; however, the values are grouped so rather than giving me an individual value it gives me: (sum of all completed) - (sum of all completed the previous year).
Here is my expression I am using for the column "Compared to last year"
=SUM(Fields!Completed.Value, "MTDSales") - SUM(Fields!Completed.Value, "MTDminus1")
"MTDSales" and "MTDMinus1" are 2 seperate datasets. MTDSales Dataset is the current months sales outcomes grouped by company MTDMinus1 dataset is last years figure for this current month as i am comparing the 2 months separately.
I had to do this in a report where I was pulling current data from one database and older data from a data warehouse and combining. You will need to do a few things:
1. Establish a match field
This can be as simple as a single column. If you need to match on multiple fields you will need to add a calculated field to each dataset that you can match on. Assuming you need to match on company and financial year and each dataset returns one year of data, this might look something like match_id (assuming numeric values - otherwise you might need to use | or something as a separator):
`="A" & Fields!fin_year.Value & "B" & Fields!cust_id.Value`
2. Retrieve the data to the source field.
In your tablix add a column as you have to hold the looked up value:
=Lookup(Fields!matchId.Value, Fields!matchId.Value, Fields!Completed.Value, "MTDminus1")
3. Use the data
Now you can aggregate the data or do whatever further calculations you wish as if the field was part of your original dataset.

Resources