This tutorial is for Google Workspace Domain accounts.
Recently, I was a guest interviewee at a Google Workspace Developer Summit in Singapore and an attendee asked me how they could automatically add the editor’s email to an adjacent cell when the user checks a check box in Google Sheets.
This can be incredibly handy for project managers to see when a user completes a task or, at a glance, who edited a row.
Of course, there are some simple ways of doing this out-of-the-box within Google Sheets.
A simple right-click > Show edit history on any cell can reveal who has edited the cell in the past.
If you want a more detailed history of edits on your Google Sheet workbook then you can always select the version history button in the top right of your Sheet.
The ‘clock’ icon here opens the version history page.
The problem with these options is that it is not there on the screen for the user to quickly see who edited what line.
In this tutorial, we are going to use some Google Apps Script magic to automatically add the editor’s email to the row when they click that checkbox.
You’ve probably come across the problem where you need to know when a piece of data has been added to your spreadsheet. You probably have been equally frustrated that there is no out-of-the-box function that will do just this.
You’ve tried TODAY() and NOW(), but they change dynamically. What you really need here is something that does not change.
Let’s look at two workarounds that can help you out with this problem.
On a recent board post, a Google Sheets user wanted to change a four-digit number (for example, 1230) to a time, like 12:30, in the same cell that the item was entered.
Unfortunately, the user was not in a position to change the starting values, so they were left with the 4 digits.
There are two ways of doing this with varying levels of complexity:
A mate reached out to me last week asking if there was a way to monitor the times any article in a Google Sheet list goes through an editing stage before being published. From there, he wanted to report the number of edits on the article in an adjacent cell.
Take a look at the example:
As you can see in the example, whenever “NEEDS EDIT” is selected from the dropdown menu, then the counter column for the selected row item is updated automatically.
In this tutorial, we will cover how to create this for a single Google Sheet tab or for multiple selected tabs. I’ll also wrap up with a script to calculate just the aggregate count of changes to all the rows in the selected range and report it in a single cell.
Check out the video tutorial that covers the basics and grab the Starter Sheet to play along:
Everything starts with the onEdit(e) simple trigger. This is a special trigger in Google Apps Script called a Simple Trigger that will run every time you edit your Google Sheet. If Apps Script sees the onEdit() function in your project it runs automatically.
Every time onEdit() is executed, it will retrieve an event parameter that is commonly referenced as "e" (onEdit(e)). The event object can return things like:
The current value
The previous value
The edited range
The source spreadsheet
The trigger id
The authorisation mode
We will be using a few of these in our code below.
Unless you have a very short coding task, it is generally good practice to reference another function that will be executed when onEdit() is run rather than coding directing within the onEdit() function.
Take a look at the three examples I added for my test project for this tutorial:
onEdit()
1
2
3
4
5
6
7
8
functiononEdit(e){
countTimesSpecificCellValSelected_v1_(e);// Count each row in a single col
countTimesSpecificCellValSelected_v2_(e);// Count for multiple Sheet Tabs
First, let’s assign all our variables at the top of our function to make it easier for us to change should we need to down the track.
We have 3 variables that we need to include here. They won’t change so we will make them a constant variable:
tgtSheet – This is the target sheet tab name. For our example, this is assigned to “Single List”.
tgtCol – This is the target column or the column that has the values that will need to be monitored for changes. In our example, this is the status column, column 3.
counterCol – This is the column where we display our change count. For us, this is column 4, but it could be any selected column in the sheet.
Numbers correspond to the points above.
You can stop here if you want to copy and paste the script into your own project and update the variables for your own purposes. Or continue to learn how it all works.
Need help with Google Workspace development?
Go something to solve bigger than Chat GPT?
I can help you with all of your Google Workspace development needs, from custom app development to integrations and security. I have a proven track record of success in helping businesses of all sizes get the most out of Google Workspace.
We don’t want to end up counting the wrong column or updating a completely different sheet tab by mistake. This means we need a way to check if we are in the right spot.
The first thing we need to do is check the range we are currently editing. This can be done by grabbing the range object in our event parameter. Line 33
Using the JavaScript ‘if’ statement we first check that the sheets name (sheet.getName()) is equal to our assigned target sheet name and if it is, then check that the selected column is equal to the target column. Line 38
Update the Counter Cell
Lines 40 – 48
We need to update the adjacent counter cell in the same row that was changed when edited.
Next, using the sheet variable we created earlier we can call the getRange() method to get the counter cell. For a single cell, this method can take two variables the row and the column number. Here, we add in these two variables we collected earlier.
Now we need to add one to the current count in our counter cell. This means that we first need to collect the current value in the cell, which we do with the getValue() method.
We need a way to check if the value in the counter cell is empty. If it is then we want to give it a value of 1 otherwise we want to add 1 to the current value.
First off, we need to store a target value that we want to monitor for and if that value appears add one to our counter cell. Here on line 29, we set our target value to “NEEDS EDIT”.
const tgtVal = "NEEDS EDIT"
You can change this to the value that you need for your project.
Next, we need to check if the cell that was edited was edited to the new target value before we update the counter cell.
To do this we first get the value of the selected range (Line 42):
const cellVal = range.getValue();
Then we create an if statement checking that the cell value matches the target value on line 43 and closes on line 54. if(cellVal === tgtVal){
Apply The Script to Multiple Selected Google Sheets
What if we have different editorial teams or genres handled by different editors? We might want to put the data for each team in a different sheet tab to make it easy for monitoring. Here we will need to check all the selected sheets for any changes.
In our example now we want the “Team 1” and “Team 2” sheet tabs. Both tabs are identical in format.
Let’s see how our code works now:
countTimesSpecificCellValSelected_v2_(e)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
/**
* @OnlyCurrentDoc
*/
/**
* Simple trigger function that runs after each change in the sheet.
*/
functiononEdit(e){
countTimesSpecificCellValSelected_v2_(e);// Count for multiple Sheet Tabs
};
/**
* Counts the number of times a cell value is change to a specfic item
* from a dropdown in a specified column for selected sheets and displays
* the count in the selected adjacent column.
* @param {Object} e - The event object from the onEdit trigger event.
*/
functioncountTimesSpecificCellValSelected_v2_(e){
// ### VARIABLES ###
// Update these
consttgtSheets=["Team 1","Team 2"];// The sheet names the data is on.
consttgtCol=3;// The column to search for a change.
constcounterCol=4;// The column to update the counter.
consttgtVal="NEEDS EDIT"
// ### --- ###
constrange=e.range
constsheet=range.getSheet();
constcolumn=range.getColumn();
// check if on the correct sheet and in the correct column.
On line 25, we need to change the tgtSheet variable to tgtSheets and include an array of all the Google Sheet tabs we need to monitor with our Apps Script code.
const tgtSheets = ["Team 1", "Team 2"]; // The sheet names the data is on.
Then on line 38, we need to replace the first part of the if statement with a way that will look through our array of sheets and check if the current sheet contains the selected name.
This can be achieved with the JavaScript includes function. This function appends a selected array (In our case, the target sheets array) and takes a target value as an argument. Our target value is the select sheet that this being edited.
... tgtSheets.includes(sheet.getName()) ...
Get the Aggregate Count of the Changes
This final script checks all the cells in the target column in a single Google Sheet tab and checks if they have been changed to “NEEDS EDIT”. Then records the aggregate count of all the cells in a single counter cell in a separate sheet tab.
In our example, we will monitor the “Single List” sheet tab for our desired change and record the total count of changes for all rows in the “Aggregate” sheet tab.
Check out the code:
countTimesSpecificCellValSelected_v3_(e)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* @OnlyCurrentDoc
*/
/**
* Simple trigger function that runs after each change in the sheet.
First, we have replaced the counterCol variable with the counterCell variable and set that to cell A2 of the ‘Aggregate’ sheet tab.
const counterCell = 'Aggregate!A2'; // The column to update the counter.
Next, we don’t need to get the row number this time so we have deleted this variable.
Lastly, on line 44, we use the source property of the event (e) object to grab the current spreadsheet. This allows us to use the getRange() method to select our counter cell.
Conclusion
There should be enough samples there for you to work out your own combinations. If you want to test your new skills out, try to:
Create an aggregate count of multiple sheet tabs.
Move the counter column to another location in the sheet.
Check for different target values in different sheets with different locations.
If you get stuck check out some of the other popular tutorials on using onEdit():
It’s always nice to hear how people use these scripts in their own projects and it can be inspiring to share your use cases with others. Feel free to share your experience and examples in the comments below.
Finally a big thanks to Mike Kanert for the inspiration for this post. Editor, writer, artist, actor, educator, polymath and all-around nice fella, you can find Mike on Instagram @Unremarkable_Us for his latest comic series made by parents for parents:
Google Apps Script: isChecked(), switch, filter, map
One Checkbox to Rule them All
Now that’s a fantasy novel I could be my gums into.
Have you ever created a Google Sheet projects where you could really use a select all checkbox (they call them ‘Tick-boxes’ in Google Sheets)? Sure you can copy a range of tickboxes and paste the same range etc. But can you really trust your users not to mess that up?
People are used to select-all checkboxes in their computerised lives. It’s always better to work with familiarity to provide a better user experience rather than try and teach the user on the fly how to do something your way.
With this in mind, I went about creating a select-all checkbox for Google Sheets. Here is a little demo of how it all works. All the black background Tick boxes are select All boxes. These boxes have been assigned a range of other checkboxes that will be either checked or unchecked depending on the main select-all boxes state.
Select All Demo
As you can see, the select all checkbox only changes the tick boxes in the assigned range. It does not affect any other non-tick box data in the same range.
To get this up and running on your own project, all you need to do is copy and paste in the two code files in your Google Apps Script editor. The first code file is the function that runs the check-all code. The other file stores all the select-all checkboxes and the ranges that they will affect.
Let’s take a look at the code and then run through a quick use guide before finishing off with an example.
Those of you who want to dive into the nuts and bolts of the code, there will be more explanation of each element of the code at the end.