I'm fairly new to google sheets so I apologise in advance if this seems too basic.
My macro seemed to work fine on computers, I assigned it to a 'shape' button but since it needs to also be functional on a ipad, I searched about it and the answer found was to use an onEdit(e) trigger and use checkbox to set it up.
My issue now is that there's no assign button to have the macro attributed to the checkbox when it's checked :')
I have no issue sharing the script if needed because it's a very simple one.
A checkbox is just a True or False value in a cell, checking/unchecking it triggers the onEdit(e) function. You just need to check the location of the checkbox and it's value to execute the macro.
Sample:
function onEdit(e) {
if (e.range.getA1Notation == "A1") {
if (e.range.getValue == true) {
// execute something
}
else {
// execute something else
}
}
}
Given that the code works, CarlosM's provided answer is already almost correct.
I'll just have to combine it together with your macro
Code:
function onEdit(e) {
// Update if your checkBox is located somewhere else
var checkBoxLocation = "A1";
// Change to false if you want to run the macro when checkBox is unticked
var checkBoxCondition = true;
// Since getA1Notation and getValue are both methods
// We need to add () for them to work
if (e.range.getA1Notation() == checkBoxLocation) {
if (e.range.getValue() == checkBoxCondition) {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('D2').activate();
spreadsheet.duplicateActiveSheet();
spreadsheet.getActiveSheet().setName('Estimate ');
spreadsheet.getActiveSheet().setFrozenRows(0);
var sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).activate();
sheet = spreadsheet.getActiveSheet();
sheet.getRange(1, 1, sheet.getMaxRows(), sheet.getMaxColumns()).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
spreadsheet.getRange('E7').activate();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Clients List'), true);
spreadsheet.deleteActiveSheet();
spreadsheet.deleteActiveSheet();
spreadsheet.getRange('A39:H39').activate();
}
}
}
The code above does execute your macro if the conditions are met. These conditions are:
The checkBox location is found in variable checkBoxLocation
The checkBox was ticked, this will execute your macro
To quickly check the behavior of the logic of your script, kindly try this one. Make sure to have a checkBox in A1 before trying the code.
Test Code:
function onEdit(e) {
var checkBoxLocation = "A1";
var checkBoxCondition = true;
if (e.range.getA1Notation() == checkBoxLocation) {
var spreadsheet = SpreadsheetApp.getActive();
var cell = spreadsheet.getRange('D2');
if (e.range.getValue() == checkBoxCondition) {
cell.setValue("A1 checkbox is ticked");
}
else {
cell.setValue("A1 checkbox is unticked");
}
}
}
Related
I've seen many similar questions like this asked, but I'm still stumped.
I want an onEdit script to only work on a specific tab. I've tried several things but none of them are working correctly.
The tab on my sheet is called 'WEB Graffiti'. I want to run this script on other tabs on my sheet, but the columns are in different orders. I know how to edit the script to edit different columns but I don't know how to make it only work on the specified tab.
Here is the script I'm using.
function onEdit(e) {
if (!e) {
throw new Error(
);
}
indirectTimestamp_(e);
}
/**
* Inserts a timestamp in column T when column B is edited
* and column C contains the value TRUE.
*
* #param {testing} e The onEdit() event object.
*/
function indirectTimestamp_(e) {
if (e.range.columnStart !== 2
|| e.range.offset(0, 1).getDisplayValue() !== 'TRUE') {
return;
}
const timestampCell = e.range.offset(0, 18);
timestampCell.setValue(new Date()).setNumberFormat('mmm" "d" "yyyy');
};
I tried adding
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('WEB Graffiti'), true);
I tried this and several variations in various locations of the script and it was not working properly.
It's not clear if you want to only EDIT WEB Graffiti, or only run the procedure when that WEB Graffiti is EDITED. OnEdit will always run, the only thing you can do is scope it to make changes based on where the edit was conducted.
The below code of yours will only execute the indirect function when the WEB Graffiti sheet is edited.
function onEdit(e) {
var myRange = e.range;
var theSheetName = myRange.getSheet().getName();
if (!e) {
throw new Error(
);
}
if(theSheetName == 'WEB Graffiti'){
indirectTimestamp_(e);
}
}
Do this for Sheet1
function onEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == "Sheet1") {
//perform rest of your code which is for sheet1
}
}
I have been making a google sheets document with buttons to make it more easy to use. This sheet will need to be used on my mobile phone. This is why I am using the drop down button with a onEdit(e) function in apps script. The point of the button is as follows:
I can click it on my phone and then I will get to choose a set of pre defined numbers. In this case : invoer,-2,-1,1,2,3,4,5,6. When a selection is made, the chosen number will be added to the value in a specific cell. The code looks like this:
function onEdit(e) { *calls the function HVBBplus() when the cell J2 is edited
if (!e) {
}
if (e.range.getA1Notation() !== 'J2') {
return;
}
HVBBplus()
}
function HVBBplus(){
var spreadsheet = SpreadsheetApp.getActive();
var invoer = spreadsheet.getRange('J2').getValue();
var output = spreadsheet.getRange('K2').getValue();
spreadsheet.getRange('K2').setValue(invoer+output);
spreadsheet.getRange('J2').setValue("Invoer");
}
This works perfectly, but the problem is that I cannot figure out how to create multiple buttons with different codes. When I copy and paste the function onEdit, it will only run the second onEdit function and it will ignore the first one. Can someone please help me with this problem and maybe explain how this piece of code works exactly?
Basically it could be something like this:
function onEdit(e) {
if (e.range.getA1Notation() == 'J2') HVBBplus();
if (e.range.getA1Notation() == 'J3') HVBBplus2();
if (e.range.getA1Notation() == 'J4') HVBBplus3();
}
function HVBBplus(){
var spreadsheet = SpreadsheetApp.getActive();
var invoer = spreadsheet.getRange('J2').getValue();
var output = spreadsheet.getRange('K2').getValue();
spreadsheet.getRange('K2').setValue(invoer+output);
spreadsheet.getRange('J2').setValue("Invoer");
}
function HVBBplus2(){
// do something
}
function HVBBplus3(){
// do something
}
The code can be improved if you describe what the 'buttons' you have and what exactly they supposed to do.
Just in case the same onEdit() function can be written with switch/case statement:
function onEdit(e) {
switch (e.range.getA1Notation()) {
case ('J2'): HVBBplus(); break;
case ('J3'): HVBBplus2(); break;
case ('J4'): HVBBplus3(); break;
}
}
Update
The obvious optimization could be to add arguments into the function HVBBplus():
function onEdit(e) {
switch (e.range.getA1Notation()) {
case ('J2'): HVBBplus('J2','K2'); break;
case ('J3'): HVBBplus('J3','K3'); break;
case ('J4'): HVBBplus('J4','K4'); break;
}
}
function HVBBplus(cell1, cell2){
var spreadsheet = SpreadsheetApp.getActive();
var invoer = spreadsheet.getRange(cell1).getValue();
var output = spreadsheet.getRange(cell2).getValue();
spreadsheet.getRange(cell2).setValue(invoer+output);
spreadsheet.getRange(cell1).setValue("Invoer");
}
As a guess. I don't know your goal.
My script works perfectly when I execute it manually through the editor but fails to fire with the edit or change trigger.
I saw a bunch of people having the same problem but none of these solutions help me solving this issue.
Has anybody a solution for this ?
function createNewSheets() {
// 1. Retrieve the current sheet names.
var dataSheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetNames = dataSheet.getSheets().map(s => s.getSheetName());
// 2. Retrieve the values from "mastersheet" sheet.
var masterSheet = dataSheet.getSheetByName('Liste de nageurs');
var values = masterSheet.getRange('A2:B' + masterSheet.getLastRow()).getValues();
// 3. Using the retrieved sheet names and values, the new sheets are inserted and the values are put.
values.forEach(r => {
if (!sheetNames.includes(r[0])) {
var newSheet = dataSheet.insertSheet(r[0])
sheetNames.push(r[0]);
newSheet.appendRow(r);
}
});
}
I ran it this way, using a checkbox in A1:
function onEdit(e) {
//e.source.toast('entry');//just a toast to let me know it's work
const sh = e.range.getSheet();// getting sheet name
//next line limits execution to Sheet1 A1 being changed to 'TRUE'
if (sh.getName() == 'Sheet1' && e.range.columnStart == 1 && e.range.rowStart == 1 && e.value == 'TRUE') {
e.range.setValue('FALSE');//reset the checkbox back to 'FALSE'
//the rest is your code
var ss = SpreadsheetApp.getActive();
var names = ss.getSheets().map(s => s.getSheetName());
var masterSheet = ss.getSheetByName('Sheet2');//changed sheet name
var vs = masterSheet.getRange('A2:B' + masterSheet.getLastRow()).getValues();
vs.forEach(r => {
if (!names.includes(r[0])) {
var newSheet = ss.insertSheet(r[0])
names.push(r[0]);
newSheet.appendRow(r);
}
});
}
}
You can simplify your code if you learn how to use the event object better but I left most of your code intact. The problem that most users dislike about using the event object is that you can't debug the code by running it from the script editor because you have to supply the event object as a parameter. I normally debug them but running them from the trigger. You can use JSON.stringify(e) to look at the event object.
Using the event object normally results in faster code and simple triggers must finish in 30 seconds or less.
I cannot get the below to work. Any help would be appreciated. I posted a similar post which I had some great assistance with, however when I apply the same concepts here I cannot get it to work. Thank you.
/** #OnlyCurrentDoc */
function onEdit(e) {
//This IF statement ensures that this onEdit macro only runs when cells A1:A2 are edited
if (
e.source.getSheetName() == "Finances 2020" &&
e.range.getColumn() == 1 &&
1<=e.range.getRow()<=2
) {
//Cells A1:A2 are checkboxes. This section ensures the following script only runs when the checkbox is checked (and not when unchecked).
var checkboxtest = e.range.getValue()
if (checkboxtest == true) {
//Some script to test if the above works (by grabbing some text from a cell near by and pasting it into another):
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var test = spreadsheet.getRange(3, 3).getValues();
spreadsheet.getRange('A3').setValues(test);
}
}
}
;
You haven't defined a sheet for getRange(3, 3), so your code is silently failing. Try running just that portion of your script and you'll see what I mean.
function test() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var test = spreadsheet.getRange(3, 3).getValues();
Logger.log(test); // Error: Cannot find method getRange(number,number).
}
You can easily resolve this by defining a sheet. I'm not sure if you want to use the active sheet or not, but I'll assume you do. So your code could look like this, and it works.
/** #OnlyCurrentDoc */
function onEdit(e) {
//This IF statement ensures that this onEdit macro only runs when cells A1:A2 are edited
if (
e.source.getSheetName() == "Finances 2020" &&
e.range.getColumn() == 1 &&
1<=e.range.getRow()<=2
) {
//Cells A1:A2 are checkboxes. This section ensures the following script only runs when the checkbox is checked (and not when unchecked).
var checkboxtest = e.range.getValue()
if (checkboxtest == true) {
//Some script to test if the above works (by grabbing some text from a cell near by and pasting it into another):
var sheet = SpreadsheetApp.getActiveSheet();
var test = sheet.getRange(3, 3).getValues();
sheet.getRange('A3').setValues(test);
}
}
}
Anyone who can help me with this?
Why my codes wont work in formulated cell?
I want to run my codes in formulated cell like vlookup
Is there a way to solve this problem?
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheets()[0]; // 0 == first sheet.
var ee = ss.getActiveRange().getA1Notation();
if (ee == "A1") { // Check if edited cell is the one we're watching.
if (e.value == "DONE"){ // If the value == "DONE", do stuff.
var toggle = sh.getRange("A1:M1");
for(var i=0;i<50;i++) {
if( i%2 == 0 )
toggle.setBackground("GOLD");
else
toggle.setBackground("WHITE");
SpreadsheetApp.flush();
Utilities.sleep(500);
}
}
}
}
On edit and on change triggers only are fired by changes directly made by the user, not when the result of a formula changes or a change is made by code.
Use conditional formatting instead.