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.
Related
I have a "Task" tab that has a priority and status for each task. I want to delete the task from "Tasks" and add a row to "Completed Tasks" when the status of that task changes to completed. I've been playing around with Macro and the on edit feature. But it's a little complicated for me because both my tables of data are on different rows and columns. So it's not lining up very well. I'll post my spreadsheet to help give you guys a better idea of what I'm talking about.
Google Spreadsheet: https://docs.google.com/spreadsheets/d/1rnICvztZiKXXeXX6ZZhmeJ99BS0yS_K4HAEAuLHEbyA/edit?usp=sharing
I've tried using Macro and using a for loop of sorts. But it's just a big mess now
You were on the right track. Just a few things to note:
You are correct that you need to use onEdit, but it needs to be an Installable Trigger. You can install the trigger manually - just follow the instructions.
You need to make use of Event Objects. This gives you access to the name of the edited sheet, the edited value, and the edited row.
function clearRow(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
// define the edit Sheet Name for use in the IF
var editSheetName = "Tasks"
var editSheet = ss.getSheetByName("Tasks");
// get the eddited value for use in the IF
var eVal = e.value
// test for the "Tasks" sheet and for the tick mark
if(ss.getActiveSheet().getSheetName() === editSheetName && eVal === '✅'){
// define the target sheet
var targetSheet = ss.getSheetByName("Completed Tasks")
// get the editted row
var eRowStart = e.range.rowStart
// get the last row in the target sheet
var targetLR = targetSheet.getLastRow()
// define the range in the edit sheet and 'Get' the values
var editValues = editSheet.getRange(eRowStart,1,1,5).getValues()
// define the range in the target sheet and 'set the Values
targetSheet.getRange(targetLR,1,1,5).setValues(editValues)
// delete the edited row in the edit sheet
editSheet.deleteRow(eRowStart)
}
else{
// Logger.log("DEBUG: no match")
}
}
In Google Sheets, I want to create a macro that will automatically populate a column in each row when another column in that row is manually filled. The autofilled cell will use a formula that takes a chunk of the information (date) that's been entered manually and use a formula to concatenate it with a random number in order to create a unique ID. After inserting and executing the formula, the macro needs to copy and then paste "values only" the result of that formula. The point is to automatically create a stable ID in response to a triggering event (entry of date in row).
In pseudocode, here's the process I'd like the macro to execute:
when (date in yyyy-mm-dd format entered into A[i]) {
fill B[i] with =CONCATENATE(SUBSTITUTE(LEFT(A[i], 7), "-", ""),RANDBETWEEN(0,1000000000));
copy B[i];
PASTE_VALUES B[i] in B[i];
}
Apologies if I've overlooked a previous answer that solves this problem. I'm not new to coding, but I am new to coding in Google Sheets and am not sure what terms or phrases to use to describe what I'm after.
I believe your goal is as follows.
For example, when a value with the format of yyyy-mm-dd is put to the cell "A1", you want to put the formula of =CONCATENATE(SUBSTITUTE(LEFT(A1, 7), "-", ""),RANDBETWEEN(0,1000000000)) to the cell "B1".
You want to fix the value of the formula as the value.
You want to achieve this using OnEdit trigger.
Added: You want to put the value to the column "B", when the column "B" is empty.
In this case, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet, and save the script. And, please set the sheet name you want to use. When you use this script, please put the value with the format of yyyy-mm-dd to the column "A", by this, the script is run.
function onEdit(e) {
const sheetName = "Sheet1"; // Please set the sheet name.
const range = e.range;
const sheet = range.getSheet();
const [a, b] = range.offset(0, 0, 1, 2).getDisplayValues()[0];
if (sheet.getSheetName() != sheetName || range.columnStart != 1 || !/\d{4}-\d{2}-\d{2}/.test(a) || b) return;
const dstRange = range.offset(0, 1);
dstRange.setFormula(`=CONCATENATE(SUBSTITUTE(LEFT(${range.getA1Notation()}, 7), "-", ""),RANDBETWEEN(0,1000000000))`);
SpreadsheetApp.flush();
dstRange.copyTo(dstRange, { contentsOnly: true });
}
Reference:
Simple Triggers
This is the script I came up with:
/** #OnlyCurrentDoc */
function onEdit(e) { //Runs every time the sheet is edited
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1'); //Change this to whatever your sheet is named
var inputCol = sheet.getRange('A1'); //Change this to whatever column the date is going to be entered
//This is the range that will be checked. Slightly redundant, but makes it easier to reuse this script without needing to retype every variable
var myRange = inputCol;
//Get the row & column indexes of the active cell
var row = e.range.getRow();
var col = e.range.getColumn();
//Check that your edited cell is within the correct column
if (col == myRange.getColumn()) { //This runs only if a value is entered into the column defined in 'inputCol'
if(sheet.getRange(e.range.getA1Notation()).getValue() == '') {return}; //If the edited cell is empty (ie the date is deleted, nothing happens)
if(row == 1) {return} //If the header is changed, nothing happens
let codeCell = sheet.getRange('B'+row); //Change to the column that will store the generated code value
codeCell.setValue('=CONCATENATE(SUBSTITUTE(LEFT(A'+row+', 7), "-", ""),RANDBETWEEN(0,1000000000))');
let hardValue = codeCell.getValue(); //Gets the value from the formula you just entered
codeCell.setValue(hardValue); //Replaces the formula with just the resulting value
};
}
Comments are included to explain everything that is happening. Linked below is the spreadsheet I used to test this. It is set to allow editing, so feel free to use it to test the script yourself.
https://docs.google.com/spreadsheets/d/1UONgRPBEbxn8CQeiRSPS4eFKHjh4ae8hXGYn6ImHxeI/edit?usp=sharing
Hope this helps!
I am trying to modify a Script in Google Sheets that creates a Note that contains the content of the Cell it lives in. I think I'm almost there- however, the script I have below only references a static cell. I need it to create a note within each cell in Column C, with each note referencing the text in the specific cell it is assigned.
For example:
C1 contains "TEST", C1 Note shows "TEST"
C2 contains "HELLO", C2 Note shows "HELLO"
C3 contains "WORLD", C3 Note shows "WORLD"
Here is the script that I have currently:
function addNote() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var targetCell = sheet.getRange("C3");
var sourceCell = sheet.getRange("C3");
var noteText = sourceCell.getValue();
targetCell.setNote(noteText);
}***
Appreciate any help that can be provided- also, would be great if this could update the content of the note when the spreadsheet is updated, if anyone knows how to append that.
You want to set the values of column "C" to the notes of the same column.
The values for the notes are the same with the values of cells of column "C".
For example, when the cell "C1" has "TEST", you want to set "TEST" to the note.
When the values of column "C" in 1st tab of active Spreadsheet is edited, you want to update the notes.
You want to achieve this using Google Apps Script.
From your question and your replying comments, I could understanding like above. If my understanding is correct, how about this sample script? Please think of this as just one of several answers.
In this sample script, I used a simple trigger. By this, when the column "C" of the 1st tab is edited, the script is run and the notes of column "C" are updated using the values of column "C".
Sample script:
Please copy and paste the following script and save the script. When you edit the cell of the column "C" in the 1st tab of active Spreadsheet, the script is run and the notes are set with the values of column "C".
function onEdit(e) {
var sheet = e.source.getSheets()[0];
if (e.range.getSheet().getSheetName() === sheet.getSheetName()) {
var range = sheet.getRange("C1:C" + sheet.getLastRow());
var values = range.getValues();
range.setNotes(values);
}
}
References:
Simple Triggers
Event Objects
getValues()
setNotes(notes)
The following script will create a note using the text from the cell that is being edited. The cell must be in the third column ("C"). To change the column that can be edited, change the 3 to the correct column number (A=1,B=2,C=3,etc...)
function onEdit(e){
var range = e.range;
if (range !== 3) return;
range.setNote(e.value);
}
You may want to go a step further and clear the cell after creating the note. Here is an example of that:
function onEdit(e){
var range = e.range;
if (range.getColumn() !== 3) return;
range.setNote(e.value);
range.clearContent();
}
I have done something like this before and found it useful to be able to keep adding notes by entering values into the cell. Here's how you can do that:
function onEdit(e){
var range = e.range;
var newNote = '';
var cellValue = e.value;
if (range.getColumn() !== 3) return;
var previousNote = range.getNote() ? range.getNote() : '';
if (previousNote) {
newNote = cellValue + '\n\n' + previousNote;
} else {
newNote = cellValue;
}
range.setNote(newNote);
range.clearContent();
}
I am doing my project management in a Google Spreadsheet. A script that automates changes in my comment field to my change_date-field =TODAY() would help me to save some time and also use this function for other scripts I might need in the future.
When I make changes in a comment-field currently, I have to manually enter the change date in my change_date-field which is something that could be easily automated, I think.
Unfortunately I have no clue how to write the code for this.
When I am making any changes in my column named "comment" I want to return the value "=TODAY()" in the column named "change_date". Can you guys help me out with a script that does this job for me automatically?
It might be helpful if you could share a version of the spreadsheet you are referring to to help us answer more accurately.
Based on the information provided some ideas that might help you might be:
1. Use setFormula to change the requested cell to today(). Something like
function setToday() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('B1'); //Set the cell here
range.setFormula('=today()');
}
2. Add the date in using the script directly
function newDate() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('B1'); //Set the cell here
var today = Utilities.formatDate(new Date(),Session.getScriptTimeZone(),'dd//MM/yy');
range.setValue(today);
}
You could use an onEdit trigger to update the cells when a specific cell is edited.
function onEdit(e){
var sheet = SpreadsheetApp.getActiveSheet();
var range = e.range;
var column = range.getColumn();
var row = range.getRow();
if (column==2) { //Replace 2 with the column number of your comments cell//
var newRange = sheet.getRange(row,column+1); //If the date is in the next column
newRange.setFormula('=today()');
}
Sorry I couldn't be more specific.
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.