Auto insert row above, based on single cell value - google-apps-script

I am trying to auto-insert a row above the current top row (row 2) based on a cell's value.
I cannot figure out the variables I need to put into the script editor.
I tried googling for help and modified other peoples script to see if I could do it, and the answer is no, no I do not possess the knowledge/skill.
function conditionalNewRow() {
var ss = SpreadsheetApp.getActive().getSheetByName('NEW INV');
var sh = ss.getActiveSheet();
var headerRow = 1;
var firstRow = headerRow + 1;
var range = sh.getRange("A2"); // Get range of row 2.
var futureRange = sh.getRange("A3"); // Get range of row 3.
var numCols = range.getNumColumns(); // Get the number of columns for row 2.
var contentVal = false;
for (i = 1; i <= numCols; i++) {
var currentValue = range.getCell(1,i).getValue();
if (currentValue == "NO"){
contentVal = true;
break;
}
}
if (contentVal == true) {
sh.insertRowBefore(firstRow); // Insert an empty row into row 2.
futureRange.copyTo(sh.getRange(firstRow, 1, firstRow, numCols), {contentsOnly:false}); // Copy row 3 to row 2.
}
}
All I want is a blank row above the previous row when a cell meets certain criteria;
e.g. Cell A2 contains any of the following; YES, NO, LOADED, UNLOADED
If it contains any of those values, it will auto-insert a row above.

I am a little unclear on your intent and what issues you are having.
A few things I see:
1) Since your range is a single cell, var numCols = range.getNumColumns(); should always return 1, so your loop, for (i = 1; i <= numCols; i++), should run exactly once. It feels like there is a lot of redundant code here.
To get the value of cell A2, you could just write:
var range = sh.getRange("A2");
var currentValue = range.getValue();
2) From the if statements, it looks like you only want to add a new row if the value of A2 is something other than "NO". Is that correct? (This is not what your question states). If so, I think you're pretty close with the sh.insertRowBefore(firstRow); statement, it just might be getting lost in some convoluted logic.
3) Do you really want to copy everything from row 3 into row 2? In the question you state "All I want is a blank row above the previous row when a cell meets certain criteria".
Perhaps something like this is closer to what you want?
function conditionalNewRow() {
var ss = SpreadsheetApp.getActive().getSheetByName("NEW INV");
var sh = ss.getActiveSheet();
var range = sh.getRange("A2"); // Get range of row 2.
var currentValue = range.getValue();
if (currentValue !== "NO") {
sh.insertRowBefore(firstRow); // Insert an empty row into row 2.
}
}
Edit
From your comment, sounds like you want to insert a new row whenever A2 is edited to one of the selectable values. You may want to check out simple triggers, such as onEdit, which runs whenever a cell is edited. For instance, something like this:
/**
* The event handler triggered when editing the spreadsheet.
* #param {Event} e The onEdit event.
*/
function onEdit(e) {
// get sheet
var sheet = SpreadsheetApp.getActive().getSheetByName("NEW INV");
// Get the edited range
var editedRange = e.range;
// check if cell A2 was edited
if (editedRange.getA1Notation() === "A2") {
// check if value is a desired value
if (editedRange.getValue() === "YES" || "NO" || "LOADED" || "UNLOADED") {
// if yes to both, insert new row
sheet.insertRowBefore(2);
}
}
}

Related

Script - Add a row beneath, based on conditional criteria

Dear Oracles of the script,
I have been trying to get some script to automatically add a row beneath the one I have inputted on, but only if the Balance is anything BUT zero. If it's zero, I don't want another row adding.
I've tried a few scripts and looked around the site, and tried them with triggers with on edit, but they just seem to add a row, despite me trying to state a condition for them to trigger.
function onEdit(event) {
var eventRange = event.range;
if (eventRange.getColumn() == 12) { // 12 = column of input that triggers it
var columnXRange =
SpreadsheetApp.getActiveSheet().getRange(eventRange.getRow(), 13,
eventRange.getNumRows(), 12); /// column number it affects
var values = columnXRange.getValues();
for (var i = 0; i < values.length; i++) {
if (!values[i][0]) { // If cell isn't empty
values[i][0] = '0';
}
}
columnXRange.setValues(values);
}
}
function Clear(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('AGL');
sheet.getRange('N4:N').clearContent();
}
function AddRow() {
var sheet = SpreadsheetApp.getActiveSheet();
if (sheet.getName() == "AGL") {
var activeCell = sheet.getActiveCell();
if (activeCell.getColumn() == 13) {
var Balance = sheet.getRange('N:N');
if (Balance != '0'); {
sheet.insertRowAfter(activeCell.getRow());
}
}
}
}
In column N, I have an array formula working out the balance of stock in, against stock out.
In column M, I have a script running that will add a 0 when something is put into column L. I also have a script that erases the output of the array formula, so they don't get tangled up with each other.
I would like, when editing a row, when I place a figure in column L or M, and if the balance in Column N is greater than 0, I would like a new row adding underneath. (If you can get it to add the values from A & B, that'd be a bonus, but not fussy.) If the balance is 0, I don't want a row adding.
Currently, I have mixed results with it just adding a row every time I edit column N.
Requirement:
Add a row when columns L or M are edited and the value in column N is greater than 0 (& if possible, add values from columns A & B to the new row).
Solution:
This is pretty much all you need for your script. I've added comments to explain what each part is doing so it should be pretty easy to follow.
function onEdit(e) {
//define edited sheet, row number and column number
var sh = e.source.getActiveSheet();
var row = e.range.getRow();
var col = e.range.getColumn();
//get value of column N for edited row
var val = sh.getRange(row, 14).getValue();
//if columns L or M are edited and column N is greater than 0
if ((col === 12 || col === 13) === true && val > 0) {
//insert row below edited row
sh.insertRowAfter(row);
//get values of columns A and B of edited row
var vals = sh.getRange(row, 1, 1, 2).getValues();
//set values in columns A and B
sh.getRange(row+1, 1, 1, 2).setValues(vals);
}
}
Notes:
I haven't included any of your other functions, only adding a row, you can incorporate these in this function if you desire.
You won't be able to run this script manually at all (it'll fail on the first line), it'll just run automatically when the sheet is edited.
References:
Event Objects
Class Sheet

How to get Row where two Columns equal specific values

I'm very new and I'm trying to create a Time in/Time out sheet. I have 2 separate sheets, first(ACTIVE) is where the trigger happens that starts the onEdit(e) script. All the functions that start onEdit(e) affects the second sheet(PASSIVE) to fill out Columns A(Last Name), B(First Name), C(Location), D(Time Out). I finished making the Time out functions by getting value of A, B, C + Active Row(this isn't the code). The trigger is always on the same row as the values being copied, so it was relatively simple. On the PASSIVE sheet I have all the values being stored using a code someone made called addRecord where it gets last row + 1 of the PASSIVE sheet and installs the values grabbed from the ACTIVE sheet and plugs them in. So it adds records without overwriting anything. Works beautifully. However making a "time in" function has been difficult. E(Time In) My idea is to getRow of the PASSIVE sheet by searching PASSIVE!A for the Value grabbed from (ACTIVE!A + Active Row) once it finds a match, it sees if (PASSIVE!E + the matched row) is empty. If it is, it adds new.Date and finishes. If it isn't empty, it ignores this row and continues searching down the line for the next Row that has PASSIVE!A match the grabbed value. Once it finds this Row, getRow. setValue of (PASSIVE!E + grabbed row, new Date())
I did find a function online to find the first row that matched the ACTIVE!A with PASSIVE!A. But it kept overwriting the date on the first match. It never ignored row with nonempty cell to the next match row. Maybe I was just slightly off, which is why I'm asking for a lot of detail and explanation in the Answers.
This was the Code I used from another answer.
function getCurrentRow() {
var currentRow = SpreadsheetApp.getActiveSheet().getActiveSelection().getRowIndex();
return currentRow;
}
function onSearch1()
{
What I added
var row = getCurrentRow();
var activeLocation = getValue('ACTIVE!A' + row);
Continued Other Code
var searchString = activeLocation;
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PASSIVE");
var column =1; //column Index
var columnValues = sheet.getRange(2, column, sheet.getLastRow()).getValues(); //1st is header row
var searchResult = columnValues.findIndex(searchString); //Row Index - 2
What I added
setValue(PASSIVE!E + searchResult, new Date().toLocaleString())
It worked if everyone has a different name, but the search Result always found the first row of the match, I tried adding an if ACTIVE!A == PASSIVE!A
&& PASSIVE!E =="", grabRow (I know this isn't proper code) But I didn't even know where to put this if function or if it would work or if it would just keep coming up false after it runs the first time true.
Continued Other Code
if(searchResult != -1)
{
//searchResult + 2 is row index.
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PASSIVE").setActiveRange(sheet.getRange(searchResult + 2, 1))
}
if(searchResult = searchResult2) {
setValue('PASSIVE!E' + searchResult, new Date().toLocaleString())
}
}
Array.prototype.findIndex = function(search){
if(search == "") return false;
for (var i=0; i<this.length; i++)
if(this[i] == search) return i;
return -1;
}
So this is what I used, but not sure if it's the right way to go about this. Every time I used it, it would only set the SearchResult to the first row it found that had the searchString I'd actually prefer if it found the last row, considering the add record goes down over time and signing in should be the most recent name. But I'm guessing if I can just get a function that searches a range and finds the row for two values in specific columns, I can then just setValue('PASSIVE!E' + foundRow, new Date().toLocaleString())
Edit 5/9/2019 17:34 PST
Thank you to those Answering. I'm expanding on the question.
function rowWhereTwoColumnsEqual(value1,col1,value2,col2) {
var value1=value1 || 'A1';//testing
var value2=value2 || "";
The idea I'm having is to search Column1 of another sheet for, let's say, 'SheetA1' (the first sheet). And Column3 of another sheet for "" (cellisempty).
var value1= 'Sheet1!A1';
var value2= "";
var col1='Sheet2!A';
var col2='Sheet2!C';
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet2');
var rg=sh.getDataRange();
var vA=rg.getValues();
However, I don't know how the vA works. I also want to getRow() of the Row that is found in order to use that number in another function.
Try this:
function rowWhereTwoColumnsEqual(value1,col1,value2,col2) {
var value1=value1 || 9;//testing
var value2=value2 || 8;
var col1=col1 || 1;//testing
var col2=col2 || 2;//testing
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getDataRange();
var vA=rg.getValues();
var rA=[];
for(var i=0;i<vA.length;i++) {
if(vA[i][col1-1]==value1 && vA[i][col2-1]==value2) {
rA.push(i+1);
}
}
SpreadsheetApp.getUi().alert(rA.join(','));
//return rA;//as an array
//return rA.join(',');//as a string
}

How can I store a range of cells to an array?

If I have a list of data in cells A1:A150 (but the amount can vary), is there a way to push that into an array without looking at each cell individually to determine if it is empty? I exceed my execution time by doing this and I need a faster way to store the data and stop when it hits an empty cell.
Below is how I currently do it:
for (var i = 1; i < 500; i++) {
if(datasheet.getRange("A" + i).getValue() == ""){
break;
}
else{
addedlist_old.push(datasheet.getRange("A" + i).getValue())
}
If you're using only one column, I'd suggest:
// my2DArrayFromRng = sh.getRange("A2:A10").getValues();
var my2DArrayFromRng = [["A2"],["A3"],["A4"],["A5"],[],[],["A8"],["A9"],[]];
var a = my2DArrayFromRng.join().split(',').filter(Boolean);
The methods .join() and .split(',') together convert the 2D array to a plain array (["A2","A3","A4","A5",,,"A8","A9",]).
Then the method .filter(Boolean) strips the empty elements. The code above returns [A2, A3, A4, A5, A8, A9].
Try this:
var sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName(SHEET_NAME);
var lastRow = sheet.getLastRow();
var data = sheet.getRange(1, 1, lastRow, 1).getValues(); //getRange(starting Row, starting column, number of rows, number of columns)
for(var i=0;i<(lastRow-1);i++)
{
Logger.log(data[0][i]);
}
the variable data stores all the cells of column A.
Cell A1 is stored in data[0][0], cell A2 is stored in data[0][1], cell A3 is stored in data[0][2] and so on.
The getRange(starting Row, starting column, number of rows, number of columns) is a batch operation so it is much faster when you have a large dataset.
If you don't have empty cells in between it's actually pretty easy.
var lastRow = sheet.getLastRow();
var array = sheet.getRange('A1:A' + lastRow).getValues();
If you need to weed out empty entries after that, you can use a for statement, or to be faster, filter like an earlier answer shows.
var filteredArray = array.filter(function(n){ return n != '' });
The main difference between this answer and the one posted earlier that I mentioned is that getValues() will give you an array.
I've tested this and it works in google apps script, and it does not time out when I use the array, or even when I put in large amounts of data (I tested it with an array that has about 20-50 characters per entry and about 500 entries). Just make sure to define the var sheet or put in your own variable.
Try this:
It will allow you to select any column on the sheet.
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
ui.createMenu('Sheet Functions')
.addItem('Get values from column', 'getVals')
.addToUi();
}
function getVals() {
var sheet = ss.getActiveSheet();
var getColumnLetter = ui.prompt('Select column..' , 'Enter the letter of the target column..', ui.ButtonSet.OK_CANCEL);
if(getColumnLetter.getSelectedButton() == ui.Button.CANCEL) {
return } else {
getColumnLetter = getColumnLetter.getResponseText().toUpperCase();
}
var columnNo = getColumnLetter.charCodeAt(0) - 64;
try { var data = sheet.getRange(1, columnNo, sheet.getMaxRows()).getValues().filter(String); } catch (e) { ui.alert('Invalid input please try again.', ui.ButtonSet.OK); return;}
/*
*
* Do what ever you need to do down here
*
*/
}

Automatically move data from one sheet to another in google docs

i have a spreadsheet that i keep track of tasks i need to do, once complete i enter a date in the last column. What i want is for that completed task to be moved to sheet 2.
At present i have sheet 1 named SUD_schedule and i want the completed row of data to be moved to sheet 2 named SUD_archive. I've looked through the forum posts already and i've tried a variation of scripts but so far no luck. The closest i have come is this script:
function onEdit() {
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();//Original sheet
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];//target sheet
// to act on only one sheet, check the sheet name here:
//If it si not first sheet, it will do nothing
if (sheet1.getSheetName() != "SUD_schedule") {
return;
}
//Get Row and column index of active cell.
var rowIndex = sheet1.getActiveRange().getRowIndex();
var colIndex = sheet1.getActiveRange().getColumnIndex();
//If the selected column is 10th and it is not a header row
if (colIndex == 16 && rowIndex > 1) {
//Get the data from the current row
var data = sheet1.getRange(rowIndex,1,1,9).getValues();
var lastRow2;
(sheet2.getLastRow()==0)?lastRow2=1:lastRow2=sheet2.getLastRow()+1;
//Copy the data to the lastRow+1th row in target sheet
sheet2.getRange(lastRow2,1,1,data[0].length).setValues(data);
}
}
Column P (16) is the task complete date, row 1 is frozen and contains column headers.
Can anybody help show where i'm going wrong.
Kind regards
Den
Your code is not generic and you are more complicating your objective. Below will work out your need.
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('SUD_schedule');
var sheet2 = ss.getSheetByName('SUD_archive');
var dateColumn = "16";
var array = []
var range = sheet1.getRange(1, 1, sheet1.getLastRow(), dateColumn);
for (var i = 2; i <= sheet1.getLastRow(); i++) //i iterates from 2 as you say R1 is header
{
if(isValidDate(range.getCell(i, dateColumn).getValue()) == true) //checking if any values on column16 is valid date
{
data = sheet1.getRange(i, 1, 1, dateColumn).getValues(); //Getting the range values of particular row where C16 is date
for (var j = 0; j < dateColumn; j++) //Adding the row in array
{
array.push(data[0][j]);
}
}
if(array.length > 0)
{
sheet2.appendRow(array); //Appending the row in sheet2
array = [];
sheet1.deleteRow(i); //deleting the row in sheet as you said you want to move, if you copy remove this and next line
i=i-1; //managing i value after deleting a row.
}
}
}
//Below function return true if the given String is date, else false
function isValidDate(d) {
if ( Object.prototype.toString.call(d) !== "[object Date]" )
return false;
return !isNaN(d.getTime());
}
I am not sure that the syntax you have as used below is entirely correct.
(sheet2.getLastRow()==0)?lastRow2=1:lastRow2=sheet2.getLastRow()+1;
sheet2.getRange(lastRow2,1,1,data[0].length).setValues(data);
What I know will work for certain is if you omit the variable lastRow2 all together and use this instead.
sheet2.getRange(getLastRow+1,1,1,data[0].length).setValues(data);
To complement Joachin's answer, here is how you can adapt that code if you don't have the date in the last row. In the below shown part of the code replace Lastcolumnumber with your last column.
//Getting the range values of particular row where C16 is date
data = sheet1.getRange(i, 1, 1, LASTCOLUMNNUMBER).getValues();
//Adding the row in array
for (var j = 0; j < LASTCOLUMNNUMBER; j++)

Delete a row in Google Spreadsheets if value of cell in said row is 0 or blank

I'd like to be able to delete an entire row in a Google Spreadsheets if the value entered for say column "C" in that row is 0 or blank. Is there a simple script I could write to accomplish this?
Thanks!
I can suggest a simple solution without using a script !!
Lets say you want to delete rows with empty text in column C.
Sort the data (Data Menu -> Sort sheet by column C, A->Z) in the sheet w.r.t column C, so all your empty text rows will be available together.
Just select those rows all together and right-click -> delete rows.
Then you can re-sort your data according to the column you need.
Done.
function onEdit(e) {
//Logger.log(JSON.stringify(e));
//{"source":{},"range":{"rowStart":1,"rowEnd":1,"columnEnd":1,"columnStart":1},"value":"1","user":{"email":"","nickname":""},"authMode":{}}
try {
var ss = e.source; // Just pull the spreadsheet object from the one already being passed to onEdit
var s = ss.getActiveSheet();
// Conditions are by sheet and a single cell in a certain column
if (s.getName() == 'Sheet1' && // change to your own
e.range.columnStart == 3 && e.range.columnEnd == 3 && // only look at edits happening in col C which is 3
e.range.rowStart == e.range.rowEnd ) { // only look at single row edits which will equal a single cell
checkCellValue(e);
}
} catch (error) { Logger.log(error); }
};
function checkCellValue(e) {
if ( !e.value || e.value == 0) { // Delete if value is zero or empty
e.source.getActiveSheet().deleteRow(e.range.rowStart);
}
}
This only looks at the value from a single cell edit now and not the values in the whole sheet.
I wrote this script to do the same thing for one of my Google spreadsheets. I wanted to be able to run the script after all the data was in the spreadsheet so I have the script adding a menu option to run the script.
/**
* Deletes rows in the active spreadsheet that contain 0 or
* a blank valuein column "C".
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function readRows() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var rowsDeleted = 0;
for (var i = 0; i <= numRows - 1; i++) {
var row = values[i];
if (row[2] == 0 || row[2] == '') {
sheet.deleteRow((parseInt(i)+1) - rowsDeleted);
rowsDeleted++;
}
}
};
/**
* Adds a custom menu to the active spreadsheet, containing a single menu item
* for invoking the readRows() function specified above.
* The onOpen() function, when defined, is automatically invoked whenever the
* spreadsheet is opened.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet
*/
function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Remove rows where column C is 0 or blank",
functionName : "readRows"
}];
sheet.addMenu("Script Center Menu", entries);
};
Test spreadsheet before:
Running script from menu:
After running script:
I was having a few problems with scripts so my workaround was to use the "Filter" tool.
Select all spreadsheet data
Click filter tool icon (looks like wine glass)
Click the newly available filter icon in the first cell of the column you wish to search.
Select "Filter By Condition" > Set the conditions (I was using "Text Contains" > "word")
This will leave the rows that contain the word your searching for and they can be deleted by bulk selecting them while holding the shift key > right click > delete rows.
This is what I managed to make work. You can see that I looped backwards through the sheet so that as a row was deleted the next row wouldn't be skipped. I hope this helps somebody.
function UpdateLog() {
var returnSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('RetLog');
var rowCount = returnSheet.getLastRow();
for (i = rowCount; i > 0; i--) {
var rrCell = 'G' + i;
var cell = returnSheet.getRange(rrCell).getValue();
if (cell > 0 ){
logSheet.
returnSheet.deleteRow(i);
}
}
}
quite simple request. Try this :
function try_It(){
deleteRow(2); //// choose col = 2 for column C
}
function deleteRow(col){ // col is the index of the column to check for 0 or empty
var sh = SpreadsheetApp.getActiveSheet();
var data = sh.getDataRange().getValues();
var targetData = new Array();
for(n=0;n<data.length;++n){
if(data[n][col]!='' && data[n][col]!=0){ targetData.push(data[n])};
}
Logger.log(targetData);
sh.getDataRange().clear();
sh.getRange(1,1,targetData.length,targetData[0].length).setValues(targetData);
}
EDIT : re-reading the question I'm not sure if the question is asking for a 'live' on Edit function or a function (like this above) to apply after data has been entered... It's not very clear to me... so feel free to be more accurate if necessary ;)
There is a simpler way:
Use filtering to only show the rows which you want to delete. For example, my column based on which I want to delete rows had categories on them, A, B, C. Through the filtering interface I selected only A and B, which I wanted to delete.
Select all rows and delete them. Doing this, in my example, effectively selected all A and B rows and deleted them; now my spreadsheet does not show any rows.
Turn off the filter. This unhides my C rows. Done!
There is a short way to solve that instead of a script.
Select entire data > Go to menu > click Data tab > select create filter > click on filter next to column header > pop-up will appear then check values you want to delete > click okay and copy the filtered data to a different sheet > FINISH
reading your question carefully, I came up with this solution:
function onOpen() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// create menu
var menu = [{name: "Evaluate Column C", functionName: "deleteRow"}];
// add to menu
ss.addMenu("Check", menu);
}
function deleteRow() {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get active/selected row
var activeRow = ss.getActiveRange().getRowIndex();
// get content column C
var columnC = ss.getRange("C"+activeRow).getValue();
// evaluate whether content is blank or 0 (null)
if (columnC == '' || columnC == 0) {
ss.deleteRow(parseInt(activeRow));
}
}
This script will create a menu upon file load and will enable you to delete a row, based on those criteria set in column C, or not.
This simple code did the job for me!
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); // get active spreadsheet
var activeRow = ss.getActiveRange().getRowIndex(); // get active/selected row
var start=1;
var end=650;
var match='';
var match2=0; //Edit this according to your choice.
for (var i = start; i <= end; i++) {
var columnC = ss.getRange("C"+i).getValue();
if (columnC ==match || columnC ==match2){ ss.deleteRow(i); }
}
}
The below code was able to delete rows containing a date more than 50 days before today in a particular column G , move these row values to back up sheet and delete the rows from source sheet.
The code is better as it deletes the rows at one go rather than deleting one by one. Runs much faster.
It does not copy back values like some solutions suggested (by pushing into an array and copying back to sheet). If I follow that logic, I am losing formulas contained in these cells.
I run the function everyday in the night (scheduled) when no one is using the sheet.
function delete_old(){
//delete > 50 day old records and copy to backup
//run daily from owner login
var ss = SpreadsheetApp.getActiveSpreadsheet();
var bill = ss.getSheetByName("Allotted");
var backss = SpreadsheetApp.openById("..."); //backup spreadsheet
var bill2 = backss.getSheetByName("Allotted");
var today=new Date();
//process allotted sheet (bills)
bill.getRange(1, 1, bill.getMaxRows(), bill.getMaxColumns()).activate();
ss.getActiveRange().offset(1, 0, ss.getActiveRange().getNumRows() - 1).sort({column: 7, ascending: true});
var data = bill.getDataRange().getValues();
var delData = new Array();
for(n=data.length-1; n>1; n--){
if(data[n][6] !=="" && data[n][6] < today.getTime()-(50*24*3600*1000) ){ //change the condition as per your situation
delData.push(data[n]);
}//if
}//for
//get first and last row no to be deleted
for(n=1;n<data.length; n++){
if(data[n][6] !=="" && data[n][6] < today.getTime()-(50*24*3600*1000) ){
var strow=n+1 ; //first row
break
}//if
}//for
for(n=data.length-1; n>1; n--){
if(data[n][6] !=="" && data[n][6] < today.getTime()-(50*24*3600*1000) ){
var ltrow=n+1 ; //last row
break
}//if
}//for
var bill2lr=bill2.getLastRow();
bill2.getRange((bill2lr+1),1,delData.length,delData[0].length).setValues(delData);
bill.deleteRows(strow, 1+ltrow-strow);
bill.getRange(1, 1, bill.getMaxRows(), bill.getMaxColumns()).activate();
ss.getActiveRange().offset(1, 0, ss.getActiveRange().getNumRows() - 1).sort({column: 6, ascending: true}); //get back ordinal sorting order as per column F
}//function