Limit the number of row in Google Sheets - google-apps-script

I have a google sheets document that keeps adding rows to the sheet. It slows down my document tremendously because of scripts I run against the document. I only need around 100 rows, but it continues to add several hundred to a thousand plus. Is there a way to limit this with a hard number or set a script to automatically delete any row after 100.
This is a log of orders I am maintaining.
I had considered using a script to
getMaxRows() - getLastRow() + 25 //for future blank rows.
However, I could not get it to function properly. My scripting abilities are limited.
Something akin to.
var Max = getMaxRows()
var Last = getLastRows()
start = 2;
end = Max-Last+25
sheet.deleteRows(start, end);

Issue:
You're probably using a badly written auto-iterating array formula function, where the end result of the formula is more than the number of cells in the sheet. The function will automatically create space for the result by inserting rows.
Example:
A simple example of a self-iterating arrayformula is provided below. In a "1000 row" new sheet, If you type in this formula, New rows will be inserted upto a total of 50,000 rows, but it varies depending on the device/ browser you use.
A1:
=ARRAYFORMULA(ROW(A1:A1001))
Formula Explanation:
ROW(A1:A1001) creates a array of 1 to 1001 and returns them to the sheet
But there's no space in the sheet
One more row is needed
Sheets automatically adds 1 row after row 1000
But, If a row is inserted after A1000, The reference A1001 in ROW(A1:A1001) automatically becomes A1002, because a new row is added between A1:A1001.
Now, The formula says, =ARRAYFORMULA(ROW(A1:A1002)), so, 1002 numbers, So, we still need a extra row. A new row is added, reference changes again, a new row is needed again and so forth until a hard limit like 50,000 is reached and your formula stops iterating and becomes a #REF error.
Solution(s):
Create a copy of your sheet and delete each array formula one by one followed by deleting the rows each time to pin the rogue formula.
Pay attention to expanding array formulas like those using SPLIT.
Use sane arrayformula methods:
Avoid: IF(ROW(A1:A100)=1,"Header",...) Use: {"Header";...}
Avoid: Open ended ranges; Use Close ended ranges using INDEX/COUNTA

Related

Write in the row under the function IMPORTRANGE

I want to write in the row under the function IMPORTRANGE but when I do that the function stop working bc it cant increase. Can someone know how to solve that pls?
here is my google sheet :
exemple: When i want to write in the row 15 column A,B,C or D the function stop working and I have a REF ERROR but I want to be able to write
The IMPORTRANGE() function occupies a range based on the data that queries. If you add some content within the datarange that importrange returns, the latter will break because it can't expand.
You can either restrict the range that importrange occupies:
=IMPORTRANGE("SprdID";"All Months!$A$1:$D14")
or add content starting from column E. You can also put the importrange function in bottom rows and use the top rows for manually entered data.
Since the raw data could potentially increase in the future, I would advice you to have a dedicated sheet to accommodate the importrange function and all of the other calculations/formulas to be stored in a different sheet.
References:
https://support.google.com/docs/thread/26662291?hl=en

insertRowBefore the last Row returning error

I have a script that (gross, I know) writes to a spreadsheet. It dynamically adds and deletes rows based on input data from another sheet. I like doing this because the user has to copy and paste the resulting data, formatted into a table, into an email after (Let's skip creating an email directly from this script for now, that's part two).
I figured the easiest way to let the script know where to paste new data is to always insert a row before the very last row of the spreadsheet and paste said data.
I have been using getMaxRows(), getLastRow(), and insertRowBefore(), but all combos of these functions returns an "those rows are out of bounds" error!
I really don't understand what's going on. I use logs and see the variables getLastRow() and getMaxRows both get updated after I've done some copying of a template table to the sheet which then "inserts" rows. For some reason, even after re-calling the getMaxRows() and getLastRow() functions, they don't recognize the new rows. The script can still manipulate these new rows.
This leads me to believe getMaxRows() and getLastRow() can only get info about the number of rows in the sheet only when the script first runs, or only when the sheet is first activated? Has anyone faced this issue before? Does anyone have details about how those two functions work? The GAS 'sheet' class page didn't help.
spread = SpreadsheetApp.getActiveSpreadsheet();
emailsSheet = spread.getSheetByName("emails");
emailsMaxRows = emailsSheet.getMaxRows(); //# of rows regardless of content.
emailsSheet.deleteRows(2,emailsMaxRows-1); //I want to start from scratch each time I run the script, having just 1 row from which I append 'template' boxes where I can put data for the user to copy and paste into emails.
emailsMaxRows = emailsSheet.getMaxRows(); //now that I've deleted, Logger.log() shows that getMaxRows() correctly updates with just 1 row.
emailsSheet.insertRowsBefore(emailsMaxRows, 2);//insert two more, so there are 3 rows in the sheet.
emailsMaxRows = emailsSheet.getMaxRows(); //logger correctly shows 3
templateEmail = spread.getRangeByName("templateEmail"); //email template, A1:E5
templateEmail.copyTo(emailsSheet.getRange(emailsMaxRows,1)); //paste a table of 5 rows to row 3, so there are 7 total.
emailsMaxRows = emailsSheet.getMaxRows(); //should be 7, no?
//NO. Logger shows MaxRow is still 3, how come????? I can visibly see in the sheet there are 7 rows, with formatting and text. I simply don't understand how getMaxRows() doesn't update to return 7.
I need either getMaxRows() or getLastRow() to correctly update each time I delete or insert a row, why can't they do that for me?
SpreadsheetApp.flush() fixed the problem.

Keeping value after reference cell has been changed

I need cell B3 to reference B1 while blank.
Once you put something in B1 it'll keep that value forever, even once B1 get's changed to something else.
This is my situation:
Basically I have a sheet that is fed by a Google form and each submission needs three key reference numbers each kept in columns a,b,c
A = Unit Number/Individuals name (There may be duplicates down the sheet as this is per submission)
B = Work Order (Imputed by me after actual work on unit has been done)
C = Cry Number/Reference number (Automatically generated per submission; no duplicates)
I then have a frozen row at the top which contains a search bar that you can search for the cry number (A1)(Which has a Data Validation set to column C so that you can only search valid cry numbers) and then a cell to add a W/O to that Cry Number (B1)
In column B3:1000, I have this formula copied down:
B3=if(isblank($C3),"",if($A$1=$C3, SUBSTITUTE($B$1,"",$B$1),""))
...which makes it so that if you select say "CN-168" (A valid cry number) and in 'B1' type "W1134" that work order number will be assigned.
Now I need that work order to stay there regardless of when 'A1' changes so that you can do the process over again on another submission.
Is it possible to do with formulas? If not, then a Google Script?
Here is a template of what I'm dealing with but not to the same scale as my Data Base
Its not possible with formulas but easily done with apps script. look at the onEdit trigger and the documentation for SpreadsheetApp to setValues to the appropiate ranges.
If you want to be 100% complete you also need a time trigger (say every 10 minutes) to check that a row wasnt missed. It can be missed during apps script errors/outages or when the sheet is changed from outside the sheets webpage/app (For example using the http spreadsheet api)

Copy formula down using script

I've been working on a script (With some help from folk on SO). I have managed to create a script that imports a csv file and updates named ranges based on the imported data.
Here is an image of what I'm trying to do:
At this point I have imported data which has been populated into columns A:G. The cells in columns H:L are formula and are based on the data in A:G. Because I have imported data the data are now longer than the formula range. If not relying on script I would just double click the small blue square at the bottom right of the highlighted cells and the formulas would copy down. This is what I'd like to have the script do once I have imported the data.
I created a range called "formula_range" which automatically updates with the length of data. "formula_range" starts in cell H3 and ends in L:N where N is the length of rows in the sheet.
"formula_range" therefore contains some populated cells with formula and then blank rows all the way to the bottom of the sheet.
I saw this SO post. So in English, my line of thinking is:
Create a variable formula_range H3:L3 as a range
paste formula_range to every row in formula_range
Voila?
How do I get the variable formula_range if the first row in formula_range will always have the formula to be copied down. Put another way it should be fixed at H3:L3.
I tried this:
var copy_range = ss.getRangeByName("formula_range").getRange(1,5,1);
SpreadsheetApp.getUi().alert(copy_range);
My alert said "undefined" (I really wasn't sure what it would show.)
My line of thinking is not the most efficient since I am going to copy over existing formula. Perhaps there is a better way?
How do I get the first row in a named range formula_range[0]; ?
How can I use script to copy down formula in formula_range?
I think what you're trying to accomplish could be achieved more efficiently with a built-in arrayformula:
https://support.google.com/docs/answer/3093275
Place in H3:
=ARRAYFORMULA(DATE(A3:A,B3:B,1))
for each of your formulas in H through L in row 3 surround them with array formula and extend the arguments with open-ended ranges starting with row 3 as in the above example

sheet.appendrow in adwords scripts is appending too many lines

I'm trying to add rows to a google spreadsheet through an adwords script which runs daily.
Some of the code so far is:
var report_iter = AdWordsApp.report(
'SELECT ' + columns_str +
'FROM ACCOUNT_PERFORMANCE_REPORT ' +
'DURING YESTERDAY', { apiVersion: 'v201302' }
).rows();
while(report_iter.hasNext()) {
var row = report_iter.next();
var row_array = [""]; // This is deliberate to include an empty cell in column A in the spreadsheet.
for(var i in columns) {
row_array.push(row[columns[i]]);
}
sheet.appendRow(row_array); // I think this line might be the problem
}
It is working properly, however, it has some unwanted outcomes as well. What I want to stop is every time I append a row to the bottom of the spreadsheet, it also appends 50 other rows of blank cells. Then, the next time I append a row, it appends it to the bottom of the spreadsheet, 50 rows after the one before... Is there any way to stop this. I had a look at using feed lists but I don't know how to do that or if you can with adwords scripts.
The only other thing I was thinking was to insert a new row to the bottom every time, find the row number, then insert data based on the row number.
What I had was working perfectly 3 days ago, but now it has just stopped.
Any suggestions or ideas?
1) you should not use appendRow. It would be much faster and efficient if you write all the rows at once using getRange setValues and using sheet.getLastRow to calculate the starting row.
2) if you do use appendRow, it will append to the last non-empty row, so it should work ok and shouldnt be writting past the blank rows that are autoinserted. However maybe you have something like an arrayformula or something else operating on an entire column that is writting in those empty rows at the bottom. Even if it writes blank values those rows wont be considered empty so the next appendRow will write below them.
The something is probably one of the calls setting the array to 30 rows, then only emptying the array, but not creating a new resized one.
But #1 is the way to go...