I have to check weather a certain property exists before I can run the function listed in the add-on menu for a google spreadsheet. Rather than creating a copy of the same check for each function I would like to create a single function that I can pass the function to run as a parameter. How can I do this?
Below is my non functioning test code, but you may get the idea.
function testRun(){
//in practicality this would be an add-on menu
test1Check('test1()');
}
function test1(){
Logger.log("Function Ran");
}
function test1Check(functionToRun){
var labels = PropertiesService.getDocumentProperties().getProperty('labels');
var ui = SpreadsheetApp.getUi(); // Same variations.
if (!labels) {
var result = ui.alert(
'You have not yet set up the page for gClassFolders',
'Would you like to do this now?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
setupGCF();
}
}
else {
functionToRun;
}
}
I had to remove the () from the parameter sent, and add () to the variable in the function.
function testRun(){
test1Check(test1);
}
function test1(){
Logger.log("Function Ran");
}
function test1Check(functionToRun){
var labels = PropertiesService.getDocumentProperties().getProperty('labels');
var ui = SpreadsheetApp.getUi(); // Same variations.
if (!labels) {
var result = ui.alert(
'You have not yet set up the page for gClassFolders',
'Would you like to do this now?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
setupGCF();
}
}
else {
functionToRun();
}
}
Related
I am new to Google sheets. Previously, I have some C++ Background.
I would like to write a custom code that performs the following:
Tick the checkbox
Confirmation message pops out
Yes affirms the check, no unticks the box.
In C, a function can only run once and it exits. How do I write a code in Google sheet whereby this code is constantly checking for the checkbox condition?
Is there some kind of conditional script running?
You could try using an OnEdit Trigger as suggested in the comments and check the value of the checkbox. Use the info here to check the value of the check box and then use some variant of this code to create your popup dialog box:
function showAlert() {
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.alert(
'Please confirm',
'Are you sure you want to continue?',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
ui.alert('Confirmation received.');
} else {
// User clicked "No" or X in the title bar.
ui.alert('Permission denied.');
}
}
function onEdit(e) {
const sh=e.range.getSheet();
if(sh.getName()=='Sheet14' && e.range.columnStart==1 && e.value=='TRUE') {
var resp=SpreadsheetApp.getUi().alert('Message', SpreadsheetApp.getUi().ButtonSet.YES_NO);
if(resp==SpreadsheetApp.getUi().Button.YES) {
return;
}else{
e.range.setValue('FALSE');
}
}
}
Animation:
Is this what you tried because it works for me:
function onEdit(e) {
const sh=e.range.getSheet();
if(sh.getName()=='Sheet14' && e.range.columnStart==1 && e.value=='TRUE') {
var resp=SpreadsheetApp.getUi().alert('Message', SpreadsheetApp.getUi().ButtonSet.YES_NO);
if(resp==SpreadsheetApp.getUi().Button.YES) {
SpreadsheetApp.getUi().alert('Is this what you tried. Because it works for me.')
return;
}else{
e.range.setValue('FALSE');
}
}
}
I am an absolute beginner and using some code from the documentation, I am trying to pass a user interface response to a variable and then place it on a sheet.
The response gets into the logger OK but only "Response from user" appears in the cell.
The piece of code is:
if (response.getSelectedButton() == ui.Button.YES) {
Logger.log('The user\'s name is %s.', response.getResponseText());
var name=response;
var target1 = tr.getRange(8, 25).activate(); // a test cell in sheet
target1.setValue(name);
} else if (response.getSelectedButton() == ui.Button.NO) {
Here's an example:
function gettingAResponse() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet1');
var resp=SpreadsheetApp.getUi().prompt("Are you ten feet tall?", SpreadsheetApp.getUi().ButtonSet.YES_NO_CANCEL);
if(resp.getSelectedButton()==SpreadsheetApp.getUi().Button.YES) {
SpreadsheetApp.getUi().alert('You pressed yes');
sh.getRange("E5:E6").setValues([["Your response is:"],[resp.getResponseText()]]);
}
if(resp.getSelectedButton()==SpreadsheetApp.getUi().Button.NO) {
SpreadsheetApp.getUi().alert("You pressed no.");
sh.getRange("E5:E6").setValues([["Your response is:"],[resp.getResponseText()]]);
}
if(resp.getSelectedButton()==SpreadsheetApp.getUi().Button.CANCEL) {
SpreadsheetApp.getUi().alert("You pressed cancel");
sh.getRange('E5:E6').clearContent();
}
}
Another Example
In your code, you are doing the following:
var name=response;
var target1 = tr.getRange(8, 25).activate(); // a test cell in sheet
target1.setValue(name);
However, if what you want, is to set the actual response value in your cell, you have to do it as follows (notice the difference in the first line):
var name=response.getResponseText();
var target1 = tr.getRange(8, 25).activate(); // a test cell in sheet
target1.setValue(name);
Further to that, I suggest that you evaluate whether you need the activate() function call, and that you check out the troubleshooting page in the documentation (it can save you lots of time!).
Reference
https://developers.google.com/apps-script/reference/base/prompt-response#getResponseText()
When I make double click the form submitted twice. It creates duplicated rows. How can I prevent double click ?
Thank you!
function doGet(e) {
//Logger.log( Utilities.jsonStringify(e) );
if (!e.parameter.page) {
// When no specific page requested, return "home page"
return HtmlService.createTemplateFromFile('employee').evaluate()
.setTitle('care backup').setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
// else, use page parameter to pick an html file from the script
return HtmlService.createTemplateFromFile(e.parameter['page']).evaluate()
.setTitle('care').setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
I have not tested this, but just an option- also Set a time based trigger to run function reset every so often?
var recentSubmit = 0;
function doGet(e) {
//Logger.log( Utilities.jsonStringify(e) );
if (recentSubmit = 0){
if (!e.parameter.page) {
var recentSubmit = 1;
// When no specific page requested, return "home page"
return HtmlService.createTemplateFromFile('employee').evaluate()
.setTitle('care backup').setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
// else, use page parameter to pick an html file from the script
return HtmlService.createTemplateFromFile(e.parameter['page']).evaluate()
.setTitle('care').setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
Logger.log("Submitted a form to recently, try again later...");
}
function reset() {
var recentSubmit = 0;
}
You can try using the createClientHandler.forEventSource().setEnabled(false). It can disable the submit button. It's deprecated but it still works for now.
Full code implementation sample is found in this SO post:
function onOpen() {
var app = UiApp.createApplication();
app.setTitle('My Title');
app.setHeight(150);
app.setWidth(300);
var form = app.createFormPanel();
var flow = app.createFlowPanel();
flow.add(app.createHidden("action", 'action'));
flow.add(app.createLabel('My Label'));
//Submit
var submit = app.createButton('Run', app.createServerHandler('notif').addCallbackElement(form)).setId('run');
var cliHandler = app.createClientHandler().setEnabled().setEnabled(false);
submit.addClickHandler(cliHandler);
flow.add(submit);
form.add(flow);
app.add(form);
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
spreadsheet.show(app);
};
function notif(){
//DO NOTHING. JUST SHOW THE button is DISABLED.
}
button is greyed-out after clicking..
The method return is undefined before user clicks yes/no. According to Google app script, server process should be frozen when dialog shows up. But in my test, the value is returned before users clicks yes/no.
function getValues() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var okToInsert = true;
if (sheet.getName() !== "xxx") {
var ui = SpreadsheetApp.getUi();
var alert = ui.alert('Confirm',
'Your active sheet is not "xxx". Continue to insert?',
ui.ButtonSet.YES_NO);
if(alert == ui.Button.NO){
okToInsert = false;
}
}
return {
"okToInsert": okToInsert
};
}
This is my frontend js:
google.script.run
.withSuccessHandler(
function(selectedRange, scope) {
console.log(">>> selectedRange: " + selectedRange);
})
.withFailureHandler(
function(msg, scope) {
})
.withUserObject($scope)
.getValues();
This is how I enable the sidebar:
var ui = HtmlService.createTemplateFromFile('sidebar').evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('this is title');
SpreadsheetApp.getUi().showSidebar(ui);
I have a sample sidebar add-on called "Dialog return test" created here.
https://docs.google.com/spreadsheets/d/1eHwjHKuBIDw2WOTRU5CZAu9m9V-9mXimFyMlGXbPl-U/edit?usp=sharing
Your code runs perfectly for me:
I get the dialogue prompt and return is defined with no errors. It's likely the issue is with another part of your code, or possibly the script file itself. I would recommend trying it on a new script in a new sheets file and try and narrow the issue down from there.
So, I made a Google Spreadsheet for a group of people to use to keep track of weekly "counts" for a large group of people on a Reddit sub. The things I'm trying to automate are two things. The one I'm having problems with is the one I thought would be the easiest, just copying the values from one set (G2:G200) to overwrite the values in another (E2:E200). I'm having some other issues as well, but I'd be more interested in an explanation for what I'm doing wrong there than just an answer. The biggest one is that this is supposed to be making a custom menu on the sheet, and I can't seem to get that working, even though I basically copied the script from the Google Tutorial for that. I've tried the script for this two ways, one using the same script as Excel printed out when recording the same basic thing:
function UpdateLore_() {
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.alert(
'Please confirm',
'Only do this once per week, at end of updates.',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
Range("G2:G200").Select;
Selection.Copy;
Range("E2:E200").Select;
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False;
} else {
// User clicked "No" or X in the title bar.
ui.alert('No Changes Made.');
}
}
This returns an arror on the "Selection.PasteSpecial" line. The other way I tried it was using what I could find online for this:
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
function copyFunction () {
var inputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("G2:G200");
var inputValue = inputRange.getValue();
var outputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("E2:E200");
}
The top part of the code looks like this:
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Weekly Update')
.addItem('Update for Lore', 'UpdateLore')
.addItem('Update for XP Master', 'UpdateMaster')
}
I feel like I'm missing something very obvious, especially with the whole "doesn't seem to change the sheet in anyway" part. Thanks for any help
Got some answers and now it works, thanks for all the help:
Got it, thanks for all the help. New code looks like this:
function UpdateLore() {
var ui = SpreadsheetApp.getUi(); // Same variations.
var result = ui.alert(
'Please confirm',
'Only do this once per week, at end of updates.',
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
copyFunction ();
}
function copyFunction () {
var inputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("G2:G200");
var inputValues = inputRange.getValues();
var outputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("E2:E200").setValues(inputValues);
}
if (result ==ui.Button.NO) {
// User clicked "No" or X in the title bar.
ui.alert('No Changes Made.');
}
}
To add data to a sheet you need to use:
setValue()
setValues()
appendRow()
You've got a function inside of the if body:
if (result == ui.Button.YES) {
// User clicked "Yes".
function copyFunction () {
. . . .
}
}
If you want to call another function at that point, you could use:
if (result == ui.Button.YES) {
// User clicked "Yes".
copyFunction ();
};
function copyFunction () {
. . .
};
You need to set the values from the inputRange to the outputRange. Use the .setValues() on your outputRange to do this.
function copyFunction () {
var inputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("G2:G200");
var inputValues = inputRange.getValues();
var outputRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1").getRange("E2:E200").setValues(inputValues);
}
None of this is valid apps script code:
Range("G2:G200").Select;
Selection.Copy;
Range("E2:E200").Select;
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _ :=False, Transpose:=False;