specific columns of selected row for print - google-apps-script

How to set specific columns of selected row for print ? Google Apps Script - Google Sheets
Where I select a row of the google sheet, the data of these columns should be printed by the macro ("A", "B", "J", "S").
I've written this macro to select rows but I don't know how to make more changes required
function print() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(spreadsheet.getCurrentCell().getRow(), 1, 1, sheet.getMaxColumns()).activate();
}

I believe your goal is as follows.
When you select a cell, you want to retrieve the values of the specific columns of the row of the selected cell.
In this case, how about the following modification?
Modified script:
function print() {
var selectColumns = ["A", "B", "J", "S"]; // This is from your question.
var sheet = SpreadsheetApp.getActiveSheet();
var currentRow = sheet.getCurrentCell().getRow();
var columnIndex = selectColumns.map(letter => [...letter.toUpperCase()].reduce((c, e, i, a) => (c += (e.charCodeAt(0) - 64) * Math.pow(26, a.length - i - 1)), -1));
var values = sheet.getRange(currentRow, 1, 1, sheet.getMaxColumns()).getValues().map(r => columnIndex.map(c => r[c]))[0].join(",");
console.log(values) // Here, you can also confirm the values in the log.
Browser.msgBox(values); // You can see the values at a dialog of Spreadsheet.
}
When you select a cell and run this script, the values of the specific columns "A", "B", "J", "S" of the row of the selected cell are retrieved.
At columnIndex, the column letters are converted to the column indexes.
From sheet.getRange(spreadsheet.getCurrentCell().getRow(), 1, 1, sheet.getMaxColumns()).activate();, if you want to activate the specific columns, how about the following modification?
function print2() {
var selectColumns = ["A", "B", "J", "S"]; // This is from your question.
var sheet = SpreadsheetApp.getActiveSheet();
var currentRow = sheet.getCurrentCell().getRow();
sheet.getRangeList(selectColumns.map(e => e + currentRow)).activate();
}
Reference:
map()
Added 1:
From your following reply,
I mean when i using function print2() if selectColumns = ["A", "B", "C" ] , Cells A B C are highlighted And that's great. but when i try To Use CTRL + P and And I make the settings related to print the selected cells, I only see cell c in the print output
First, in this case, it is required to select the continuous ranges like "A1:C1". When the cells "A1:C1" and "E1" are selected, only "E1" is shown. And, when the cells are selected using RangeList, the cells are selected for every cell. I thought that this might be the reason for your current issue. So, when you want to use the selected cells using the printer setting, how about the following sample script?
Sample script:
When you use this script, please set startColumn and endColumn. And, please select a cell. And, please run the script. By this, in this sample, the columns "A" to "C" are selected. When you push CTRL + P and do the settings related to print the selected cells, you can see the 3 cells.
function print3() {
var startColumn = "A"; // Please set the start column.
var endColumn = "C"; // Please set the end column.
var sheet = SpreadsheetApp.getActiveSheet();
var currentRow = sheet.getCurrentCell().getRow();
sheet.getRange(`${startColumn}${currentRow}:${endColumn}${currentRow}`).activate();
}
Added 2:
If you want to use the discrete columns and cells, how about the following sample script?
Sample script:
This script uses Sheets API. So, please enable Sheets API at Advanced Google services.
When you use this script, please set selectColumns. In this case, you can set the discrete columns. And, please select a cell, and run the script of print4. By this, only the columns of selectColumns of the selected row are shown. By this, when you push CTRL + P, you can see the showing cells. This is another workaround for achieving your goal.
After your work is finished, when you run showAll, all rows and columns are shown.
function print4() {
var selectColumns = ["A", "B", "J", "S"]; // This is from your question.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var currentRow = sheet.getCurrentCell().getRow();
var columnIndex = selectColumns.map(letter => [...letter.toUpperCase()].reduce((c, e, i, a) => (c += (e.charCodeAt(0) - 64) * Math.pow(26, a.length - i - 1)), -1));
var sheetId = sheet.getSheetId();
var requests = [...Array(sheet.getMaxColumns())].reduce((ar, _, i) => {
if (!columnIndex.includes(i)) {
ar.push({ updateDimensionProperties: { range: { sheetId, startIndex: i, endIndex: i + 1, dimension: "COLUMNS" }, properties: { hiddenByUser: true }, fields: "hiddenByUser" } });
}
return ar;
}, []);
var maxRows = sheet.getMaxRows();
if (currentRow == 1) {
requests.push({ updateDimensionProperties: { range: { sheetId, startIndex: currentRow, endIndex: maxRows, dimension: "ROWS" }, properties: { hiddenByUser: true }, fields: "hiddenByUser" } });
} else if (currentRow == maxRows) {
requests.push({ updateDimensionProperties: { range: { sheetId, startIndex: 0, endIndex: maxRows - 1, dimension: "ROWS" }, properties: { hiddenByUser: true }, fields: "hiddenByUser" } });
} else {
requests.push({ updateDimensionProperties: { range: { sheetId, startIndex: 0, endIndex: currentRow - 1, dimension: "ROWS" }, properties: { hiddenByUser: true }, fields: "hiddenByUser" } });
requests.push({ updateDimensionProperties: { range: { sheetId, startIndex: currentRow, endIndex: maxRows, dimension: "ROWS" }, properties: { hiddenByUser: true }, fields: "hiddenByUser" } });
}
Sheets.Spreadsheets.batchUpdate({ requests }, ss.getId());
}
function showAll() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
const requests = [{ updateDimensionProperties: { range: { sheetId: sheet.getSheetId(), dimension: "COLUMNS" }, properties: { hiddenByUser: false }, fields: "hiddenByUser" } }, { updateDimensionProperties: { range: { sheetId: sheet.getSheetId(), dimension: "ROWS" }, properties: { hiddenByUser: false }, fields: "hiddenByUser" } }];
Sheets.Spreadsheets.batchUpdate({ requests }, ss.getId());
}

Related

Google App Script: Speed up script - Conditional copy to another tab

There are 2 tabs:
Alerts
MASTER
The script:
In Alerts tab, if A is empty and H >= 45, copies the value from G to A, on the next empty row, in MASTER
Ads specific values to some columns in tab MASTER, on the recently added row. All new rows will have those same values.
The script was retrieving ocasionally some timeouts and I tried to add some
SpreadsheetApp.flush();
With our without any relation to these additions, the script started to work better but I'm sure it will return more timeouts as the list may grow.
Is it possible to speed it up?
function CopyPendingPayment(){
var sheet = SpreadsheetApp.getActive();
var sourceSheet = sheet.getSheetByName("Alerts");
var destination = sheet.getSheetByName("MASTER");
var lastRow = sourceSheet.getDataRange().getLastRow();
var column = destination.getRange('A' + destination.getMaxRows())
SpreadsheetApp.flush();
for(var row=3; row<=lastRow; row++){
if(sourceSheet.getRange(row,1).getValue() == "" & sourceSheet.getRange(row,8).getValue() >= "45"){
var rangeToCopy = "G"+row+":G"+row;
var lastFilledRow = parseInt(column.getNextDataCell(SpreadsheetApp.Direction.UP).getA1Notation().slice(1))
SpreadsheetApp.flush();
sourceSheet.getRange(rangeToCopy).copyTo(destination.getRange(lastFilledRow+1,1)),{contentsOnly:true};
destination.getRange(lastFilledRow+1, 9).setValue("No Payment Received");
destination.getRange(lastFilledRow+1, 10).setValue(new Date());
destination.getRange(lastFilledRow+1, 12).setValue("PENDING");
destination.getRange(lastFilledRow+1, 13).setValue("- Reminder sent");
destination.getRange(lastFilledRow+1, 14).setValue(new Date());
}
}
}
I guess at least the part where it ads the values on the different columns it could be done quicker, right?
Can anyone give me a hand?
Thank you in advance
Sample
I believe your goal is as follows.
You want to reduce the process cost of your script.
In this case, how about the following modification?
Modified script:
function CopyPendingPayment() {
var sheet = SpreadsheetApp.getActive();
var sourceSheet = sheet.getSheetByName("Alerts");
var destination = sheet.getSheetByName("MASTER");
// I modified below script.
var srcValues = sourceSheet.getRange("A3:H" + sourceSheet.getLastRow()).getValues();
var lastRow = destination.getLastRow();
var obj = srcValues.reduce((o, [a,,,,,,g,h], i) => {
if (a == "" && h >= 45) {
o.values.push([g]);
o["No Payment Received"].push(`I${lastRow + i + 1}`);
o["date"].push(`J${lastRow + i + 1}`, `N${lastRow + i + 1}`);
o["PENDING"].push(`L${lastRow + i + 1}`);
o["- Reminder sent"].push(`M${lastRow + i + 1}`);
}
return o;
}, {values: [], "No Payment Received": [], "date": [], "PENDING": [], "- Reminder sent": []});
destination.getRange(lastRow + 1, 1, obj.values.length).setValues(obj.values);
["No Payment Received", "date", "PENDING", "- Reminder sent"].forEach(e => destination.getRangeList(obj[e]).setValue(e == "date" ? new Date() : e));
}
In this modification, the value of column "A" is put with setValues of Class Range. And, the values of columns "I", "J", "L", "M" and "N" are put with setValue of Class RangeList. Because I thought that you might want to keep other columns.
As another method, I think that your goal can be also achieved by overwriting the cells of the destination sheet. In that case, how about the following script?
function CopyPendingPayment() {
var sheet = SpreadsheetApp.getActive();
var sourceSheet = sheet.getSheetByName("Alerts");
var destination = sheet.getSheetByName("MASTER");
var srcValues = sourceSheet.getRange("A3:H" + sourceSheet.getLastRow()).getValues();
var lastRow = destination.getLastRow();
var values = srcValues.reduce((ar, [a,,,,,,g,h], i) => {
if (a == "" && h >= 45) {
var date = new Date();
ar.push([g,,,,,,,,"No Payment Received", date,,"PENDING","- Reminder sent",date]);
}
return ar;
}, []);
destination.getRange(lastRow + 1, 1, values.length, values[0].length).setValues(values);
}
References:
setValues(values) of Class Range
setValue(value) of Class RangeList
Added:
From your following replying,
It seems a lot quicker, indeed. I've tested your versions vs mine. The only problem is that if there is an array in any ot the destination sheet columns, the values are pasted below. The original version takes into consideration that and pastes the values on the 1st blank cell of column A.
How about the following sample script?
Sample script:
function CopyPendingPayment_C() {
// This is from https://stackoverflow.com/a/44563639
Object.prototype.get1stEmptyRowFromTop = function (columnNumber, offsetRow = 1) {
const range = this.getRange(offsetRow, columnNumber, 2);
const values = range.getDisplayValues();
if (values[0][0] && values[1][0]) {
return range.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow() + 1;
} else if (values[0][0] && !values[1][0]) {
return offsetRow + 1;
}
return offsetRow;
};
var sheet = SpreadsheetApp.getActive();
var sourceSheet = sheet.getSheetByName("Alerts");
var destination = sheet.getSheetByName("MASTER");
// I modified below script.
var srcValues = sourceSheet.getRange("A3:H" + sourceSheet.getLastRow()).getValues();
var lastRow = destination.get1stEmptyRowFromTop(1) - 1;
// I modified below part.
var obj = srcValues.reduce((o, [a,,,,,,g,h]) => {
if (a == "" && h >= 45) {
o.offset++;
o.values.push([g]);
o["No Payment Received"].push(`I${o.offset}`);
o["date"].push(`J${o.offset}`, `N${o.offset}`);
o["PENDING"].push(`L${o.offset}`);
o["- Reminder sent"].push(`M${o.offset}`);
}
return o;
}, {values: [], "No Payment Received": [], "date": [], "PENDING": [], "- Reminder sent": [], offset: lastRow});
destination.getRange(lastRow + 1, 1, obj.values.length).setValues(obj.values);
["No Payment Received", "date", "PENDING", "- Reminder sent"].forEach(e => destination.getRangeList(obj[e]).setValue(e == "date" ? new Date() : e));
}

Google App Script Exceeded Maximum Execution Limit

I've been attempting to export the entire contents of my spreadsheet. The code works fine, but it displays an error message that says Maximum execution limit exceeded. According to my research, the maximum execution time is only 6 minutes. I'm new to this and am still trying to figure it out. Could you kindly help me in determining a possible solution for this?
Here's the code that I'm currently using...
function PrintMultiple() {
const srcSs = SpreadsheetApp.getActiveSpreadsheet();
const sheet = srcSs.getSheetByName("TEMPLATE");
const values = sheet.getRange("C2").getDataValidation().getCriteriaValues()[0].getValues().flat().filter(String);
const dstSs = SpreadsheetApp.create("tempSpreadsheet");
SpreadsheetApp.getActive().toast("About to take some action... Please wait...");
values.forEach(v => {
sheet.getRange("C2").setValue(v);
SpreadsheetApp.flush();
const tempSheet = sheet.copyTo(srcSs);
const range = tempSheet.getDataRange();
range.copyTo(range, {contentsOnly: true});
tempSheet.getRange("B2:2").clear().clearDataValidations();
tempSheet.getDrawings().forEach(e => e.remove());
tempSheet.deleteColumn(1);
tempSheet.deleteRow(1);
tempSheet.deleteRow(2);
tempSheet.deleteRow(3);
tempSheet.copyTo(dstSs);
srcSs.deleteSheet(tempSheet);
});
dstSs.deleteSheet(dstSs.getSheets()[0]);
}
I believe your goal is as follows.
You want to reduce the process cost of your script.
From your script, when the length of values is large, I thought that the process of copy might be the high cost. So, in this case, how about using Sheets API? I thought that when Sheets API is used, the process cost of your script might be able to be reduced. When Sheets API is used for your script, it becomes as follows.
Modified script:
Before you use this script, please enable Sheets API at Advanced Google services.
function PrintMultiple() {
const ss = SpreadsheetApp.getActiveSpreadsheet().copy("tempSpreadsheet");
const sheet = ss.getSheetByName("TEMPLATE");
const sourceSheetId = sheet.getSheetId();
sheet.getDrawings().forEach(e => e.remove());
const values = sheet.getRange("C2").getDataValidation().getCriteriaValues()[0].getValues().flat().filter(String);
const requests1 = values.flatMap((v, i) => {
const sheetId = 123456 + i;
return [
{ duplicateSheet: { newSheetName: `page${i + 1}`, sourceSheetId, newSheetId: sheetId, insertSheetIndex: i + 2 } },
{ updateCells: { range: { sheetId: sheetId, startRowIndex: 1, endRowIndex: 2, startColumnIndex: 2, endColumnIndex: 3 }, rows: [{ values: [{ userEnteredValue: { numberValue: v } }] }], fields: "userEnteredValue.numberValue" } },
];
});
Sheets.Spreadsheets.batchUpdate({ requests: requests1 }, ss.getId());
const requests2 = values.flatMap((_, i) => {
const sheetId = 123456 + i;
return [
{ copyPaste: { source: { sheetId }, destination: { sheetId }, pasteType: "PASTE_VALUES" } },
{ deleteDimension: { range: { sheetId, startIndex: 0, endIndex: 3, dimension: "ROWS" } } },
{ deleteDimension: { range: { sheetId, startIndex: 0, endIndex: 1, dimension: "COLUMNS" } } },
];
});
Sheets.Spreadsheets.batchUpdate({ requests: requests2 }, ss.getId());
ss.deleteSheet(sheet);
ss.deleteSheet(ss.getSheets()[0]);
}
In this modification, the method of batchUpdate of Sheets API is used for copying values and deleting rows and columns.
When this script is run, "tempSpreadsheet" Spreadsheet is created to the root folder.
Reference:
Method: spreadsheets.batchUpdate

Conditional formatting of borders in Google Sheets using Apps Script

I would like to add borders to cells in a Google Sheet using conditional formatting. I am aware that you cannot do this using the standard conditional formatting process in Google Sheets so I'm trying to get to grips with how to do it using a script.
I have copied a script from the following solution, and attempted to edit it for my needs: (Add border format to row if condition met in Google Sheets)
However, I am still coming to terms with how these scripts work and haven't yet been able to make this work as desired.
The desired effect is that for all rows 5 and higher, where A is not null, a border should be applied to all cells in columns A to M. The sheet is called 'Kit check list', and the script should be triggered any timean edit is made to the sheet.
Here is the my attempt so far
function onEdit() {
GroupMyData(); // trigger this function when edits are made
}
function GroupMyData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Kit check list'); // apply to sheet name only
var rows = sheet.getRange('A5:M'); // range to apply formatting to
var numRows = rows.getNumRows(); // no. of rows in the range named above
var values = rows.getValues(); // array of values in the range named above
var testvalues = sheet.getRange('a5:a').getValues(); // array of values to be tested (1st column of the range named above)
rows.setBorder(false, false, false, false, false, false, "black", SpreadsheetApp.BorderStyle.SOLID); // remove existing borders before applying rule below
//Logger.log(numRows);
for (var i = 0; i <= numRows - 1; i++) {
var n = i + 1;
//Logger.log(n);
//Logger.log(testvalues[i] > 0);
//Logger.log(testvalues[i]);
if (testvalues[i] > 0) { // test applied to array of values
sheet.getRange('a' + n + ':m' + n).setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID); // format if true
}
}
};
Unfortunately all it only resets the borders in the specified area, and does not apply a borders to the desired rows.
Any help with this would be much appreciated.
Try this:
function onEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() == 'Kit check list') {
const sr = 5;
const rg = sh.getRange(sr, 1, sh.getLastRow() - sr + 1, sh.getLastColumn());
const vs = rg.getValues();
rg.setBorder(false, false, false, false, false, false, "black", SpreadsheetApp.BorderStyle.SOLID);
const numcolumns = sh.getLastColumn();
vs.forEach((r, i) => {
if (r[0]) {
sh.getRange(i + sr, 1, 1, numcolumns).setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID);
}
});
}
}
Demo:
Note: you cannot run this function without providing the event object which populates the e. The only reasonable way to test it is to set it up and save it and edit the sheet.
You might actually like it better this way:
function onEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() == 'Kit check list') {
const sr = 5;
const rg = sh.getRange(sr, 1, sh.getLastRow() - sr + 1, sh.getLastColumn());
const vs = rg.getValues();
//rg.setBorder(false, false, false, false, false, false, "black", SpreadsheetApp.BorderStyle.SOLID);
const numcolumns = sh.getLastColumn();
vs.forEach((r, i) => {
if (r[0]) {
sh.getRange(i + sr, 1, 1, numcolumns).setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID);
} else {
sh.getRange(i + sr, 1, 1, numcolumns).setBorder(false, false, false, false, false, false, "black", SpreadsheetApp.BorderStyle.SOLID);
}
});
}
}
Your script works fine. I just fixed one line.
Instead of this:
var n = i + 1;
You need:
var n = i + 5;
Here is the code:
function onEdit() {
GroupMyData(); // trigger this function when edits are made
}
function GroupMyData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Kit check list'); // apply to sheet name only
var rows = sheet.getRange('A5:M'); // range to apply formatting to
var numRows = rows.getNumRows(); // no. of rows in the range named above
var values = rows.getValues(); // array of values in the range named above
var testvalues = sheet.getRange('A5:A').getValues(); // array of values to be tested (1st column of the range named above)
rows.setBorder(false, false, false, false, false, false, "black", SpreadsheetApp.BorderStyle.SOLID); // remove existing borders before applying rule below
for (var i=0; i <= numRows-1; i++) {
var n = i + 5;
//Logger.log(n);
//Logger.log(testvalues[i] > 0);
//Logger.log(testvalues[i]);
if (testvalues[i] > 0) { // test applied to array of values
sheet.getRange('A' + n + ':M' + n).setBorder(true, true, true, true, true, true, "black", SpreadsheetApp.BorderStyle.SOLID); // format if true
}
}
};
without any script, you can do it by first using conditional formatting in MS Excel, then importing the workbook into google sheets ! weird ...

How to append an html table to a sheet

This script sends the data content of an html table to a Google Sheet.
But I now need it to append the data to the next available row.
I've used appendRow() in many cases, but I'm not sure of the syntax in this particular case.
function pasteRequisicaoHtml(table) {
var ss = SpreadsheetApp.openById("1J_7GZ1C7pgHuRsdfsdfsdfsdf");
var sheet = ss.getSheetByName('Sheet5').getSheetId();
var req = {
requests: [
{
pasteData: {
html: true,
data: table,
coordinate: {
sheetId: sheet,
rowIndex: 2,
columnIndex: 0,
},
},
},
],
};
Sheets.Spreadsheets.batchUpdate(req, ss.getId());
}
You want to put a HTML table to "the next available row" using Sheets API with Google Apps Script as appending.
If my understanding is correct, how about this answer?
Modification point:
In your case, you can use both Sheets API and Spreadsheet service. Using this, in order to append the table using Sheets API, you can use getLastRow() of Spreadsheet service. And please use the value retrieved by getLastRow() to rowIndex.
When this is reflected to your script, it becomes as follows.
Modified script:
function pasteRequisicaoHtml(table) {
var ss = SpreadsheetApp.openById("1J_7GZ1C7pgHuRsdfsdfsdfsdf");
var sheet = ss.getSheetByName('Sheet5'); // Modified
var req = {
requests: [{
pasteData: {
html: true,
data: table,
coordinate: {
sheetId: sheet.getSheetId(), // Modified
rowIndex: sheet.getLastRow(), // Modified
columnIndex: 0,
},
},
}, ],
};
Sheets.Spreadsheets.batchUpdate(req, ss.getId());
}
References:
getLastRow()
GridCoordinate
Added:
In this sample script, the header row is deleted after the table is append. In this case, it supposes that the header row is one row.
function pasteRequisicaoHtml(table) {
var ss = SpreadsheetApp.openById("1J_7GZ1C7pgHuRsdfsdfsdfsdf");
var sheet = ss.getSheetByName('Sheet5'); // Modified
var lastRow = sheet.getLastRow(); // Added
var req = {
requests: [{
pasteData: {
html: true,
data: table,
coordinate: {
sheetId: sheet.getSheetId(), // Modified
rowIndex: lastRow, // Modified
columnIndex: 0,
},
},
}, ],
};
Sheets.Spreadsheets.batchUpdate(req, ss.getId());
sheet.deleteRow(lastRow + 1); // Added
}

Define whole column in API range specification

I can use below syntax to refer whole column A,B and C:
A1:C
Below script will refer to full available cells!
var myRange = {
'sheetId': sheet.getSheetId(),
'startRowIndex': 0,
'endRowIndex': sheet.getLastRow(),
'startColumnIndex': 0,
'endColumnIndex': sheet.getLastColumn()
}
If user insert a new line, this range will not cover it. How to change it to support whole column just like A1:C?
Full script as below:
function addConditonalFormat() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getActiveSheet()
sheet.clearConditionalFormatRules()
var colorMerged = {'red': 222/255, 'green': 235/255, 'blue': 246/255, 'alpha': 0.7}
var colorSkipped = {'red': 222/255, 'green': 235/255, 'blue': 0, 'alpha': 0.7}
var myRange = {
'sheetId': sheet.getSheetId(),
'startRowIndex': 0,
'endRowIndex': sheet.getLastRow(),
'startColumnIndex': 0,
'endColumnIndex': sheet.getLastColumn()
}
var config = [["merged",colorMerged],["skipped",colorSkipped]]
var requests = []
for (var i=0;i<config.length;i++) {
var row = config[i]
var keyword = row[0]
var color = row[1]
Logger.log(keyword + ":" + color)
var cond = {'addConditionalFormatRule': {
'index': 0,
'rule': {
'ranges': [ myRange ],
'booleanRule': {
'format': {'backgroundColor': color},
'condition': {
'type': 'CUSTOM_FORMULA',
'values':[{'userEnteredValue': '=$A:$A="' + keyword + '"'}]},},},} }
requests.push(cond)
}
var format_req = {
'requests': requests,
'includeSpreadsheetInResponse': false,
}
Sheets.Spreadsheets.batchUpdate(JSON.stringify(format_req), ss.getId())
}
After run the script, then insert rows after last row, the conditional format will not apply to the new added rows!
Simple: to refer to the entirety of the sheet, do not supply any index specifications. Per the DimensionRange and GridRange documentation, missing indices indicate an unbounded specification.
const theWholeSheet = {
sheetId: sheet.getSheetId()
};
const noFirstRowOrFirstCol = {
sheetId: sheet.getSheetId(),
startColumnIndex: 1,
startRowIndex: 1
};