I have a column of dates with the format "yyyy-mm-dd". And I want to do summary statistics by month -- using native formulas.
When I put arrayformula around month(...)>month(...), I get the error
Result was not expanded automatically, please insert more rows (1).
Why is that? And how do I get around that?
Example sheet. Formula in B4.
=arrayformula(month(B4:B)>month(B3:B))
Note: I don't know the number of rows ahead of time -- it is expected to update from time to time.
Firstly, erase your formula, it is trying to automatically expand the sheet and the sheet already has over 50,000 rows.
Next delete 48,000 rows or so.
Next put this formula in cell B4:
=arrayformula(month(B4:B)>month(arrayconstrain(B3:B,rows(B4:B),1)))
That will prevent the formula from auto-expanding the sheet.
That should work, though I think you're going to realize you don't like what happens when the year changes. I believe this to be an xyProblem.
=arrayformula(if(isblank(B4:B),,month(B5:B)>month(B4:B)))
works.
It seems it is always better to include an isblank() wrap to avoid indefinite expansion of the sheet.
Related
I have a large Google Sheets spreadsheet that has individual sheets for financial statements of activity for multiple years. I want to reference particular columns of those in other sheets, and I've successfully figured out how to do that with an HLOOKUP function. However, because I want to do this for multiple years, I'd like that HLOOKUP function to pick up the name of the sheet to reference from its column header. Right now, I'm hard-coding it like this—you can see the HLOOKUP range refers to cells in the "2021 Overall" sheet. The hard-coded approach works but makes adding a new year tedious. Ideally, the HLOOKUP formula would read the contents of its column header cell to determine which year it is.
As best I can tell, the solution is to use INDIRECT, but I can't figure out any way to build the formulate with INDIRECT and not get an error. For instance, this seemed like it should work. As you can see, I have 2021 in cell D4, and my INDIRECT statement is referencing that and building the rest of the range.
I've also tried using INDIRECT with an explicit CONCATENATE, with no more success.
Any ideas for how to look up that D4 cell and slide it into the HLOOKUP range?
Thank you!
Try to remove the "'"& before D4 and the ' after the Overall.
Your formula should look like this:
=IFERROR(HLOOKUP($A$2,INDIRECT(F4 &" Overall!$A$5:$X$150", Utility!$A10, FALSE)))
With Nikko's nudges in the right direction, I eventually figured out the right format. This allows the formula to work in multiple sheets and to be filled right (for more years) and down (for more classes).
=IFERROR(HLOOKUP($A$2,INDIRECT("'"D$4&" Overall'!$A$5:$X$150"), Utility!$A3, FALSE))
Note that if you try to replicate this, you may need to type the formula out from scratch—I had a problem where pasting it in didn't work. Once I'd retyped it and Google Sheets acknowledged it, it worked from then on in the spreadsheet, even when pasted from sheet to sheet.
SOLVED EDIT
Thank you for the help. Solution here.
ORIGINAL POST
I have made a google sheet to describe the issue I am facing linked here (https://docs.google.com/spreadsheets/d/1yK6ZAX8BFnEqiuQO9HIxuY0l62ewDDccj-8EN1r2i2w/edit?usp=sharing).
I will also describe in words, below, the problem I am facing, along with the solutions I have tried.
The data of column A are random single-digit (0-9). I would like column B to show the most recent even number from column A, but only up to a specific row. That specific row is the row corresponding to the row of the cell in column B. In other words, in cell B7, I want to find the most recently entered even number of column A, specifically only on the range A2:A7 (A1 contains a column header).
This is actually a pretty simple formula, and I can get the desired outputs by simply checking if the value in a cell in column A is even and then returning the value of that cell if it is, or the output of the cell above if it isn't. So the formula would look something like: =IF(ISEVEN(A7),A7,B6)
However, my problem is that the length of the data in column A will be growing as more data are entered, and my current solution of using the fill handle to copy the formula to new cells is inelegant and time-consuming. So my desired solution is to use an array formula entered into the first cell of column B (B2), capable of returning the same value as the other formula. The formula I tried to enter to perform this was the following: =ARRAYFORMULA(IF(ISEVEN(A2:A),A2:A,INDIRECT(ADDRESS(ROW(A2:A)-1,2))))
However, as some of my previous work with arrays has taught me, not all formulas iterate as expected down the array. The formula seems to be able to return the correct output on lines which are already even, but it is unable to return the expected most-recently entered even number for all the other lines. It appears that the formula is not able to appropriately interpret the value_if_false argument of the IF formula.
I'm a little new to scripting, so I'm still trying to learn, but I also tried to dabble around with custom functions to no avail. I'm still wet behind the ears when it comes to coding, which is why I've been so lenient on the built-in formulas of Google Sheets, but I fear I may have reached the limit of what Sheets formulas can do.
I am open to trying new approaches, but my only real constraint is that I would really like for this to be a one-touch (or even better no-touch) solution, hope that's not too far beyond the scope of this issue. Any assistance would be much appreciated.
EDIT
After rubber-ducking the problem here, I went back and tried to use the OFFSET formula, hoping I could get it to play nicely with the array formula. Alas, I was unable, but I thought I should at least post my progress here for reference.
Attempt with offset
Still working at it!
Doing a vlookup on the row number seems to work for me
=ArrayFormula(if(A2:A="","",vlookup(row(A2:A),{if(iseven(A2:A),row(A2:A)),A2:A},2)))
Note: if there are no even numbers in range for some rows, it will produce #N/A for those rows.
I'm trying create a list of sequential dates from a set date to the most recent date in another column.
=ARRAYFORMULA(IF(OR(A2:A=MAX(C:C),A2:A=""),"",DATEVALUE(A2:A+1)))
I use MAX() to find the dates most recent date in column C. What I'm trying to get this formula to do is to recursively check the date in the cell above to determine if the max date has been reached. I've made sure A2 already has the set starting date.
The output is in only one cell though and I don't know why.
Thank you for the help.
What appears to be troubling your current array formula is that as defined it goes on forever and is self-referential. There may be a way to make it by setting preferences to be iterative and helping it interpret getting to repeated cells with "" as convergence.
Here is a way to sidestep those issues. You can bulletproof it more (for example, by encasing it in an IFERROR), but basically you can calculate exactly how many entries you need, and then set your range in the Array formula accordingly. In A3 you place the following:
=arrayformula(DATEVALUE(Row(indirect("A3:A"&(max(C:C)-A2+2)))+A2-2))
which will construct the exact range you want, then calculate each entry with an explicit rather than recursive formula.
EDIT: the above implementation assumes you need at least 2 dates. You can handle that case and other weird ones with the following, less readable formula, =if(max(C:C)>A2,iferror(arrayformula(DATEVALUE(Row(indirect("A3:A"&(max(C:C)-$A$2+2)))+$A$2-2))),"")
For a league I run we keep track of games played and w/l/t and calculate that into a ranking score. The player name is listed in column U and the ranking score in column AD of a fixed table. I then use an array formula to list the players in ranking order in column E (then vlookup to pull in other stats based on the value in E for that row). Specifically I use this formula in column E:
=ARRAY_CONSTRAIN(ARRAYFORMULA(INDEX($U$4:$U$153,MATCH(LARGE($AD$4:$AD$153-ROW($AD$4:$AD$153)/COUNT($AD$4:$AD$153),ROW(E72)-ROW(E$4)+1),$AD$4:$AD$153-ROW($AD$4:$AD$153)/COUNT($AD$4:$AD$153),0))), 1, 1)
I need to be able to add players to the table in U:AD without having to edit the formula every time, i.e. from $U4:$U153 and $AD$4:$AD$153 to $U4:$U154 and $AD$4:$AD$154 in all the various places in the formula then copy the new formula all the way down.
Is there a way that I could define the range as $U$4:$U(last populated row) and the same for column AD in the above formula?
I eventually be using this in both Excel and Google Sheets so I would really like to avoid scripting. First I'm looking to solve this for Google Sheets.
Here is a copy of the sheet I am working on.
You could use INDEX and COUNTA
Instead of $U4$U153,
$U4:INDEX(U4:U,COUNTA(A4:A))
The COUNTA portion will give the number of populated rows and feed it into INDEX to give $U4:$U153
The answer for the Google sheet that you shared.
skip to the end for the simple solution
I used the indirect method by entering a formula in E1 that counts the AD column for player stats and adds 3 to get the last row. (I was going create the full range AD4:AD?? but you also have U4:U73 in the formula)
=counta(AD4:AD)+3
I then changed your formula use indirect, indirect("$AD$4:AD"&E$1), to reference the last row number in cell E1 to create the required range.
=iferror(ARRAY_CONSTRAIN(ARRAYFORMULA(INDEX(indirect("$U$4:U"&E$1),MATCH(LARGE(indirect("$AD$4:AD"&E$1)-ROW(indirect("$AD$4:AD"&E$1))/COUNT(indirect("$AD$4:$AD"&E$1)),ROW(E4)-ROW(E$4)+1),indirect("$AD$4:$AD"&E$1)-ROW(indirect("$AD$4:$AD"&E$1))/COUNT(indirect("$AD$4:AD"&E$1)),0))), 1, 1),"")
I discovered by accident that if you remove the ARRAY_CONSTRAIN from your formula and change U4:U73 to U4:AC73 then the formula will populate the scores to the right of your formula where you currently have vlookups. I put an example of this in E4 but note that you will have to delete the vlookup formulas if you want to fill the formula down otherwise it will show REF
I also added iferror so that the formula can be copied to the same row as the end of the "open slots" in column A without showing errors.
Also, I got to this point and was thinking that since you're using Google Sheets, a better way to do this could be to use the QUERY function to pull the data and also sort it using ORDER BY with a single formula in cell E4.
I've not really used the QUERY function but maybe it's time to learn.
EDIT
Turns out it doesn't take much learning
=QUERY(U4:AD,"SELECT U,V,W,X,Y,Z,AA,AB,AC ORDER BY AD DESC")
Put the formula above in cell E4 and delete everything beneath and scores to the right and you're done. you'll notice that there is no indirect because Google understands that you don't want the blank rows.
https://docs.google.com/spreadsheets/d/16IclEmKwDFdInIAZhH2vt-tLJ5pbwX06jv9xrUXwhnY/edit?usp=sharing
Why are you using $ signs around U4:U153,remove $ signs for rows that will give you flexibility while keeping columns fixed.As your drag the formula,the data array will append the newly filled cells or you can create table using Ctrl+T that will automatically expand as you keeping adding data.
I'm having problems with something that is likey very simple to correct. I have a form that submits data to a Google Spreadsheet, simply a date, name and score. On a separate sheet I am going to have a leaderboard which shows all submissions ranked by highest score (for simplicity in the example in the link below, I just have the leaderboard showing up on the right of the same sheet). I have it sorting the data fine, but I'm struggling with getting the 'rank' value to display. As shown for the first 3 rows (G2, G3, G4) I know what the formula is to display the 'rank' value...but what I'm struggling with is how to get that value to show without having to have that formula in each cell. Since the data will be coming from a form, there will obviously be new rows added regularly which means the leaderboard will automatically get adjusted and I want all of the rows to display the rank #. From what I have read, ArrayFormula should allow this to work, but even with looking at examples I can't figure out how to get it to work with my formula.
I know I could just highlight the entire 'G' column and paste in the formula, and hope it adds it to enough rows...but then it displays 'N/A' for all of the rows which don't currenlty have any data.
Hoping its just a simple solution that I'm being dumb and missing...any help would be greatly appreciated. The link to an example is below. To summarize, for all rows that have content in column H and I, the G cell for that row should show the rank value automatically.
https://docs.google.com/spreadsheets/d/1pCIJQi5g2scOtB6o2PgVVb-0azzhupEOPjiL0RMM57A/edit?usp=sharing
Thank you!
=ARRAYFORMULA(RANK(INDIRECT("I2:I"&COUNTA(H:H)),$I$2:I,0))
This will automatically rank and sort, for all values, including additional ones that are added. You only need to enter it into G2, and it will dynamically fill in the rest for you.
You can use
IFERROR(RANK(...),"")
and drag it to all rows - this will leave blank cells instead of #N/As. I'm sure there are other ways but that seems like the easiest one to me.