Triggering script by specific cell value - google-apps-script

I am pretty new to google sheets script development and am wondering how to trigger a clearAll script with cell value i.e. A1=100.
My clearAll script works (see below), though I don't know what to add to it to trigger it using a specific cell value.
function clearAll() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formresponses1 = ss.getSheetByName("formresponses1");
formresponses1.clearContents();}
Thanks

If you are trying to make it so that whenever somebody puts in the value of "100", it clears the content of the entire sheet, then you can do this:
function onEdit(e) {
var ss = SpreadsheetApp.getActive() //gets the active spreadsheet
var sheet = SpreadsheetApp.getActiveSheet() //gets the active sheet
var cell = ss.getActiveRange() //gets the active cell
var cellContent = cell.getValue() //gets the value of the active cell
if(cellContent === 100) {
sheet.clearContents() //clears the values of the entire active sheet
}
}
If you want to make it so that whenever somebody edits the cell and makes its value "100", the code clears only that cell, then do this:
function onEdit(e) {
var ss = SpreadsheetApp.getActive()
var sheet = SpreadsheetApp.getActiveSheet()
var cell = ss.getActiveRange()
var cellContent = cell.getValue()
if(cellContent === 100) {
cell.setValue("") //clears the value of the active cell
}
}
Of course, in the latter, due to the slight lag in Google scripts, if somebody rapidly puts in 100 in every cell they can, then some of the cells with a value of "100" will stay there, but if the person is putting the values in like a normal person rather than a spammer, then this code will work.
Also, if you are trying to make it so that if the value of a certain cell (ie: A1) is equal to "100," the script clears the entire sheet, do this:
function onEdit(e) {
var ss = SpreadsheetApp.getActive()
var sheet = SpreadsheetApp.getActiveSheet()
var cell = sheet.getRange('A1')
var cellContent = cell.getValue()
if(cellContent === 100) {
sheet.clearContents()
}
}
Hope I could help!

The onEdit trigger runs when any cell in the spreadsheet is edited.
Google Documentation - Spreadsheet On Edit
There is also a change trigger. It is an installable trigger, not a simple trigger.
Available types of triggers
Quote from documentation:
An installable change trigger runs when a user modifies the structure
of a spreadsheet itself — for example, by adding a new sheet or
removing a column.
I think the only thing that will work for you is the On Edit trigger. The trigger gets set from the Resources menu in the Apps Script Code editor.
I don't think you can restrict the code from running only to a certain cell, or a certain value within a cell. The code will run every time you edit ANY cell.
I think that the only other alternative would be to run a time based trigger, and have the script get the value of that cell, and check the value. The shortest time interval you can use is to run a script every minute. So if you edited the cell on second 1, it would take 59 more seconds before anything happened.
If you had some type of user interface, and the value in that cell was written to when the user entered a value in an input field, you could detect that change immediately, and make something happen.

Related

Run a script every time there is a change in a cell

I want to run this sript every time there is a change in notes!C4 and automatically copy the value to notes!D4 cell
function Copy() {
var ss = SpreadsheetApp.getActive().getSheetByName("notes") ;
ss.getRange('notes!C4').copyTo(ss.getRange('notes!D4'), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}
Update 1
If this it can't be done, I have in another spreadsheet a script that copies the link http://openinsider.com/screener?s= every time I run it to L2 cell of that sheet.
I'm taking that value with an =ImportRange to the actual spreadsheet. How can I copy that link to notes!D4 that's in another spreadsheet to the actual one?
function Refresh() {
var ss = SpreadsheetApp.getActive().getSheetByName("sheet1") ;
var cell = ss.getRange("L2");
cell.clearContent();
SpreadsheetApp.flush();
Utilities.sleep(5000); // You have 5 second to check that the cell has cleared
cell.setValue('http://openinsider.com/screener?s=');
}
Update 2
I've tried this, the first time the script was charging but it didn't make anything. I'm new to google scripts and I don't know how to make it working.
function onEdit(e) {
if (e.range.getA1Notation() === 'C4') {
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("notes").getRange('D4').CopyPasteType.PASTE_VALUES;
}
}
As mentioned by #Cooper, you just need to use onEdit(e) Simple Trigger to run your script whenever there is a cell being modified.
I will just refer on your latest update, you can refer to this sample code:
function onEdit(e) {
var ss = e.source;
var cell = e.range;
if(cell.getA1Notation() === "C4" && ss.getActiveSheet().getName() == "notes"){
ss.getActiveSheet().getRange("D4").setValue(e.value);
}
}
What it does?
Get the spreadsheet object using Google Sheets events source parameter
Get the range object using Google Sheets events range parameter
Check if the modified cell is in sheet notes and in cell C4, I get the sheet object using Spreadsheet.getActiveSheet() method and get its sheet name using Sheet.getName(). This will make sure that your function will only run when Sheet notes!C4 was modified.
Set the value of the cell D4 using Range.setValue(value). To maximize the event object, I used value parameter in Google Sheets events.
Additional Tips:
Please be mindful of the methods available in each classes/objects that you are using. For example in this code:
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("notes").getRange('D4').CopyPasteType.PASTE_VALUES;
You get the range object of cell D4 using Sheet.getRange(a1Notation)
range object doesn't have CopyPasteType.PASTE_VALUES in its methods

Google Sheets App Script to change sheet and keep same active cell

I'm writing a script for Google Sheets in App Script. The spreadsheet contains two sheets and each has a button on it. Clicking the button on the first sheet takes you to the second sheet. Clicking the button on the second takes you back to the first.
It sounds simple, but I'm unable to restore the cursor position when I go back to each sheet. It always changes to A1 instead. Here is my code.
function changesheet2() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Sheet2'), true);
};
function changesheet1() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Sheet1'), true);
};
According to the documentation, calling setActiveSheet with parameter true should restore the previous active selection and cursor position. This seems to work OK if you do everything within a single function. It doesn't work when there are two separate functions as here.
It's presumably something about context and who can see what data. I am running both scripts from the same user context by getting the user to click a button in each sheet. How can I make it work?
Note that it will only work if it is in the same function. Since the session still has the data where it was previously at. When the function stops, you don't have a way of knowing where was the previous selection was.
The sample code shows it merely returns to the previous activated cell of the sheet.
// Set the first sheet as the active sheet and select the range D4:F4.
spreadsheet.setActiveSheet(firstSheet).getRange('D4:F4').activate();
// Switch to the second sheet to do some work.
spreadsheet.setActiveSheet(secondSheet);
// Switch back to first sheet, and restore its selection.
spreadsheet.setActiveSheet(firstSheet, true);
What I can recommend you is create another sheet storing their previous active cells before the session ends.
Code:
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = spreadsheet.getSheetByName('Sheet1');
var sheet2 = spreadsheet.getSheetByName('Sheet2');
var record = spreadsheet.getSheetByName("record");
function changesheet() {
var sheet = spreadsheet.getActiveSheet();
var sheetName = sheet.getSheetName();
var selection = sheet.getActiveCell().getA1Notation();
if(sheetName == sheet1.getSheetName()){ // if in sheet1, go to sheet2
spreadsheet.setActiveSheet(sheet2);
var sheet2LastActiveCell = record.getRange("A2").getValue();
// if sheet2 was previously recorded, get it's last active cell
// else, go to A1 (default cell)
if(sheet2LastActiveCell)
sheet2.getRange(sheet2LastActiveCell).activateAsCurrentCell();
}
else if(sheetName == sheet2.getSheetName()){ // if in sheet2, go to sheet1
spreadsheet.setActiveSheet(sheet1);
var sheet1LastActiveCell = record.getRange("A1").getValue();
// if sheet1 was previously recorded, get it's last active cell
// else, go to A1 (default cell)
if(sheet1LastActiveCell)
sheet1.getRange(sheet1LastActiveCell).activateAsCurrentCell();
}
else // don't do anything if not in sheet1 or sheet2
return;
// record current cell of previous sheet
recordSheet(sheetName, selection);
}
function recordSheet(sheet, range){
if (sheet == sheet1.getSheetName())
// record sheet1 active cell in A1
record.getRange("A1").setValue(range)
else
// record sheet2 active cell in A2
record.getRange("A2").setValue(range)
}
Additional Notes:
You can hide the record sheet after creating it.
If not yet recorded, it will go to A1 by default.
getActiveCell will always get the active cell of the active sheet. It can't get the active cell of non-active sheets.

Trigger a function on selecting a cell

How to write a trigger which gets triggered everytime the user selects any cell. The trigger will call a function which would log the row number of the highlighted cell on Google Apps Scripts
I have already written a function which is doing that:
function getCell() {
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//get the current highlighted cell
var cell = sheet.getCurrentCell();
//get the row number
var row = cell.getRow();
//log the value
Logger.log(row);
}
But I don't know how to write the trigger. Currently, I have to run the script every time I click on some other cell.
strange, it worked the first time....
function onSelectionChange(e){
Browser.msgBox('cell selection change');
}
maybe things have changed since the question was posted, but landed here.
The available triggers are described on https://developers.google.com/apps-script/guides/triggers/. An alternative that could serve as a workaround is to use the "poll technique" described on How do I make a Sidebar display values from cells?

How to add an input parameter to onEdit Function

I'm trying to create a custom onEdit function with google sheets script editor. I want to know if its possible to add an input parameter such as onEdit(e,row) where row is an integer I use to specify a target cell. Here is my noob code:
function onEdit(e,row) {
// writes the current date to the cell in column B on the same row when a cell in a specific column is edited
var sheetNameToWatch = "M2";
var columnNumberToWatch = /* column */ 7; // column A = 1, B = 2, etc.
var ss = SpreadsheetApp.getActiveSpreadsheet(); // not used atm
var sheet = SpreadsheetApp.getActiveSheet(); // sheet on which changes are tracked
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("GRID-TRACKING") // sheet that contains formula cells
var range = sheet.getActiveCell(); // active cell is cell being edited
if (sheet.getName() == sheetNameToWatch && range.getColumn() == columnNumberToWatch) {
var targetCell = sheet2.getRange(row, 2); // I want the input parameter to control the "row" so I can autofill
targetCell.setValue("" + Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd")); // writes current date to cell
}
}
I'm using this to write the latest date of any edit on sheet "M2" column G to the sheet with formulas("GRID-TRACKING"). I put the formulas in column A and write the dates to column B. The problem is that my "row" variable is undefined...if I replace it with a fixed number and dont try to add the parameter at all it works fine, but I need a parameter I can autofill.
in the cell my formula is =onedit(cell,row)
Thanks,
Umpsy
Short answer
If you want to use two or more arguments use another name instead of onEdit for your function.
Explanation
On Google Apps Script, onEdit is a reserved function name . If you don't follow the guidelines to use the reserved function names you could get unexpected results.
References
https://developers.google.com/apps-script/guides/triggers/
You cannot pass any other variables to onEdit. However, if you are using this as a formula, I don't really see why you would even need an onEdit trigger, it can just as successfully be thisFunc(). As I see in the code, you do not even use the event object so there is definitely no reason to have an onEdit. You also have to consider that it will start any time you edit any cell on the spreadsheet.

How do I deselect an active cell when clicking on an image to run a script?

I have a spreadsheet-bound script that is invoked by clicking an image in the spreadsheet. I've found that the script can be blocked if a cell that it needs to modify is active or being edited by the user.
The code could be anything, even as something as simple as this:
function newf() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getRange("R4");
range.clear();
}
When the cell R4 is open, the function will ignore the cell.
How do I deselect an open cell when clicking on an image to run a script?
The easy (manual) solution would be to click off the open cell prior to clicking on the image, but I am trying to make the script fool-proof and this can be a costly concern. Is there any way that the function can forcefully deselect an active cell?
Edit: I do not mean active cell. Definitely "open cell." Here are pictures of the error.
Open cell with data being entered
Clicked on Picture, program ran
You can use Sheet.setActive() to move the attached user's cursor to a different location in the spreadsheet. You need to remember that there is a relationship between the User Interface and scripts invoked from it, which is what allows the script to determine and change the currently active cell. This does not extend to the multiple user case, though - if User1 is editing the guarded cell when User2 clicks to run the script, the script will have no idea about it.
function newf() {
var safePlace = "A1"; // Some safe cell
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var activeCell = ss.getActiveCell();
if (activeCell.getSheet() == sheet && activeCell.getA1Notation() == "R4")
sheet.setActiveSelection(safePlace);
var range = sheet.getRange("R4");
var activeCell = ss.getActiveCell();
if (activeCell.getA1Notation() == range.getA1Notation() && activeCell.getSheet().getName() == range.getSheet().getName()) {
// Move user from target cell
sheet.setActiveSelection(safePlace);
range.clear();
}
I had the same problems, both the initial one and with the solution proposed by Mogsdad.
I resolved it the following way:
Before running any of the script, the first three lines get a different sheet opened and the spreadsheet gets flushed:
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('DIFFERENT SHEET NAME'), true);
SpreadsheetApp.flush();
The rest of the script follows.
Then at the end of the script, I reopen the initial sheet with a simple:
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('ORIGINAL SHEET NAME'), true);
Another "solution" to this is not to use a button, but use a check mark as if it we a button, and use the onEdit function.
function onEdit(e)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
checkbox1 = ss.getRange("saveCheckbox_001");
if (checkbox1.isChecked())
{
submit1(); //do all the fun stuff associated with this checkbox
checkbox1.uncheck();
}
//more checkbox handling and calling other functions can go here if you need more than one "button"
}