How to get all checked cells from checkboxes in google apps script? - google-apps-script

I have a goolesheets that contains checkboxes. I would like to get all checked cells using google apps script. For example, as below picture, I would like to get a result of 'A3', 'A6' and 'A9'.
I tried many different ways and I found a script below but it only gives me the last cell, which is 'A9'.
Any ideas or suggestions would be much appreciated.
var range = '';
var sel = SpreadsheetApp.getActive().getSelection().getActiveRangeList().getRanges();
for(var i = 0; i < sel.length; i++){
range += sel[i].getA1Notation() + ', ';
}
Logger.log(range);

Explanation:
Your current solution uses getSelection which means if you select the desired cells manually:
you will get A3, A9, A6, which based on your code is the correct answer. Although, I guess you don't want to manually select them, otherwise it wouldn't make sense to use a script to find them.
Side Note:
If you want to use that solution, I assume you want A3, A9, A6 instead of A3, A9, A6, so this would make more sense:
function myFunction() {
const sel = SpreadsheetApp.getActive().getSelection().getActiveRangeList().getRanges();
const range = [];
for(var i = 0; i < sel.length; i++){
range.push(sel[i].getA1Notation());
}
Logger.log(range.join(', '));
}
assuming again you have selected the checkboxes as in the screenshot.
Solution:
In the below solution, adjust Sheet1 to the name of your sheet.
function myFunction() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet1'); // put the name of your sheet here
const colA = sh.getRange('A1:A'+sh.getLastRow()).getValues().flat();
const range=colA.map((c,i)=>c==true?`A${i+1}`:'').filter(c=>c!='').join(', ');
Logger.log(range); // A3, A6, A9
}
In this solution, we are getting all the values of column A, then using map we get the cell reference of the true cells (checkbox is clicked) and then filtering on these values.

I tried replicating your scenario and did some changes in your code specifically in the declaration of the sheet and data range to be checked. For the solution, I changed your loop and added a condition inside to check for true(ticked checkbox) values.
Please see my code below. This is working fine on my end. Note that this is assuming that you only have your checkboxes on column A.
function myFunction() {
var range = '';
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Sheet1');
var val = sheet.getRange(1,1,sheet.getLastRow(), 1).getValues();
for(row in val){
if(val[row][0]==true){
range += 'A'+ (parseInt(row) + 1) + ',';
}
}
Logger.log(range);
}

Related

How do I automatically create checkbox in Google Sheets if X

I have a Google Sheet file linked to a Google Form, that I use to record registrations for classes by different teachers. Inside of it I create extra columns that mark "X" in a row, when someone registers for that particular class, using an =IF function. I'd like those "X"'s to be checkboxes so that I can check attendees in the sheet itself as they arrive, but there is no method I can find for a function to output a tickbox into the cell and I have next to no knowledge of JavaScript.
Example Sheet: https://docs.google.com/spreadsheets/d/19BUkEfo8dWcAfPDhmhBTuhC1-V-QROlfF0pWH75c9VA/edit?usp=sharing
Ideally, I'd have a custom function that basically does the same as my =IF but inserts a checkbox instead of writing "X" (ie. if cell A contains text from cell B insert checkbox, else leave empty).
Alternatively I also found this solution to a similar problem, that I think would work, but I don't know enough to tweak it to my needs. This way I'd keep my sheet as is and the script would just replace the X's with checkboxes?
Probably it is not very efficient but it works:
// function creates menu 'SCRIPTS'
function onOpen() {
SpreadsheetApp.getUi().createMenu('SCRIPTS')
.addItem('Insert checkboxes', 'replace_x_to_checkboxes')
.addToUi();
}
// function replaces all 'X' on the sheet with checkboxes
function replace_x_to_checkboxes() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getDataRange();
var data = range.getValues();
for (var row in data)
for (var col in data[row]) {
if (data[row][col] == 'X') sheet.getRange(+row+1,+col+1).insertCheckboxes()
}
}
To insert checkboxes without using formulas and 'X's you can run this function:
function insert_checkboxes() {
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange().getValues();
var b1 = data[0][1]; // name from cell 'B1'
var c1 = data[0][2]; // name from cell 'C1'
for (var row=1; row<data.length; row++) {
if (data[row][3].indexOf(b1) > -1) sheet.getRange(row+1,2).insertCheckboxes();
if (data[row][3].indexOf(c1) > -1) sheet.getRange(row+1,3).insertCheckboxes();
}
}
Just in case. Instead of data[row][3].indexOf(b1) > -1 you can use a modern variant of the same condition data[row][3].includes(b1))

Get notes from a cell and insert into another cell

I have a range of cells in Google Sheets, some of them have notes attached.
If there's a note attached to a cell, I need to put the note in a separate cell, and put the location of that note in another cell.
I found this script elsewhere:
function getNote(cell)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange(cell)
return range.getNote();
}
but when I try to use it I get an error "Exception: Range not found (line 12)."
But this script only gets me halfway there as it only gets the note and puts it in a cell. I also need to know what cell the note came from.
Any help is greatly appreciated.
In the script above the function getNote() expects the paramter cell
If you just run the script without calling getNote() from another function / an environment where it gets a values for cell assigned, the script will fail wiht the error you obtained.
Indeed, this script doe snot not meet your needs. What you probably want is to screen all your cells for the one that have notes.
What you need to decide is into which cells you want to put the note and the cell notation.
Below is a sample that you need to adapt for your needs:
function getNotes() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
//if you have only one sheet in the spreadsheet, otherwise use ss.getSheetByName(name);
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
var results = range.getNotes();
for (var i = 0; i < results.length; i++) {
for (var j = 0; j < results[0].length; j++) {
//if a not empty note was found:
if(results[i][j]){
var note = results[i][j];
var cell = range.getCell(i+1, j+1);
var notation = cell.getA1Notation();
//adjust the offset as function of the column / row where you want to output the results
cell.offset(0, 1).setValue(note);
cell.offset(0, 2).setValue(notation);
}
}
}
}
Important references:
getNotes()
getA1Notation()
getDataRange()
getCell(row, column)
offset(rowOffset, columnOffset)

How to speed up COLUMNS deleting function in Google App Script

I am working through data in Google sheets, attempting to delete EMPTY COLUMNS based I have 600 so it take too much time
Any suggestions on how to speed this up?
Here is my code :
function delCols() {
var s = SpreadsheetApp.getActive().getActiveSheet()
var c = 600
var data = s.getRange(1, 1, 1, c).getValues()
Logger.log(data[0].length)
var delCol=0
for (var i = data[0].length; i >0 ; i--) {
if(s.getRange(1, c ).getValue() =="") { s.deleteColumn(c);delCol=delCol+1 }
c=c-1
}
s.insertColumns(600-delCol, delCol);
Logger.log(delCol)
}
Thank you in advance if you may help
Create a new sheet, for example "Sheet0", for intermediate data. It can be hidden.
Run this script function to remove empty columns from the active sheet:
function removeEmptyColumns() {
var ss = SpreadsheetApp.getActive();
var activeSheet = ss.getActiveSheet(),
sheet0 = ss.getSheetByName('Sheet0');
// AHG is 600-th column (if I am not mistaken)
var formula = "=TRANSPOSE(QUERY(TRANSPOSE('" + activeSheet.getName() +
"'!A:AHG); \"select * where Col1 is not null\"; 0))";
sheet0.getRange('A1').setFormula(formula);
SpreadsheetApp.flush();
var values = sheet0.getDataRange().getValues();
sheet0.getRange('A1').clear();
activeSheet.clearContents();
activeSheet.getRange(1, 1, values.length, values[0].length).setValues(values);
}
I believe it is faster, than column by column deletion. Some remarks:
There is a restriction for use of formulas on the active sheet, because we copy only values.
If you do not remove the formula in the script, then calculations will take place on every active cheet change, resulting in delays.
Please note, empty column detection is based on top cell value, as in your code.

Google Apps Script custom function for sheets - range not found

I have an issue that's likely due to my lacking understanding on how the getRange() function works.
I wrote two small functions to use in a Google Sheet, but I can't get cell references to work properly as input. Here is the code:
function getCellRGB(input, color) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cell = sheet.getRange(input);
var hex = cell.getBackground();
hex = hex.replace('#','');
if (color == "r") return parseInt(hex.substring(0,2), 16);
else if (color == "g") return parseInt(hex.substring(2,4), 16);
else if (color == "b") return parseInt(hex.substring(4,6), 16);
else return null;
}
This only works if I input like this:
getCellRGB("A1", "r")
if I attempt to use a normal cell reference like they are used in other functions:
getCellRGB(A1, "r")
I get the error "Range not found (line 6)"
The second function colors a cell from a R, G and B value in one cell each:
function setCellColorFromRGB(red,green,blue) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var r = sheet.getRange(red);
var g = sheet.getRange(green);
var b = sheet.getRange(blue);
cell.setBackgroundRGB(r, g, b)
}
I get the same error for this one, also line 6.
Change this line
var cell = sheet.getRange(input);
to
var cell = sheet.getRange('"' + input + '"');
and you should be putting quotes around the passed value. You should be able to do the same for the other lines.
The getRange() method accepts several different types of arguments. For one cell you have two choices: a string in the a1 notation or two integers counting starting at 1.
So:
//these are valid and will get the top left most cell
var cell = sheet.getRange('A1');
var cell = sheet.getRange(1,1);
//this is not valid
var willNotWork = sheet.getRange(A1);
After you get the cell, you also need to call .getValue(); to get the contents of the cell.
Thanks everyone for your efforts, I've actually managed myself to find the solutions to them. There were quite a few more mistakes than I thought.
First of all, the code for my first function:
function getCellRGB(sheet, row, col, color) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheet);
var cell = sheet.getRange(row, col);
var hex = cell.getBackground();
hex = hex.replace('#','');
if (color == "r") return parseInt(hex.substring(0,2), 16);
else if (color == "g") return parseInt(hex.substring(2,4), 16);
else if (color == "b") return parseInt(hex.substring(4,6), 16);
else return null;
}
Issue, input.
It turns out when you call a function in sheets like so:
=getCellRGB(Sheet1, A1, A1, "r")
A1 and B1 actually return the values of those cells, not the reference to the cells themselves. In fact, it doesn't look like there is a way to easily input a cell reference into a function. I solved this by doing the input like so:
=getCellRGB(Sheet1 ROW(A1), COL(A1), "r")
Which is more complicated but works and even allows me to "formula paste" in Sheets.
Input the sheet
It's necessary to input the sheet where the cell to take the RGB from is located as I wanted it to be possible for it to be on a different sheet in the spreadsheet, not just the same sheet.
issue the getRange() function
This one took a while since I thought the only way to use it is with a cell reference as a String - getRange("A1"). While that is one way of doing it, it's also possible to input a row and column instead, to input which there are the defaul ROW() and COL() functions. That worked.
So this code works and I've used it to output the correct variables, but the issue is it turns out I was actually looking for a constantly running script since the RGB values were supposed to be read and output constantly instead of just once on entering the function. That made a different code entirely necessary which is really a different topic but since it may help people having the same realization, here it is:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var edit = ss.getSheetByName("Edit");
var calculation = ss.getSheetByName("Calculation");
var listenRange = edit.getRange("M2:M");
var applyRange = calculation.getRange("D2:F");
if (e.source.getSheetName() != "Edit") {
//ss.toast('nopeSheet' + ":" + e.source.getSheetName());
return;
}
var row = e.range.getRow();
if (row < 2) {
// ss.toast('nopeRow' + ":" + row);
return;
}
var col = e.range.getColumn();
if (col < 10 || col > 10) {
// ss.toast('nopeCol' + ":" + col);
return;
}
var row = e.range.getRow();
var col = e.range.getColumn();
var cell = edit.getRange(row,col);
var hex = cell.getBackground();
hex = hex.replace('#','');
var red = parseInt(hex.substring(0,2), 16);
var green = parseInt(hex.substring(2,4), 16);
var blue = parseInt(hex.substring(4,6), 16);
var redCell = calculation.getRange("D" + row);
redCell.setValue(red);
var greenCell = calculation.getRange("E" + row);
greenCell.setValue(green);
var blueCell = calculation.getRange("F" + row);
blueCell.setValue(blue);
}
There's some commented out debug code in there but otherwise this works with the exception of not triggering properly because the change of a background color apparently doesn't trigger onEdit. A fatal flaw but again, topic for another question and for everything but the color change this will work.
I've also hardcoded the sheet references and ranges but since I'm going to only use it for this sheet specifically that should be no issue.
Secondly regarding my other original piece of code - setting the background color of a cell based on RGB values in different cells. This turned out to be a major issue since changing a cells background color based on values in another cell is apparently not allowed for a function. I've managed to get around it with these two functions:
function rgbToHex(r,g,b) {
var r = parseInt(r);
var g = parseInt(g);
var b = parseInt(b);
if (g !== undefined)
return Number(0x1000000 + r*0x10000 + g*0x100 + b).toString(16).substring(1);
else
return Number(0x1000000 + r[0]*0x10000 + r[1]*0x100 + r[2]).toString(16).substring(1);
}
source: How to convert decimal to hex in JavaScript?
function setBgColor() {
var s = SpreadsheetApp.getActive().getSheetByName("Calculation");
var targetrange = s.getRange('L2:L').setBackgrounds(s.getRange('K2:K').getValues());
}
source: https://productforums.google.com/forum/#!topic/docs/88lWZY7WDZI
Since I only needed this as a one-time function, this worked well but it could possibly be converted to work differently as well.

going through each cell in a column and reset its value if >0

When I open a google sheet, I'd like all values within one specific column to be reset to 0 if its value is >0.
Please note that some cells contain no data, I wouldn't like to mess up with these cells as they should stay empty.
At the moment I'm really trying to build up an MVP so if I have to hardcode the value of the column within the formula it's OK.
I've made some research and tried to find relevant examples here, I've tweaked one snippet which works for one specific cell, now I'd like to learn how to automate the execution of this script so I don't have to hardcode each cell....
Here is the script I have
function onOpen() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
var cell = doc.getRange("B4");
var value = cell.getValue();
if (value > 0) {
cell.setValue("0");
}
else {
cell.setValue("0");
}
}
I'd really appreciate if you could help me a bit with this one by either poiting me in the right direction or showing me a working example.
Thanks
This code works:
//function onOpen() {
function makeZero() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getSheetByName('Sheet 2');
var theLastRow = theSheet.getLastRow();
//Get all values from column A
var theColumnRng = theSheet.getRange(1, 1, theLastRow, 1);
//Get all the values from column A. The return from getValues()
//is a two dimensional array
var theColumnValues = theColumnRng.getValues();
var thisCellValue = "";
var i;
for (i=0;i<theColumnValues.length;i++) {
//Every inner array only has one element, therefore, index zero
thisCellValue = theColumnValues[i][0];
if (thisCellValue > 0) {
theColumnValues[i][0] = 0;
}; //No "else" condition needed. If not greater than zero, do nothing
};
//Reset the entire column's values all at once
theColumnRng.setValues(theColumnValues);
};
If you want to compare it with another column.
Please select sheet name, i (row ) number and col number accordingly (i,2) 2 is a col here. IF there is no col then put Val2=0 in your case. Also don't forget to edit the setValue also.
function ifelse_col_comparision(){
var ss= SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
for(var i=2;i<ss.getLastRow();i++){
var val1=ss.getRange(i,2).getValue();
var val2=ss.getRange(i,3).getValue();
if(val2 >= val1){ss.getRange(i,4).setValue('Bigger or 0');}
else{ss.getRange(i,4).setValue('lower or -1');}
}
}
Please ask if you are looking for something else.