Reset Checkboxes and Delete Notes on Defined sheets - google-apps-script

I need to reset checkboxes to FALSE (Unchecked) and also delete all notes from defined sheets.
Also need a script that deletes all notes from a Google sheet (all sheets)
I tried combining numerous different scripts.
https://webapps.stackexchange.com/questions/115076/how-to-run-script-on-multiple-google-sheet-tabs
Re-set checkboxes to false - Google Apps Script -- The problem with this script is that is turns cells with a value of 1 into cells that say "FALSE"
function ResetCheckBoxesAndClearNotesOnDefinedSheets(){
var tabs = [
'Checkboxes 1',
'Checkboxes 2',
'Checkboxes 3',
'Another Checkbox tab',
'Yet another checkbox tab'
];
//LOOP THROUGH TABS LISTED ABOVE
var ss=SpreadsheetApp.getActiveSpreadsheet();
for (var i = 0; i < tabs.length; i++) {
var sheet=ss.getSheetByName(tabs[i]);
//CLEAR NOTES ON TABS LISTED ABOVE
sheet.clearNotes();
// CLEAR CHECKBOXES ON TABS LISTED ABOVE
var dataRange = sheet.getRange('A:I');
var values = dataRange.getValues();
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
if (values[i][j] == true) {
values[i][j] = false; // Modified
}
}
}
dataRange.setValues(values);
}//end of sheets loop.
}
ACTUAL RESULTS:
-It does not loop through the pages and delete the notes. It also does not loop through and change all checkboxes in the tabs to unchecked.. and it sometimes replaces a "1" with a FALSE
EXPECTED RESULTS:
-Reset all checkboxes on defined sheets
-Clear all notes on Defined sheets (or entire Spreadsheet)

How about this modification?
Modification points:
In your script, the variable of i is used at both for (var i = 0; i < tabs.length; i++) { and for (var i = 0; i < values.length; i++) {.
By this, the value of i of for (var i = 0; i < tabs.length; i++) { is not increased every 1.
I think that this is one of your issues of It does not loop through the pages and delete the notes..
For example, please modify to for (var k = 0; k < tabs.length; k++) {var sheet=ss.getSheetByName(tabs[k]);.
Equality comparison == is used for comparing the boolean.
I think that this is another issue of it sometimes replaces a "1" with a FALSE.
Please modify this to the strict equality comparison ===.
Modified script:
Please modify as follows.
From:
for (var i = 0; i < tabs.length; i++) {
var sheet = ss.getSheetByName(tabs[i]);
To:
for (var k = 0; k < tabs.length; k++) {
var sheet = ss.getSheetByName(tabs[k]);
And
From:
if (values[i][j] == true) {
To:
if (values[i][j] === true) {
Reference:
Equality comparisons and sameness
If I misunderstood your question, please tell me. I would like to modify it.

Related

Delete all Sheets except one, loop within a loop

I have a spreadsheet that contains a list of URLS for spreadsheets and the sheet name that I want to keep.
The idea is that I delete all sheets within each of those spreadsheets except the sheet I want to keep.
I have written a script but I can not seem to get it to work, I get an error message of "invalid argument line 20" but I can not figure out why.
I have pasted my code below, any help would be appreciated.
function DeleteImportedData(){
var s3 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("URL's")
var s1 = SpreadsheetApp.getActiveSpreadsheet()
var sh1 = s1.getSheetByName("MasterSheet")
var copy = sh1.getRange(1,1,sh1.getLastRow(),sh1.getLastColumn()).getValues()
var getHeader = sh1.getRange(1,1,1,25).getValues()
for (var j = 1;j<s3.getLastRow(); j++){
var filterName = s3.getRange(j+1, 1).getValue()
var id = s3.getRange(j+1,2).getValue()
var open = SpreadsheetApp.openById(id)
var sheet = open.getSheets()[0];
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var sh3 = open.getSheetByName("STSOR - "+filterName)
}
for (i = 0; i <= sheets.length; i++) {
switch(sheets[i]) {
case sheet.getSheetName() === sh3:
break;
default:
open.setActiveSheet(sheet[i]);
open.deleteActiveSheet;
open.deleteSheet(del)
}
}
}
when you delete the first sheet from the list Sheet1, Sheet2, Sheet3 - Sheet2 changes its index to Sheet1. So it is better to delete sheets from the end
try to use the reverse loop
for (i = sheets.length-1; i >=0 ; i--){
... your code ...
}
There is something wrong between your variable sheet and sheets and your second loop.
Try this way :
for (var j = 1;j<s3.getLastRow(); j++){
// your code
// second loop inside the first loop
for (i = 0; i <= sheets.length; i++) {
switch(sheets[i]) {
case sheets[i].getSheetName() === sh3: //instead of 'sheet'
break;
default:
open.setActiveSheet(sheets[i]); //instead of 'sheet'
open.deleteActiveSheet;
open.deleteSheet(del)
}
} // close first loop
} // close second loop
but I think the second loop would be cleaner that way (IMHO):
for (i = 0; i <= sheets.length; i++) {
if (sheets[i].getSheetName() !== sh3) {
open.deleteSheet(sheets[i].getSheetName());
}
}
If this code doesn't answer your question, please provide more informations about your spreadsheets

Clear conditional formatting using Advanced Sheet Service in Google Apps script

I am trying to delete conditional formating of a range using below code:
var sheet = range.getSheet();
var address = range.getA1Notation();
var conditionalFormatRules = sheet.getConditionalFormatRules();
var conditionalFormatRule = [];
var sheetId = sheet.getSheetId();
for (let index = 0; index < conditionalFormatRules.length; index++) {
let ranges = conditionalFormatRules[index].getRanges();
for (let j = 0; j < ranges.length; j++) {
if (ranges[j].getA1Notation() == address) {
conditionalFormatRule.push({
"deleteConditionalFormatRule": {
"index": index,
"sheetId": sheetId
}
});
}
}
}
if (conditionalFormatRule.length > 0) {
var spreadsheet = SpreadsheetApp.getActive();
var ssId = spreadsheet.getId();
var format_req = {
"requests": conditionalFormatRule
};
Sheets.Spreadsheets.batchUpdate(format_req, ssId);
}
But it fails with the following exception:
{ [GoogleJsonResponseException: API call to sheets.spreadsheets.batchUpdate failed with error: Invalid requests[8].deleteConditionalFormatRule: No conditional format on sheet: 1876237346 at index: 8] name: 'GoogleJsonResponseException', details: { message: 'Invalid requests[8].deleteConditionalFormatRule: No conditional format on sheet: .... at index: 8', code: 400 } }
It says there is no conditional formatting at index: 8 but there are 11 conditional format rules for that particular range (confirmed by logging the conditional formatting rules)
I want to delete all the conditional formatting rules for a particular range if there is any better way please suggest.
Thanks in advance.
Solved the issue by using getConditionalFormatRules, clearConditionalFormatRules, and setConditionalFormatRules methods of Sheet class.
Get all conditional formatting rules and store it in a variable
existingRules.
Remove the rules from existingRules.
Concat new rules newRules and existingRules.
Clear all conditional formatting rules.
Set all conditional formatting rules allRules to the sheet again.
var existingRules = sheet.getConditionalFormatRules();
var removedRules = [];
for (let index = 0; index < existingRules.length; index++) {
let ranges = conditionalFormatRules[index].getRanges();
for (let j = 0; j < ranges.length; j++) {
if (ranges[j].getA1Notation() == address) {
removedRules.push(existingRules[index]);
}
}
}
for (var i = removedRules.length - 1; i >= 0; i--)
existingRules.splice(removedRules[i], 1);
var newRules = [] //skipping the logic to create new rules
var allRules = existingRules.concat(newRules);
//clear all rules first and then add again
sheet.clearConditionalFormatRules();
sheet.setConditionalFormatRules(allRules);
If you want to update/add new rules to one range, while preserving old rules in the sheet in different ranges, you can achieve that by changing the condition and skipping splicing in your code, like that:
var existingRules = sheet.getConditionalFormatRules();
var rulesToKeep = [];
var rangeToUpdate ="A1:B10"
for (let index = 0; index < existingRules.length; index++) {
let ranges = conditionalFormatRules[index].getRanges();
for (let j = 0; j < ranges.length; j++) {
if (ranges[j].getA1Notation() != rangeToUpdate.getA1Notation()) {
rulesToKeep.push(existingRules[index]);
}
}
}
var newRules = [] //skipping the logic to create new rules
var allRules = rulesToKeep.concat(newRules);
//clear all rules first and then add again
sheet.clearConditionalFormatRules();
sheet.setConditionalFormatRules(allRules);
Very important is to get getA1Notation() for both ranges for comparison, even if your range string is already in A1Notation()

Unchecking Checkboxes in Google Sheets

For the life of me I can't figure out how set it up. I would like the function to check the entire sheet... alternatively I do know which specific ranges (B5:B26; G5:G26...AF5:AF26) on a specific sheet, if i can't set it up for the entire sheet...
function setFalse()
{
var sheet = SpreadsheetApp.getSheetByName("Test");
var dataRange = sheet.getRange('A:AN28');
var values = dataRange.getValues();
for (var i = 0; i < values.length; i++)
{
for (var j = 0; j < values[i].length; j++)
{
if (values[i][j] == true)
{
values[i][j] = false; // Modified
}
}
}
dataRange.setValues(values);
};
There's a built-in method to uncheck called uncheck(). You can effectively apply it to the sheet by using getDataRange().
function setFalse() {
SpreadsheetApp.getActive().getSheetByName("Test").getDataRange().uncheck();
};
Lastly, looking at your original code, don't forget to get a spreadsheet file before selecting the sheet.

Refreshing custom function on every change

I have a custom function using DeveloperMetadata from other sheets in the workbook. The issue I have is that if I e.g. delete one of previous sheets (thus removing that metadata) the cell value doesn't change. The only trigger which recalculates this function is to make a simple whitespace change in the Script Editor and save the file.
Is there a method in Google Sheets to do this refresh automatically?
function get_prev_days(rest_key) {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheets = spreadsheet.getSheets();
var sheet_index = SpreadsheetApp.getActiveSheet().getIndex();
var value = 0;
for (var i = 0; i < sheet_index; i++) {
var meta = sheets[i].getDeveloperMetadata();
for (var j = 0; j < meta.length; j++) {
if (rest_key == meta[j].getKey()) {
value += Number(meta[j].getValue());
}
}
}
return value;
}

Delete Row from all google sheets based on value of a cell

I am trying to achieve a script that will delete a row based upon a string in a cell within that row,
I can achieve my mission if I want to name each individual sheet, however my sheets are constantly changing names, so this would mean updating the the script daily.
I have tried to create a loop, but that does not seem to work either, any suggestions?
The script I am working on is below.
function RemoveInvoiced() {
var ss = SpreadsheetApp.openById("1pxWr3jOYZbcwlFR7igpSWa9BKCa2tTeliE8FwFCRTcQ").getSheets();
for (var k=0; k<ss.length; k++)
var values = ss[k].getDataRange().getValues();
var rows_deleted = 0;
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
var value = values[i][j];
var row = i + 1 - rows_deleted;
if (typeof value === 'string') {
var result = value.search("INVOICED");
if (result !== -1) {
ss.deleteRow(row);
rows_deleted++;
}
}
}
}
};
Instead of using the sheet name to access them, you could access them by Id.
The id will never change as long as you don't delete the sheet, even if you change the name.
You'd first have to get the sheets Id, a simple function could do that for you
function getId(sheet){
Logger.log(sheet.getSheetId());
}
Once you have gotten your sheet ids, you can make a function that will open the right sheet by the ID
function openSheetById(doc, id){
var sheets = doc.getSheets();
for(var i = 0; i< sheets.length ; i++){
if( sheets[i].getSheetId() == id)
return sheets[i];
}
return false;
}
And then you can access the right sheet.
function myFunc(){
var doc = SpreadsheetApp.openById("1pxWr3jOYZbcwlFR7igpSWa9BKCa2tTeliE8FwFCRTcQ");
var id = // your id here
var sheet = openSheetById(doc, id);
if(sheet){
//do other stuffs
}
}