Google Sheets Add-On onEdit(e) not working with Enabled Document - google-apps-script

I am trying to to create an Add On where the user has the option to either choose from the menu, or an onEdit command triggers a change to the cell in sheets. When I use the code below, attached to the sheet it works perfectly, however, when i test it as AUTH-LIMITED (Enabled or installed & enabled) the onEdit(e) functionality doesn't work. Everything about the menu button is working great, I can't figure out how to get the onEdit(e) called, what so ever.
I've tried searching all over but to no success with how to solve for this specific issue.
Thank you in advance!
function onEdit(e){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheeter = ss.getActiveSheet();
sheeter.getRange("a1").setValue("Test");
var range = e.range;
var val = range.getValues();
if(val.length+val[0].length<=2){
var val = range.getValue();
if(range.getFormula()){}
else{
var regex2 = new RegExp('[0-5]{0,1}[0-9]:[0-5]{0,1}[0-9].[0-5]{0,1}[0-9]$','g');
var docContent2 = val.replace(regex2,"00:"+val);
range.setValue(docContent2);
range.setNumberFormat("[M]:SS.0");
}
}
}
function Mass_Convert(){
var now = Date.now();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getActiveRange();
var val = range.getValues();
var replaceBox = new Array(val.length);
var replaceFormat =range.getNumberFormats();
for(var i=0;i<val.length;i++){
replaceBox[i] = new Array(val[i].length);
replaceFormat[i] = new Array(val[i].length);
for(var j=0;j<val[0].length;j++){
var newRange = range.getCell(i+1,j+1);
var newVal = newRange.getValue();
var format = newRange
if(newRange.getFormula()){
replaceBox[i][j]=newRange.getFormula();
replaceFormat[i][j] = newRange.getNumberFormat();
}
else{
if(isNaN(newVal)){
var regex2 = new RegExp('[0-5]{0,1}[0-9]:[0-5]{0,1}[0-9].[0-5]{0,1}[0-9]$','g');
var docContent2 = newVal.replace(regex2,"00:"+newVal);
replaceBox[i][j] = docContent2;
replaceFormat[i][j] = "[M]:SS.0"
}else{
replaceBox[i][j] = newVal;
replaceFormat[i][j] = newRange.getNumberFormat();
}
}
}
}
range.setValues(replaceBox);
range.setNumberFormats(replaceFormat);
}
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Split Conversion')
.addItem('Mass Convert Selected', 'Mass_Convert')
.addToUi();
}
function onInstall(e) {
onOpen(e);
}

I tested this with my add-on and .getActiveSpreadsheet() gives the error:
Execution failed: The Add-on attempted an action that is not permitted in Test as Add-on mode. To use this action, you must deploy the Add-on
Also your onEdit() might have permission issues. There should be some condition to run on specific sheets otherwise it will run on all sheets.
I also found this:
onEdit(e) not working in Add-on

Related

Google Spreadsheet: loop through sheets stop working

i've a function called when opening my spreadsheet that aim to loop trought all sheets, activate them and set cursor to the last modified cell (saved by another function) and, a the last re-select the last used sheet (saved as before by another function).
It worked fine for years, but suddenly stopped working.
Here is my code:
function onOpen()
{
var timer = 2000;
var proprieta = PropertiesService.getScriptProperties();
var lastSheet = proprieta.getProperty("ultimo");
var lastModifiedCell = proprieta.getProperty(lastSheet);
var applicazione = SpreadsheetApp.getActive();
var fogli = applicazione.getSheets();
var ui = SpreadsheetApp.getUi();
for (var i=0; i < fogli.length; i++)
{
var attuale = fogli[i].getName();
var ultimorange = proprieta.getProperty(attuale);
applicazione.getSheetByName(attuale).getRange(ultimorange).activate();
//ui.alert(attuale);
//ui.alert(ultimorange);
Utilities.sleep(timer);
}
applicazione.getSheetByName(lastSheet).getRange(lastModifiedCell).activate();
}
Doesn't return any error but the for loop is not selecting anymore sheet and range given.
If i enable the ui.alert the sheet name and range are displayed correctly.
The last selection ath the end, works correctly...i have no idea why it happens...
Is there anyone who can help me figure out what's wrong?
Thanks to anyone who will answer!!!
I was able to replicate the issue. To prevent this from happening, you can use SpreadsheetApp.flush()
Your code:
function onOpen()
{
var timer = 2000;
var proprieta = PropertiesService.getScriptProperties();
var lastSheet = proprieta.getProperty("ultimo");
var lastModifiedCell = proprieta.getProperty(lastSheet);
var applicazione = SpreadsheetApp.getActive();
var fogli = applicazione.getSheets();
var ui = SpreadsheetApp.getUi();
for (var i=0; i < fogli.length; i++)
{
var attuale = fogli[i].getName();
var ultimorange = proprieta.getProperty(attuale);
var range = applicazione.getSheetByName(attuale).getRange(ultimorange).activate();
SpreadsheetApp.flush();
Utilities.sleep(timer);
}
applicazione.getSheetByName(lastSheet).getRange(lastModifiedCell).activate();
ui.alert("Activation Done");
}
I'm new but i found something recently (i come from excel scripts) :
getting a "range" and getting it's a1Notation are totally different.
Maybe your "ultimorange" (from "attuale") is a range and NOT the notation of the range. It would make getRange(ultimorange) not working.

Can not run standalone Google App Script from a Google Spreadsheet

I have a google spreadsheet shared with co-workers to keep track of task status. And I want to set a function through a menu to block some ranges in which the tasks were completed. The protective permissions are set to only allow me (owner) to edit it.
I've built a standalone script to run as me for this shared spreadsheet by using UrlFetch. I've tried many kinds of codes but it didn't work. The below are 3 versions I tried.
And, of course, I set "Who has access to the app: Anyone, even anonymous" in the standalone script.
Photo 1: Standalone script setting
Thanks so much!
1st version: Without using Content Service
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task')
var result = protection.removeEditors(protection.getEditors())
return result
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange);
Logger.log(response);
}
2nd version: Using Content Service
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task')
var result = protection.removeEditors(protection.getEditors())
return ContentService.createTextOutput(result)
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange).getContentText();
Logger.log(response);
}
3rd version: Using Content Service with JSON
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task')
var result = protection.removeEditors(protection.getEditors())
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON)
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange).getContentText();
var result = JSON.Parse(response)
Logger.log(result);
}
One problem is this line:
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange()
Should be:
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange().getA1Notation();
Currently, the variable taskRange is a "class" It's not a string. You need to send a string.
FINALLY IT WORKS. I think the script was not running properly because I modified many times with many kinds of code. Therefore, I've created a new one and used the "stringified" log as #SandyGood suggested.
Many thanks to you all, specially, #SandyGood.
FINAL SCRIPTS
//In standalone script
function doGet(e){
var taskRange = e.parameter.taskRange;
var ss = SpreadsheetApp.openById('SHARING_SPREADSHEET_ID');
var sh = ss.getSheetByName('Sheet1');
var protection = sh.getRange(taskRange).protect().setDescription('Completed Task');
var result = protection.removeEditors(protection.getEditors());
var resultStr = JSON.stringify(result);
Logger.log('resultStr: ' + resultStr);
}
//In sharing spreadsheet script
var url = "https://script.google.com/macros/s/STANDALONE_SCRIPT_ID/exec"
function onOpen(){
SpreadsheetApp.getUi().createMenu('TASK')
.addItem('Protect Task', 'protectTask')
.addToUi();
}
function protectTask(){
var taskRange = SpreadsheetApp.getActiveSheet().getActiveRange().getA1Notation();
var response = UrlFetchApp.fetch(url+"?taskRange="+taskRange).getContentText();
Logger.log(response);
}

Google Spreadsheet onEdit - limit to a range

I would like to fire a trigger with onEdit if a event (edit a cell) happens in a specific range of a Sheet (NOT all Sheet)?
Exemple: I only want to trigger if a cell of the range called "trgRng" (C10:C250) of Sheet_1 is edited.
I coded as below, but it trigger all sheets not only a specific range of a specific sheet
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// source sheet
var sSh = ss.getSheetByName("Diario");
var aCell = sSh.getActiveCell().getValue();
// destiny sheet - set value from source sheet
var dSh = ss.getSheetByName("Auxiliar");
dSh.getRange('L4').setValue(aCell);
}
Is it possible? How?
I already solve it:
{
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
// source sheet
var sSh = e.source.getActiveSheet();
var maxRow = sSh.getMaxRows();
var name = sSh.getName();
var rng = e.range;
var rngCol = rng.getColumn();
if (sSh.getName() == "Diário" && rng.getColumn() == 8) {
ss.getSheetByName("Diário");
var aCell = sSh.getActiveCell().getValue();
// target sheet
var shD = ss.getSheetByName("Auxiliar");
shD.getRange('L4').setValue(aCell);
}
}
}

Google Spreadsheet unable to deploy web app script --

I've been trying to deploy this web app bound to my shared spreadsheet. Basically it's a script that locks a cell after it's been edited. It is working just fine when I access it, however when I switch to another user and try, it doesn't function. You would think it would be a sharing permission setting, but I've changed everything to public and still no luck. Can you someone please help?
Here is the script:
function doGet(e) {
var sheet = SpreadsheetApp.openById('1234567891011');
}
function onEdit(){
var masterSheetName = "PlaceYourSquare" // sheet where the cells are protected from updates
var helperSheetName = "Helper" // sheet where the values are copied for later checking
var firstDataRow = 1; // only take into account edits on or below this row
var firstDataColumn = 1; // only take into account edits on or to the right of this column
var ss = SpreadsheetApp.getActiveSpreadsheet();
var masterSheet = ss.getActiveSheet();
if (masterSheet.getName() != masterSheetName) return;
var masterCell = masterSheet.getActiveCell();
if (masterCell.getRow() < firstDataRow || masterCell.getColumn() < firstDataColumn) return;
var helperSheet = ss.getSheetByName(helperSheetName);
var helperCell = helperSheet.getRange(masterCell.getA1Notation());
var newValue = masterCell.getValue();
var oldValue = helperCell.getValue();
if (oldValue == "") {
helperCell.setValue(newValue);
} else {
masterCell.setValue(oldValue);
}
}

How to set trigger 'onOpen' on a spreadsheet instead of a sheet? (Focus last row)

I want to focus the last row on a specific sheet (or if possible on every one of them) so here is my function triggered by onOpen on the sheet:
function FocusLastRows() {
var spsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spsheet.getSheetByName("Usuelle_2013");
var rowInt = sheet.getLastRow();
var colInt = sheet.getLastColumn();
var range = sheet.getRange(rowInt, colInt)
sheet.setActiveRange(range)
}
This event works but if my first loaded sheet is different from the one I want it to focus on it just teleports to the other sheet. Best will be to set an .onOpen on the spreadsheet.
Is that possible?
I found a good alternative for it. It's custom menu with function link to it.
//Pierre-luc Des. Script
//Build your menu
function setMenu() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menubuttons = [ {name: "Dernière ligne usuelle", functionName: "GOTOLastRow}];
ss.addMenu("Outils", menubuttons);
}
function GOTOLastRow() {
var spsheet = SpreadsheetApp.getActiveSpreadsheet();
var currentTime = new Date();
var sheet = spsheet.getSheetByName("Usuelle_" + currentTime.getFullYear());
var rowInt = sheet.getLastRow();
var colInt = sheet.getLastColumn();
var range = sheet.getRange(rowInt, colInt);
sheet.setActiveRange(range);
}
Now i will have a clickable menu "Outils" which will let me do the function.
This is rather inelegant, but perhaps try just checking whether the activated sheet is the target sheet? Something like this:
function FocusLastRows() {
var spsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spsheet.getSheetByName("Usuelle_2013");
if (sheet == spsheet) {
var rowInt = sheet.getLastRow();
var colInt = sheet.getLastColumn();
var range = sheet.getRange(rowInt, colInt);
sheet.setActiveRange(range);
}
}
The Google Apps Script documentation seems to indicate that you'll need custom libraries to get any other trigger events than the ones provided, and I'm not sure if it's even in-principle possible to trigger only when a certain specific sheet is activated.
I figure checking the sheet with if comparisons is the next-simplest solution.