Counting rows in a Google sheets script - google-apps-script

I am building a menu system with date and food columns. The screen will have a [working date] cell that controls which rows show on the screen.
When the [working date] changes the script should run and :
count the number of rows on the sheet with a date that matches the [working date]
count the number of row with matching date and blank food cells
add enough rows plugged with the date to fill the sheets screen
add additional rows if needed to allow additional entry by scrolling the screen
sort all the rows
scroll the sheets screen so that the first row for the selected date is at the top
This should all happen automatically when the user changes the [selected date.]
I am completely green on working in scripts and initially thought I could use the dcount function to get the counts. I now believe that the sheet side functions can only be used from there. I expect that in a script one will need to select a range of data and loop through it to get the counts.
I am pretty sure I could eventually figure this out but would really benefit if someone could give me a few pointers.
Thanks in advance - Joe

For the whole process you would need to use an onEdit trigger to execute a function each time the sheets is edited and use it's event information to conditionally run the code when the [working date] cell is the one edited. I would use the installable version of the trigger which has less restrictions.
For all the actions you want to achieve you'd have to use the SpreadsheetApp methods.
1 and 2) Create a TextFinder object from a Spreadsheet object and set it up to make the search. When you set up the range for the text finder, avoid using this version of the getRange method or it may throw an error.
3 and 4) With insertRows method you can insert rows to the Sheet object, and then use its getRange and setRange methods to set the values. There's no trigger available you could use to run a function when the user scrolls the view.
5) You can use the sort method. Or get the range values, sort them with JavaScript methods and then set the ordered array in the range.
6) You can use the activate method of a Range object which will put the focus in the range cell(s).

Related

Can I show the results of COUNTIF in one column only if there is data in another column?

I have a spreadsheet with multiple sheets.
Sheet A is generated from a template, and it is where users will enter in data to be formatted into a report; it will be deleted after that report is submitted.
As people enter info into Column A of Sheet A, they don't have to enter client information if we already have them entered in this spreadsheet, but otherwise they need to go over to Sheet B and enter it in.
To make it easier for them (so they don't have to check every time, or go back and enter info later after getting an error generating the report), I have used conditional formatting. The way it works is, column Z is set up as a helper column, and uses a "COUNTIF" function to check if the client ID in Sheet A, Column A is found in Sheet B, Column C. Sheet A Column Z returns 0 or 1 (or, theoretically, more than one if we had duplicates), and then Sheet A column A has conditional formatting based on Column Z's value-- if the client is already in, the cell for client ID turns green after they type it; if not, it turns red.
It works great! However, I am adding scripts to these sheets, and looping through them. This helper column is filled from Z1 to Z1000, which means I can't use sheet.maxRow() to get the last row.
I see plenty of workarounds on the script side, but I was wondering if anyone has a clever way to input a value into the helper column Z ONLY IF the corresponding cell (same row) in column A has a value using spreadsheet formulas.
I suspect that an array formula with a filter might do it, but I have little experience with either and can't get anything to work out.
Thanks for your help!
You can use this expression with INDEX, MAX and ROW to make an ARRAYFORMULA only expandable until the last cell with value in column:
A2:INDEX(A2:A,MAX(ROW(A2:A)*(A2:A<>"")))
It will go from A2 to the maximum number of row in A in which A is different than null (that's why both conditions are multiplied).
Then you can set a formula like this in Z2 (check the ranges in case something is not right from reading your text, and delete all other formulas in Z too in case you weren't using an arrayformula already):
=BYROW(A2:INDEX(A2:A,MAX(ROW(A2:A)*(A2:A<>""))),LAMBDA(each,IF(each="","",COUNTIF('Sheet B'!C:C,each))))

Apps Script - count rows in variable range

With Apps Script, I need to copy a section of a sheet to another area, with the start and end cells of the range based on variable inputs. Is there any built in function to count the number of rows in this variable-sized range?
I've searched all over and can't find any way to get this seemingly simple info for a defined range.
.getValues() on a Range object returns a regular javascript array of arrays, which you can measure with .length.

Script to randomly pick from a list if cells match specific value

Looking for a basic script that will trigger if cell A1 AND B1 contain a specific text, it will return a value (name) from a random pool of entries and display it in cell C1. My goal is to create a chart, pick to values in A and B and depending if specific values match, pick a random entry from a list and display it in C.
I was trying RANDBETWEEN + CHOOSE which technically works, but every other action in the spreadsheet will automatically generate a new random and re-trigger all the randoms, altering the whole list (since it's volatile) which I don’t want to happen, I’m open to suggestions from any other formulas that might work.
Thanks a lot.
There is a way to restrict re-evaluation of random functions only when specific cells are edited. Namely:
Create another spreadsheet, call it S2 to distinguish from the original spreadsheet A1
In S2, enter importrange referring to a cell or range of spreadsheet S1
Also in S2, enter any random number formulas you need: rand, randbetween, etc.
Back in S1, enter importrange that imports the output of those random formulas.
Result: the random values will get re-calculated only when the range of S1 in item 2 changes. Entering data elsewhere in S2 will not trigger recalc.
A script is a possible solution, but takes more work: you'd need to use the onEdit trigger to run a function on every edit; the function would need to check if the edit
Custom functions are only recalculated when their arguments change. You could use this feature to prevent that the result changes.
To force a recalculation you could
Delete and reenter the formula
Use a control argument that you changes every time that you want that the formula result be recalculated.

Force google sheet formula to recalculate

I have an index/match formula that matches a specific file based on the date value of certain cells. Here's the formula:
=IFERROR(INDEX(INDIRECT("'"&TEXT($O$3,"mm-dd-yyyy")&"'!"&"$D3:$D$500"),MATCH($D5,INDIRECT("'" & TEXT($O$3, "mm-dd-yyyy") &"'!$B$3:$B500"),0)),0)
I noticed the values did not change even when I imported a new CSV. Only way I got the values to update was to essentially re-enter the formula by dragging from top to the last cell like one would manually do.
I tried changing the recalculation time under settings, but it seemed like the setting does not apply to my formula, as I set it to every minute and nothing happened.
I thought about writing a script to have it re-enter the formulas and set it to run every day, but I'm hoping that there's a easier way to do this.
Short answer
Your formula is not being recalculated because its arguments do not change. The solution is, as you already figured out by yourself, to re-enter the proper arguments into cells that your formula references to.
Explanation
Google Sheets formulas are recalculated when
The spreadsheet is open
The function arguments changes
The functions NOW, TODAY, RAND, and RANDBETWEEN are updated are according to the spreadsheet settings, on change, on change and every minute, on change and every hour
External data functions recalculate at the following intervals:
ImportRange: 30 minutes
ImportHtml, ImportFeed, ImportData, ImportXml: 1 hour
GoogleFinance: may be delayed up to 20 minutes
Note: Some functions and custom functions doesn't allow not deterministic functions as arguments.
References
Change a spreadsheet's locale, time zone, recalculation, and language
I found an easy solution to my problem. I wrote a script to essentially re-enter the proper dates into cells that my formula references to and the formulas updated.
Here's another solution, albeit one that is computationally expensive: pass the range to be considered in the calculation to the function. That way, any time that a value changes in the passed range or that the range itself changes (such as inserting a row within the range), the formula is recalculated.
Example: Try this simple function.
function testPassRange( calcRange )
{
return calcRange.length ;
}

Google Apps Script Triggers For Spreadsheets

I've created a spreadsheet for one of my classes to keep track of marks. There is a leaderboard in the class and if a student is on top of the leaderboard for 7 days or more they receive a bonus for being so spectacular.
I have 4 columns for this. The first is the MARK column. The second is their SCORE. The third is the DATE they received the hi-score. The fourth is the AMOUNT_OF_DAYS that have elapsed since they obtained a hi-score. I have a script that runs if I enter in their results. It checks to see if it is a hi-score and date stamps todays date in the DATE column. The AMOUNT_OF_DAYS column is a simple formula that calculates the amount of days that have elapsed from when the hi-score was obtained. I would like to have the MARK column populated automatically once the AMOUNT_OF_DAYS value is 7 or greater. I tried the "change" trigger event, but I don't think that is the purpose of it. I don't think onEdit would work because that's only triggered when I manipulate the spreadsheet manually I think. Any ideas? Thanks in advance.
Does your spreadsheet look like this?
You can put a conditional formula in a cell:
=if(D2>=7,"bonus Time!",0)
The above formula enters the text bonus Time! if the cell in D2 is greater than or equal to 7, otherwise it enters the value zero.
You already have a script that runs when you enter the data, and then checks if it's a high score. I don't understand why you can't extend that script to also check the AMOUNT_OF_DAYS?
Here's what I did to solve this:
I created a function in a script that would be responsible for checking to see if any values in the THE_AMOUNT_OF_DAYS column are greater or equal to 7. Under the "Resources" menu in the script editor go to "all your triggers" and then add a trigger. Specify which function you'd like to run. Make sure that it is a "time-driven" event instead of a "From spreadsheet" event. Set the time to the interval you'd like the script's function to fire at.
One thing to note is that Browser.msgbox() functions don't seem to work when the function fires via the trigger, but it will work when you run the function from the script editor manually. The only reason I mention this is because I'm sure that many of us use this to debug our scripts.
Special thanks to #teatimer for pointing me in the right direction :)