Insert row and preserve formulas on Google Spreadsheet - google-apps-script

I'm making a spreadsheet that updates itself daily. For simplicity, let's say I generate a number every noon, and at night the spreadsheet is supposed to copy the number into a log column, and show the sum of all stored values for this column (there are actually several columns, and their number might grow in the future). With my current implementation, the sum formula is updated automatically, and thus keeps saving only the values previously available. I wish I could prevent this behavior.
Example:
The spreadsheet reads:
Total 1
Today 2
History
1/29/2014 1
Tomorrow, before I update it, it should be:
Total 3
Today
History
1/30/2014 2
1/29/2014 1
The formula I inserted on "Total" line is:
=sum(B4:B)
Basically, the code I've made for the script contains:
//Inserts a new line to compose history log:
sheet.insertRowsAfter(firstHystoryLine-1, 1);
And after the script is run, the formula is updated to
=sum(B5:B)
Therefore my problem.

Alternatively, you can add in your code
sheet.getRange("B1").setFormula("=sum(b4:b)")
This will reset your formula correctly.

Try Sum(b3:b). Inserting a row should then not affect the formula.

set your field to be =Sum(B$4). Using the dollar sign should prevent it from sliding. If you were adding in columns as well you'd want to do =Sum($B$4).

Related

Array Formula that also runs calculation on each cell's column header

I work at a school and at the end of each semester we need to total up instructional hours for each student in each class, then get the sum for the whole class. We keep our attendance on a Google Sheet each semester, so I can use fancy functions to do this. This function has worked perfectly the last couple years:
=arrayformula(sum(countifs([data range],{"","T","*all *","*no *"})))
I run this at the beginning of a row and it counts all instances where a student (or the entire class) would be counted as present, but doesn't count anything else; just like I need it (students are counted as present if the cell is left blank). I run this function on each row (for each individual student) and then run a quick sum at the bottom of the sheet and it's all good to go.
Well, this worked because our classes were all 1-hour long every day. Starting this semester, they are either 1 hour and 20 minutes or 32 minutes depending on the day of the week (each class has one occurrence that is an hour twenty and one that is thirty-two minutes each week). So the above function no longer works as it just totals how many classes a student showed up for. I now need something that will do that, but also multiply the result of each cell (1 or 0) by either 1.33 or .53 depending on the day of the week. This can be done by referencing each column's header, which has the date attached and running a WEEKDAY parameter nested in an IF parameter like so (using a class that has the longer instance on a Friday for example):
(if((weekday(Z$1))=6, 1.33, 0.53))
I put that together into a function that works:
=countifs(Z2,{"","T","*all *","*no "})(if((weekday(Z$1))=6, 1.33, 0.53))
... but I will have to create a dummy column next to the column that has each date's attendance data, tailor the formula to the column next to it and copy and paste the formula all the way down the column. I should only need to change the formula once per sheet, but I'll still need to create dummy columns next to each date and then run this formula by hand on each column. After all that, then I can sum up each row. It works... but I want something less time-intensive and prone to error.
What I am hoping for is a function that does what I have now (for single cells), but runs each portion of this function on each individual cell across an entire row of data after I add it to the beginning of the row and then, preferably, sums up the total hours at the end (should just be able to add a SUM parameter to the beginning of the function?); all in a one-cell function. I have tried using an array like I had before (in the first formula above), but the problem there (there's probably more than one problem), is that I can't get the function to reference each cell's header and run the IF function, I can only get the array to work on the COUNTIF portion of the function. Maybe this whole thing needs to be a script instead?
I hope what I am asking for makes sense and here is a link to a sample of the data I am using:
https://docs.google.com/spreadsheets/d/12fTE_AMlKtlqc_KToYB5TkvpYwFzON9Q6vvRfnDlr0A/edit?usp=sharing
Thank you for reading and I hope there is a reasonable solution to what I'm asking!
try:
=INDEX(BYROW(B2:N15, LAMBDA(x, SUM(
REGEXMATCH(x, "^$|no .+|all .+|T")*
IF(WEEKDAY(B1:N1)=6, 1.33, 0.53)))))

How to get the current number of cells in a sheet using Google AppsScript?

Is there a tool to get the current number of cells in a sheet using Google AppsScript? By "number of cells", I am referring to the 5-million number-of-cell limits per sheet in Google Sheet. To start off, what is "number of cells"?
For example, if isblank() on A1 and B3 of the first tab of a sheet (ie. file) gives TRUE respectively, and FALSE on any other cell (and other tabs), would range.getValues().length on Sheet1!A1:B3 produce the current "number of cells" for the sheet?
I am hoping to avoid the error
Exception: This action would increase the number of cells in the workbook above the limit of 5000000 cells.
by creating a new sheet (ie. file) every time "number of cells" approach 5000000.
The second part is how to get "number of cells" efficiently. Especially if there is no direct tool, how does one query "number of cells" efficiently, so that the query can be a (small) part of a script that runs ~100 times a day and still falls within the execution time limit of a (free) personal account? (I am hoping to run my script without impeding other scripts under an organization's domain.)
Prompted by comments, the following experiments provide an answer.
In a sheet where the following actions via the GUI prompts the error in the OP,
Adding any number of new columns or rows, including on a tab that has not changed its original .getMaxRows() and .getMaxColumns(), ie. 1000 rows x 26 columns. (Will refer to this as "reference tab".)
Adding new tabs
adding content to any cells currently displayed in the GUI does not prompt the error.
The sum of .getMaxRows()x.getMaxColumns() for all the tabs in this sheet yields 4804640.
Further, deleting a column in reference tab permits the addition of 40 rows via the GUI after which adding a 41st row would prompt the same error. Of course, 1 column with 1000 rows has the same number of cells as 40 rows with 25 columns.
Thus, it seems "number of cells" refers to .getMaxRows()x.getMaxColumns() and the max "number of cells" is 4804640. (+/- 25 cells, technically.)
In order to query current "number of cells", one can first use getSheet() and then tally .getMaxRows()x.getMaxColumns(). This is fast because getSheet(), getMaxRows(), getMaxColumns() are built-in and fast.

Is there a way to use one worksheet as database to create a code based on the date?

I am currently working on a spreadsheet formula where 2 different codes would be generated. Here is the algorithm for the "code" to start with., but I don't know how to construct a proper excel function for it.
There are 10 digits to the code where the first 8 digits are just the date i.e. 20210328_ _
The final 2 digits are dependent on the previous records whether there are records with the same date. If so it would assign a two-digit number starting from 1 to differentiate the different records.
I have tried to use the below formula to achieve what I want but the part where it references the other spreadsheet is bothering me as I need it to be a flexible value where the value is referring to the last row of the spreadsheet. Is there a way to work around this without scripts? I am planning to deploy it on Google Sheets so App scripts solutions would also be workable but not preferable.
=IF(DAY(B2)=RIGHT(Data!A114,2),Data!A114+1,CONCATENATE(YEAR(TODAY()),TEXT(B2,"MM"),DAY(TODAY()),"01"))
FYI B2 is the date of input and Data!A114 is the part where I concern.
Here's what I came up with.
Formula(D3)=IF((TO_PURE_NUMBER(Concatenate(YEAR(A3), TEXT(A3,"MM"),DAY(A3))) - TO_PURE_NUMBER(Concatenate(YEAR(A2),TEXT(A2,"MM"),DAY(A2)))), (TO_PURE_NUMBER(CONCATENATE(TO_PURE_NUMBER(Concatenate(YEAR(A3), TEXT(A3,"MM"),DAY(A3))), "00"))) ,(D2+1))
The data for the dates starts in A3, and continues down.
Link to the Google Sheet I tried it on.
https://docs.google.com/spreadsheets/d/1bwukKFaEow4PysqcJLA9jqjKBLZcY8T1vTN5VpZo8F8/edit?usp=sharing
Let me know if this worked.

Count the values from a variable column

I have a problem writing down a formula or a script in Google Sheet or Google App Script to find and count the values in a sheet where the number and references to the columns change.
I have a script that copy&paste the Sheet files for the staff shifts of every week from a Drive folder and merge them side by side (in horizontal).
In this sheet that contains all the shifts merged I want to count all the cells of the staff filtered only for handler and picker (column B, K, etc.) according to a specific date (row 3) for every hour.
Example: if today is 28/10/2020 find the right column with the same date in row 3 --> column E, count all the values from row 4 filtered by picker or handler for every hour (10 people at 05 AM).
Do you think that I can implement this with a formula (like a matrix, vlookup, etc.) or should it be written as a Script?
Thank you very much,
Marco
Please use the following
=COUNTA(QUERY({A3:I;J3:R},"select Col"&MATCH(A1,A3:I3)&"
where Col2 matches 'Technician|Picker' "))
Where B1 holds the date you wish to search for (28/10/2010)
Try the below formula. Replace date with your search date.
=COUNTA(INDEX(A4:R14,,MATCH(DATE(2020,10,28),A3:R3)))
This was earlier tagged as excel. This is how to "tackle" this in excel (office 365):
In a clear column use the following formula to get the unique hour-values that are in the column that equal today:
=UNIQUE(FILTER(INDEX(($4:$1048576,,MATCH(TODAY(),$3:$3,0)),INDEX(($4:$1048576,,MATCH(TODAY(),$3:$3,0))<>""))
In the column next to that type the following to get the result of the count of those unique values for that day:
=COUNTIF(INDEX(($4:$1048576,,MATCH(TODAY(),$3:$3,0)), FILTER (I:I,I:I<>""))
Where I:I in FILTER (I:I,I:I<>"") needs to be changed into the column you put the first formula.

How to automatically set the time-series value for the current date in Google Docs Script?

I have the following rows and columns. The value is coming from a simple API call. Is it possible to store that value for the current day and keep the previously stored value automatically? Right now, I simply copy paste the value for the day, but if I forget to update it, I might miss some data.
26/06/2019 0.01887913
27/06/2019
28/06/2019
29/06/2019
For example, for 27/06/2019, each time I open the doc, it would update the value if it is 27th, but then if I load the doc the next day, it will not be touching the 27th any more and will be updating the 28th.