I have a Google spreadsheet where column A has checkboxes in each row. I have written a script to perform a function on all rows where the checkboxes are checked, but I want to add in at the end a reset function so that all checked boxes are unchecked again after the script is run.
I've tried using a for loop like this:
var dataRange = sheet.getRange('A3:A');
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].setValue(false);
}
}
}
But clearly this doesn't work as I get an error.
Does anyone know how this could be done?
How about this modification? I think that there are several solutions for your situation. So please think of this as one of them.
Modification points :
The reason of the issue is values[i].setValue(false);. values[i] is an array. Please use the range for setValue().
But to use setValue() in the for loop leads to higher cost. So in this modification, I used setValues().
Put "false" to values, if values[i][j] is "true".
Put the modified values to the sheet using setValues().
Modified script :
var dataRange = sheet.getRange('A3:A');
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); // Added
Reference :
setValue()
setValues()
If this was not what you want, please tell me. I would like to modify it.
Update:
You can now use range.uncheck() directly on the range
Alternatively, Since you want to uncheck everything in the range (and all of the range have checkboxes in them), just do:
sheet.getRange('A3:A').setValue(false);
without checking/looping.
By highlighting all the cells in the range that you want to "uncheck" hold Crtl and double tap the spacebar.
The remove-check-marks method is "uncheck"…
var range = SpreadsheetApp.getActive().getRange('A21:A59');
range.uncheck();
This solution posted above does reset all checkboxes;
however, it also unexpectedly changes cells with the value of 1 in it to FALSE.
I want to make a script to reset checkboxes on ALL sheets...
function resetCheckBoxesAllSheets() {
var ss = SpreadsheetApp.getActive();
var allsheets = ss.getSheets();
for (var s in allsheets){
var sheet=allsheets[s]
var dataRange = sheet.getRange('A4:Z100');
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.
}// end of function...
I have set one checkbox instead of caption as shown in the picture
I write a script for check the data range and check uncheck all accordingly.
Here is the script.
function onEdit(e){
Logger.log('OnEdit');
var range = e.range;
var cl = range.getColumn();
var rw = range.getRow();
Logger.log('Row = ' + rw + ' Column = ' + cl);
var ActiveSheet = ss.getActiveSheet();
if(ActiveSheet.getName() === 'Companies' && rw == 1 && cl == 5){
var isAllTrue = ActiveSheet.getRange(rw, cl).getValue();
if(isAllTrue == true){
var Avals = ActiveSheet.getRange("A1:A").getValues();
var Alast = Avals.filter(String).length;
ActiveSheet.getRange(2, 5, Number(Alast-1)).setValue(true);
}
else
{
var Avals = ActiveSheet.getRange("A1:A").getValues();
var Alast = Avals.filter(String).length;
ActiveSheet.getRange(2, 5, Number(Alast-1)).setValue(false);
}
}
}
Change sheet name as per your need.
Note: create onedit trigger for same function if not trigger auto.
Related
I want to search for a word in a certain column and then if the value exists, I want to copy the row below with its values and change the word to two different words.
My issue was in getting the found word row Number to insert a row below it.
function myFunction() {
var ss = SpreadsheetApp.openById("1fE404JUbw3aytlqtoht6FfrIhYhTpSe2MM5UDnBkFc4");
var sheet = ss.getSheets()[0]
let range = sheet.getDataRange();
var values = range.getValues();
var typeRange = sheet.getRange("E2:E");
var typeValues = typeRange.getValues();
var i;
for(i = 0; i <= lastRow ; i++){
for (let type of typeValues){
if (type == "Both"){
var bothRow = i+1;
}
//// var bothRow = sheet.getRange(i+1,1,1,typeValues[i].length);
//// ss.insertRowsAfter(bothRow, 1);
}
}
}
I have used alert to check and it inserted an infinite number of rows after row number 1.
function myFunction() {
let sheetui= SpreadsheetApp.getUi()
sheetui.createMenu("Rahaf Game")
.addItem("Stage 1", 'pop')
.addToUi();
// var ss = SpreadsheetApp.openById("1fE404JUbw3aytlqtoht6FfrIhYhTpSe2MM5UDnBkFc4");
// var sheet = ss.getSheets()[0]
// let range = sheet.getDataRange();
// var values = range.getValues();
// var typeRange = sheet.getRange("E2:E");
// var typeValues = typeRange.getValues();
}
function pop(){
//var ss = SpreadsheetApp.openById("1fE404JUbw3aytlqtoht6FfrIhYhTpSe2MM5UDnBkFc4");
var sheet = ss.getSheets()[0]
var typeRange = sheet.getRange("E2:E");
var typeValues = typeRange.getValues();
var lastRow = sheet.getLastRow();
var i;
for(i = 0; i <= lastRow ; i++){
for (let type of typeValues){
if (type == "Both"){
var bothRow = i+1;
ss.insertRowsAfter(bothRow, 1);
}
//// var bothRow = sheet.getRange(i+1,1,1,typeValues[i].length);
//// ss.insertRowsAfter(bothRow, 1);
}
}
}
Can someone please help in achieving the required result in inserting a row below and copy the values into it with changing the word into two words?
Answer:
.getValues() returns a 2D array of values and you are referencing it as if it is unidimentional.
Code fix:
You need to change your conditional such that the object you are checking is an array:
if (type == "Both"){
//code
}
Should be:
if (type == ["Both"]){
//code
}
Adding a row and copying the data to it:
You can add a row in a sheet after a given row with the insertRowsAfter() and use .getRange().setValues() to copy in the data:
for(var i = 0; i <= lastRow ; i++){
for (let type of typeValues){
if (type == ["Both"]){
var bothRow = i + 1;
ss.insertRowsAfter(bothRow, 1);
// increment lastRow as there is now one more row in the sheet
lastRow++;
// increment i as you want to skip the row you just copied!
i++;
var rangeToCopy = sheet.getRange(bothRow + ':' + bothRow).getValues();
sheet.getRange((bothRow + 1) + ':' + (bothRow + 1)).setValues(rangeToCopy);
}
}
}
Don't forget to increment lastRow by 1 if you add a new row so that your loop still reaches the end of the sheet.
References:
Class Range | Apps Script - Method getValues()
Related Questions:
Using Google Sheets scripts, why does my if statement always return false when comparing cell values?
I am trying to create two sheets: Sheet 1: a template into which a student will enter a translation of a word into a cell; Sheet 2: a key which checks it against all possible answers: The two sheets look like this:
Here is a Link To Show the Two Spreadsheets
I am trying to take the provided answer for each column in the template (A:1), and match it against all possible answers listed in the corresponding column in the key (if it matches anything between A:1:A:3 in the key). If there's a match, the font should change to green and it should move to the next column. If there's no match the font turns red before moving to the next column.
I've run the logger, and it seems like it iterates through the data from each sheet correctly. The problem seems to be in comparing the 2 columns.
var ui = SpreadsheetApp.getUi();
var ssA= SpreadsheetApp.getActiveSpreadsheet();
var worksheet = ssA.getSheetByName("Worksheet");
var rangeData = worksheet.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
var searchRange = worksheet.getRange(2, 2, lastRow-1, lastColumn-1);
var ssB = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/1jKuxXo6o5YJjSUrQmaHR0n1ydvw7PgUl29I9mtycF_g/edit#gid=0");
var worksheetB = ssB.getSheetByName("Key");
var rangeDataB = worksheetB.getDataRange();
var lastColumnB = rangeDataB.getLastColumn();
var lastRowB = rangeDataB.getLastRow();
var searchRangeB = worksheetB. getRange(2, 2, lastRowB -1, lastColumnB -1);
function onOpen(){
ui.createMenu("Check My Translation.")
.addItem("Check Set 1", "transcheck")
.addToUi()
function transcheck(){
//iterate through the two corresponding columns in template and reference sheet
for (i = 1; i < lastColumn; i++){
for (j = 1; j < lastRow; j++){
//create the ranges to be compared and store as vars. cell and cellB
var cell = searchRange.getCell(j,i).getValue();
var cellB = searchRangeB.getCell(j,i).getValue();
//check for matches, change font accordingly
if (cell[0] === cellB[0]){
worksheet.getRange(j+1,i+1).setFontColor("green");
}else if(cell[0] =! cellB[0]){
worksheet.getRange(j+1,i+1).setFontColor("red");
I don't get any error messages; it just doesn't match the cells/change colors correctly.
There are several } missing at the end of your code and the correct operator is != instead of =!. Also, as a user mentioned, getValue() function retrieves a single value and not an array as getValues() [1], which is the recommended function to use in this case to avoid hitting the Google quotas [2]:
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu("Check My Translation.")
.addItem("Check Set 1", "transcheck")
.addToUi()
}
function transcheck(){
var ssA= SpreadsheetApp.getActiveSpreadsheet();
var worksheet = ssA.getSheetByName("Worksheet");
var rangeData = worksheet.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
var searchRange = worksheet.getRange(2, 2, lastRow-1, lastColumn-1).getValues();
var worksheetB = ssA.getSheetByName("Key");
var rangeDataB = worksheetB.getDataRange();
var lastColumnB = rangeDataB.getLastColumn();
var lastRowB = rangeDataB.getLastRow();
var searchRangeB = worksheetB. getRange(2, 2, lastRowB -1, lastColumnB -1).getValues();
//iterate through the two corresponding columns in template and reference sheet
for (var i = 0; i < searchRange.length; i++){
for (var j = 0; j < searchRange[0].length; j++){
//create the ranges to be compared and store as vars. cell and cellB
var cell = searchRange[i][j];
var k = 0;
while(k<3) {
var cellB = searchRangeB[k][j];
//check for matches, change font accordingly
if (cell == cellB){
worksheet.getRange(i+2,j+2).setFontColor("green");
break;
}else if(cell != cellB){
worksheet.getRange(i+2,j+2).setFontColor("red");
}
k++
}
}
}
}
[1] https://developers.google.com/apps-script/reference/spreadsheet/range#getValues()
[2] https://developers.google.com/apps-script/guides/services/quotas
I want a script to highlight a cell if another cell is yesterday's date (then remove the previous highlights). I want the script to run whenever I open the spreadsheet and when I switch to another tab.
I originally just had the script run as a .setActiveSelection() or a .getRange("B:B").activate(), but it's easier to notice when the cell is highlighted. But then I have to remove the previous highlights.
I'm trying to get my function to work over all my sheets to highlight a cell (col E) in the same row if the date=today()-1 (col B) and remove the highlight in column E if the date (col B) < today()-1. Right now, I'm using a script to set the highlight and conditional formatting to remove any previous highlights. However, the script only runs on the active sheet, and either has to use the trigger onOpen or I have to set it to run every minute.
I found this solution saying I could use this in my code to run a loop through all my sheets (the first 6 tabs):
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (i = 0; i < 6; i++) {
var sheet = ss.getSheetByName(sheets[i]);
}
However, when I add it, I get an error message saying:
Cannot call method "getRange" of null
Should I just use conditional formatting to highlight a specific date and remove previous highlighting?
https://docs.google.com/spreadsheets/d/1oUPWWA8NbT6pYve3pFvBlKm7PNCj3XxnM020yp-rRHs/edit?usp=sharing
My full function:
function jumpToAmtEaten() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (i = 0; i < 6; i++) {
var sheet = ss.getSheetByName(sheets[i]);
var r = sheet.getRange("B:B");
var values = r.getValues();
var day = 24*3600*1000;
var today = parseInt((new Date().setHours(0,0,0,0))/day);
var ssdate;
for (var i=0; i<values.length; i++) {
try {
ssdate = values[i][0].getTime()/day;
}
catch(e) {
}
if (ssdate && Math.floor(ssdate) == today-1) {
sheet.setActiveRange(r.offset(i,3,1,1)).setBackground("yellow");
break;
}
}
}
}
When you call
var sheet = ss.getSheetByName(sheets[i]);
You're passing a a Sheet object to the method getSheetByName() instead of a name. Also you don't need to keep calling a getSheet method once you've already obtained them once. Try this instead:
function jumpToAmtEaten() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
for (var i = 0; i < sheets.length; i++) {
Logger.log("i = " + i);
var r = sheets[i].getRange("B3:B")
Logger.log("r = " + r.getA1Notation());
var values = r.getValues();
var day = 86400000;
var today = parseInt((new Date().setHours(0, 0, 0, 0)) / day);
var ssdate;
for (var j = 0; j < values.length; j++) {
try {
ssdate = values[j][0].getTime() / day;
}
catch(e) {
}
if (ssdate && Math.floor(ssdate) == today - 1) {
Logger.log(Math.floor(ssdate));
Logger.log(today);
Logger.log(i);
Logger.log(sheets[i]);
Logger.log(r.offset(j, 3, 1, 1).getA1Notation());
sheets[i].getRange(r.offset(j, 3, 1, 1).getA1Notation()).setBackground("yellow");
break;
}
}
}
}
Also you can't use the same counter variable in nested loops as you will increment it every time you complete an interation of either one.
I am trying to color format a row in a spreadsheet where I run a loop to check if any of the values is equal to 0 and if it is equal to 0 to color it red and if not color it red.
I know I can do it with conditional format but I need this to activate after I press a button included in the sheet, so I need a script added to the button.
I have managed to write this script but it seems it color only the last cell from the range.
Can you please tell me what am I doing wrong since I am new to coding.
function FormatColor() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Acontobetaling');
var range = sheet.getRange('D34:AA34');
var values = [];
var cell = [];
for (var i = 1; i <= 24; i=i+1)
cell = range.getCell(1, i)
values = cell.getValue();
if (values = '0') {
cell.setBackground('red');
} else {
cell.setBackground('green');
}
}
I made it work, if someone is having the same problem you can use this
Anyway if you can provide me with better or fast way to do it you are welcome to show me how :)
function CopyData() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Acontobetaling');
var rangeColor = sheet.getRange('D34:AA34');
var values = [];
var cell = [];
var colors = [];
for (var i = 1; i <= 24; i=i+1) {
cell = rangeColor.getCell(1, i);
values = cell.getValue();
if (values == '0') {
colors = cell.setBackground('red');
} else {
colors = cell.setBackground('green');
}
}
I have a function running in google script. However it does not finish, it enters the main loop and then it stops somewhere, no errors. If i look in the execution description it says server error wait a while and try again.
I tried running it several times but it keeps stalling, but each time the last values of i and j are different from the previous stall.
I really can't imagine that this is a real server error, it must be the code.
function start() {
var sheet1 = SpreadsheetApp.openByUrl("xx").getSheetByName('Blad1');
var sheet2 = SpreadsheetApp.openByUrl("xx").getSheetByName('Blad1');
var range1 = sheet1.getRange(1,1,54,26);
var range2 = sheet2.getRange(1,1,10,7);
var teller = 0;
for(var i = 1; i<=range1.getNumRows(); i++){
for(var j = 1; j<=range2.getNumRows(); j++){
Logger.log(i);
Logger.log(j);
if(range1.getCell(i, 8).getValue() == range2.getCell(j, 2).getValue() && range1.getCell(i, 16).getValue() == range2.getCell(j, 4).getValue() && range1.getCell(i, 19).getValue() == range2.getCell(j, 6).getValue()){
range1.getCell(i,25).setValue(range2.getCell(j, 7).getValue());
range2.getCell(j,1).setValue("Script")
teller++;
}
}
}
Logger.log(teller);
};
I imagine you are hitting the SpreadsheetApp api too much. Best practice is to load the data you need into the script and iterate over it. Using your script as an example:
function start() {
var sheet1 = SpreadsheetApp.openByUrl("xx").getSheetByName('Blad1');
var sheet2 = SpreadsheetApp.openByUrl("xx").getSheetByName('Blad1');
var range1 = sheet1.getRange(1,1,54,26);
var range2 = sheet2.getRange(1,1,10,7);
var data1 = range1.getValues();
var data2 = range2.getValues();
var teller = 0;
for(var i = 0, r = data1.length; i < r; i++){
for(var j = 1, c = data2.length; j < c; j++){
Logger.log(i);
Logger.log(j);
if(data1[i, 8] == data2[j, 2] && data1[i, 16] == data2[j, 4] && data1[i, 19] == data2[j, 6]){
range1.getCell(i,25).setValue(data2[j, 7]);
range2.getCell(j,1).setValue("Script")
teller++;
}
}
}
Logger.log(teller);
};