Append List Items, Paragraphs and table cell items with a date-time stamp in Google Docs using Google Apps Script

Recently, I thought it would be a cool idea to add a date-time stamp to the end of a Google Doc checklist item with Google Apps Script. So I knew when I completed a task.

I often share a project Google Doc with clients and then add my tasks to the document list. With Google’s new check box list item, I wanted to add the date and time that I completed the task when I checked the box.

The bad news is that there is no onEdit() trigger (like in Google Sheets) for the DocumentApp class that would listen for an edit of the document and see a change of the checked box from unchecked to checked and then apply the date-time stamp. 😢

All good, I settled for the next best thing! A menu item.

Take a quick look at the results.

What the Date-Time Stamp Button does

The timestamp button allows you to set your cursor anywhere on a:

  • List Item
  • Paragraph
  • Table cell item
  • Header

… and then click the ‘AddDTS’ menu item. The Google Apps Script will then run the script and your custom date time stamp will be added.

The Code

Run the script

Go to Tools > Script editor to open the Google Apps Script IDE. Copy the code above and paste it into the script editor. Ctrl + s to save.

You will probably be prompted to change the title of the script. Generally, for document bound scripts it’s good practice to give the script the same or similar name as the attached document.

Close the editor and go back to your Google Doc. Refresh the page and your menu will now reload each time with your new menu item.

The first time you run the script you will get a warning to authenticate the code.

You can find out more about this here:

Running Google Apps Script for the First time. What’s with all the Warnings!

After you have run the code for the first time, you can now click the menu item and it will add the date-time stamp to where ever you have your cursor.

Looking to learn more about Google Apps Scripts in a more structured format? Udemy has some great courses that can get you from the basics to a real Google Apps Script pro.

Got a more specific problem you need help with, but don’t have the time to develop the skills? I can connect you with a trusted freelancer. I have a team of hand-picked experts ready to help.

*The above affiliate links have been carefully researched to get you to what you specifically need. If you decide to click on one of these links it will cost you just the same as going to the site. If you decide to sign up, I just get a little pocket money to help pay for the costs of running this website.

Code breakdown


The onOpen() function is a Google Apps Script custom simple trigger that is run each time the Google Doc, (Slide, Form or Sheet) is opened.

For our purposes, we want to create a menu item. Menu items are part of the Google Docs user interface and also consist of dialogue boxes, sidebars, prompts and alerts. So we can use the getUi() method from the DocumentApp ClassLine 6

To build the menu item, we first call the createMenu(‘menu title’) method that takes a title as an argument and commences the build chain to develop the menu. Line 7

We can add as many sub-menu items to our main menu by using the addItem() method. For example, if you wanted to create different displays of your date-time stamp append tool you could add more here.

Each addItem() takes two arguments (Line 8):

  1. The title of the menu item: For us, this is “Add DTS”.
  2. The function to run when you click the menu item: In our case, this is “appendElement”.

Once we have added everything we wanted to our menu, we build it with the addToUi() method. Line 9

Google Docs custom menu item for appending elements using Google Apps Script


This is the main function that runs your date-time stamp appender.

Let’s see how it works.

Document variables

Our first task is to set up our document variables.

To get the Google Doc we are using in Google Apps Script, we call the DocumentApp class and then call the getActiveDocument() method. This will create an instance of the DocumentApp class containing all the methods that you can use to work with the document. We’ll assign this instance as ‘doc’. Line 7

Referencing our ‘doc’ instance, our next job is to get where the cursor is. We can do this with the getCursor() method. Line 8

A Google Doc is broken into elements, like paragraphs, lists, tables, pictures, headers and more. Each element can have child elements as well.

Once we have our cursor position, we can find the element that the cursor is on. This will come in handy in a moment when we append the element. Line 9

Input variables

Our next task is to add our input variables.

This is where you can start getting really creative and change what is displayed when you click the ‘Add DTS’ menu item.

In our example, we are going to add a string of text containing:

  • Today’s date.
  • Today’s time.
  • The current user’s email.

We first create a new date with JavaScript’s Date constructorLine 4

Next, let’s use the Google Apps Script Session class to grab our email. We can find the active user, a.k.a. the current user, with the getActiveUser() method that then has a child method to get the email with getEmail()Line 5

Note that all editors of your Google Doc will need to give permission for the scope that controls the Session class the first time that they click the menu button.

Now we can put our date and email together in a string. I am using template literals indicated with backticks or grave accents to store our string data because it makes it easy to insert variables into the string with the ${code} template approach.

After I indicate “Complete” at the beginning of the text string, I use the Javasript toDateString() and then toLocaleTimeString() methods on the date variable. This will provide the date and time in your local area (Or more specifically, to the date and time that you have assigned to your script). Line 6

Finally, I add my email.

You can remove any of these items that you don’t want or move them into a better order to suit your own purposes.

get element lengths

To style our appended date time stamp we will need to get the length of the element and then get the length of the element plus the newly added date-time stamp. Line 4

We then get the length of the chosen element. Line 5

We will be applying our styling to the end of the old element length through to the length of the element plus the length of the input.

Note that we will subtract 2 from this value. Why? Because if we added the value right to the end of the element and a user select the end of the element and hits ‘enter’, they will bring the formatting with them. This will make the user sad. Nobody wants a sad user. Line 6

Create text styling

There are two ways of applying styling to text elements in Google Apps Script. We could simply chain a related method like setBold(), setFontFamily() or setForegroundColor() methods to your appended text. This is an okay approach for one or two styles but will slow your code down for more. There is a better approach.

The setAttributes() allows you to set a whole bunch of styles on a particular area of text and then send them to your Google Doc in one big hit.

We will be chaining the setAttributes() method to our text append method in a moment, but first, let’s talk about how the method takes style data.

The last argument for setAttribues() is a list of attributes. These attributes are formatted in an object. Each of the objects property keys needs to come from the DocumentApp.Attribute enumerator. You can find a list of properties here:

Document App Attribute Properties

To make things easier, let’s create the attr variable and assign it to DocumentApp.Attribute. Line 4

Next, we can build our object of attributes. Lines 5-11

Note that I have used square brackets around each key to generate the property key allowing for computed property names.

Append the text and styling

Finally, we get to append the text to the chosen element.

We first grab the element and read it as a text item (Text Class). Line 4

Next, we append the inputVal text to the end of the element with the appendText() method. Line 5

Finally, we use the setAttributes() method to add our style. This method can take:

  1. A start range: {number} For us, that this is the elements original length.
  2. The end range: {number} This will be our combined length of the original element plus our appended text minus 2.
  3. The style: {Object} This is the object of style properties we created in the previous section.


That’s all there is to it. You can modify the style and what you write in your text to how you would like it. I would love to hear how you modified your script for your own project. It is always interesting to see.

If you have found the tutorial helpful, why not shout me a coffee? I'd really appreciate it.

Happy coding!


How to get the most frequently appearing words in a column in Google Sheets

I love it when a Google Sheets blog post generates more curiosity and further questions. Apart from the almost endless source of new material to write about, it is great to see peoples curiosity for a topic deepen.

I wish I could reward you all for this curiosity every time, but sadly I seem to run out of hours of the day.

Fortunately, I have found a little time today to put more details into a question that came from Sue in a recent post Get the Occurrence of a Value in a Range as a Percentage in Google Sheets. She asked:

How would I modify this [the solution in the post] to get the value with the most occurrences?

I hastily wrote a solution but sadly ran out of time to provide any context to the solution. Further, on review of my solution, I discovered two much better approaches. This post answers Sue’s question more fully.

Sue, thanks for the inspiration for this article.


… in a complete platonic Goat-human interactive way, of course. 🐐

In this tutorial, I will provide two solutions. Both are interesting ways to solve the problem and provide some great insight into how to use certain functions in Google Sheets. You can choose which one makes the most sense for you in your project.

You can use the table of contents below to jump straight to the solution or follow along to learn some cool stuff about the QUERY, FILTER, INDEX, COUNTIF, MAX, ARRAYFORMULA and UNIQUE functions in Google Sheets.

If you are playing along, you can get the sheet with just the data here for you to work on.

Data Sheet. 

Just go to File > Make a copy. So you have your own copy of the sheet to edit.

The problem

Our task is to display the most frequently occurring word or words in a list of words.

Take this list of mystery words, for example.

List of letters to determine most frequently occurring in Google Sheets v2


If we were to do a manual count we would discover that the value “puzzling” was the most frequently occurring as it occurs 7 times.

Incidentally, if it was just a list of numbers we could get the most commonly occurring number simply with the MAX function.

So how do we solve this with a Google Sheets formula?

The Solution

As we mentioned earlier, we have two interesting solutions this problem. One we solve primarily using FILTER around a bunch of other functions and one around using the QUERY function on a lovingly hand-crafted array.

The FILTER solution

most frequently occurring word in a column in Google Sheets FILTER solution
Click to Expand!

Here you replace A2:A with the column that you want to find the most frequently occurring cell item in. This can be a single letter or word or phrase.

Simply copy this formula into your Google Sheet and change the range.

To quickly change the range you can select the cell with your new formula in it and hit ctrl + h. The find and replace menu will appear. Let’s say you want to change your range to H4:H200. Your Find and replace menu should look like this:

find and replace a range in Google Sheets
Click to Expand!

You are all done.

But I am sure you are just itching to learn how it all works so you can tweak and change it to other projects. So read on!

Formula Breakdown.

Get a frequency count for each value

Our first task is to get a count of all the times each word appears in each cell. Essentially we want the total count of each word to appear next to the work.

To do this we use the COUNTIF function. This function takes a range as the first argument and a criterion to check as the second argument. If the criterion is true, it will count the value in the cell.

Now, if you have used COUNTIF before you may not have seen another range being added as a criterion. We can apply a criterion as a range because the FILTER function (more on FILTER later) allows for array conditions or ranges of cells to be calculated.

Essentially inside FILTER, this COUNTIF will loop through each cell and conduct a count if the current value in column A matches any other values in the entire range.

Most commonly occurring text in a cell with Google Sheets_Get count of each cell
Click to Expand!

We can now clearly see that “puzzling” is the most frequently occurring word, followed by “cryptic”.

Note! If you are playing along, you might have noticed the inclusion of ARRAYFORMULA in this formula. I’ve used this here to help simulate how the COUNTIF function actually works in the FILTER function when it iterates through the cells in the range. 

If you want to try it out yourself, your formula should look like this: 

Find the max frequency as a value

Next, we need to find the max value of our newly created range of count numbers for each word.

We can do this with the MAX function which conveniently takes a range of values or numbers and return the highest number in that range.

Here we can apply our COUNTIF function we created above so MAX can find the highest value. On ya! Max!

Again, if you are playing along, then you will need to apply the ARRAYFORMUAL function to COUNTIF for it to work on its own in order to simulate it in the FILTER function.

Your result should look like this:

Most commonly occurring text in a cell with Google Sheets_Find the max frequency as a value
Click to Expand!

Filter only those most frequent words in the list

Now we can use these formulas in a FILTER function to only show the word or words that appear the most in your Google Sheets range.

The FILTER function takes a minimum of two arguments:

  1. The range to be displayed.
  2. The conditions that are used to filter the data. The condition starts with a range and then a criterion.

In our FILTER formula we want to display A2:A. So that goes in the first argument.

Then in the next argument, we want to compare the count of each cell against the max value.

Our FILTER will then look like this:

Which would result in displaying all the times that the most frequently occurring cell, well… occurs.

Click to Expand!
What if there is more than one Frequently occurring cell value?

I’m glad you asked.

The great part of this formula is that it will take this into account and include any cell value that is also the most common in the range.

If you have a good memory, you might have noticed that the word, “cryptic” occurs 6 times. Let’s add another “cryptic” to cell A20 and see what happens.

Most commonly occurring text in a cell with Google Sheets_Filter only those most frequent words in the list more than one word
Click to expand!

Cool, hey?

Only show each most frequent word once

We don’t want to see repetitions of the words. We get it. They are the most common. Let’s do something about that with the UNIQUE function.

UNIQUE takes a range and displays any value that occurs in the range only once.

It is pretty cool in that it doesn’t discriminate if it is a number, date or text. It is also case sensitive.

Our final formula would now look like this (Keeping in mind that we have added “cryptic” now as a most frequent value).

Most commonly occurring text in a cell with Google Sheets_Only grabbing the values once
Click to expand!

Bonus! Sorting your results

Having come this far I have now realised that my example is woefully ill-prepared to present the sorting of our results alphabetically because it is, well… already that way.

So for the sake of this short example, let’s go a little wild and sort from Z to A.

We can do this by wrapping our formula in the SORT function.

Sort takes at least 3 functions:

  1. The range to sort – This will be the result of our formula.
  2. The column to sort by – There is only one column for us. So this will be ‘1’.
  3. Whether ascending or descending – Let’s go Z to A here.

Our formula will now look like this:

Which will look like this spectacularly topsy-turvy hellscape:

Most commonly occurring text in a cell with Google Sheets_Sort
Click to Expand!

Quickly now! Change the sort value to TRUE and we will speak no more of it.

The QUERY solution

Most commonly occurring text in a cell with Google Sheets with QUERY
Click to Expand!

Here you replace the A2:A with the range you want to run the formula. You will need to do this each of the three times this range occurs in the formula.

For a shortcut to do this check out the example in The FILTER solution chapter.

This approach has the benefit of being able to quickly display headers or even the count for each max value with simple changes to the query. More on this in the bonus material at the end.

Now I am sure that you are barely containing yourself to find out how this formula works so let’s get cracking.

Formula Breakdown.

This formula uses the QUERY Google Sheets function to show the most commonly occurring cell item in a range. To do this we build our own range based on the original A1:A range and a range generated from the total count of each cell value in the A1:A range as our second column.

We then dynamically insert the largest number of occurrences from this second column to only show those values that are most frequently used, before using the UNIQUE function to shot those values only once.

Let’s break it down into steps…

Get a frequency count for each value.

Our first task is to get the number of times each cell repeats in our list.

We did the same thing here as we did in the FILTER versions.

You can click on the link for the previous explanation.

Make an array containing both the mystery word list and the total count for each word

Next, we need to create a new array containing our original list of mystery words and their corresponding count. In Google Sheets, we can create an array or range of data with curly braces ({}). We create two columns by putting our data between a comma (,).

Here is what our array is going to look like:

Which will produce this result in your Google Sheet:

most frequently occurring word in a column in Google Sheets QUERY solution_get the array
Click to Expand!

Find the max frequency as a value

Just like in our FILTER version we need to get the highest value from our list frequency count for each cell value in the list.

Check out the explanation in the FILTER portion of this tutorial.

QUERY the newly built array where column two is equal to 7

We can finally get into the query. The QUERY function takes two mandatory arguments:

  1. The range to query. This is the two-column array we created.
  2. The query. This will be the query we will write below.

QUERY uses the Google Visualisation API Query Language. You can find some good use-case examples in the main docs.

Being a new language to learn it can take a little while to get the hang of, but one of the beauties of using the query language is that is pretty close to plain English to read.

So, let’s dive in.

Your first step is to ask what you want from the data. For us, we want to display the words in our first column where the total frequency count of the word is the highest.

In query language, our statement would look like this:

Here we select all cells in column 1  where column 2 (our frequency sum col) is equal to 7.

Why 7? This is just a placeholder for our dynamic max count value we created earlier. We know that our current max count is 7 for our most frequently occurring word. We will update this in the next step. For now, it is just easier to read this way.

If you have tried out QUERY before you might be scratching your head over the ‘Col’ word instead of say, a column letter like A, B, C etc. We use the ‘Col#’ syntax when we are not referencing a ‘physical’ range on the sheet but a generated range like our array.

Let’s put our QUERY together now:

Which will result in:

most frequently occurring word in a column in Google Sheets QUERY solution_the basic query
Click to Expand!

Adding the max frequency formula inside the query

One of the cool things about Google Sheets is that we can add dynamic values to strings of text in a cell. To insert a value or formula result in a string of text we use the ampersand character “&” .

Let’s go ahead and add our dynamic max frequency formula to our query.

most frequently occurring word in a column in Google Sheets QUERY solution_the basic query with dynamic input
Click to Expand!

Complete the formula by only selecting UNIQUE values

Finally, we can use the UNIQUE function to only display the words once.

most frequently occurring word in a column in Google Sheets QUERY solution_full formula result
Click to Expand!

BONUS! Expanding QUERY views for kicks

Another benefit of using QUERY is that we can quickly change how the data is displayed by making a few changes to the formula.

First off, for all of these examples, we will need to change our ranges to A1:A instead of A2:A. Go ahead and change this now (See if you can do it with find and replace).

All done? Let’s make some mods to our QUERY.

Add a header

The QUERY function has an optional third parameter that allows you to have a header. We can simply add one to our formula and we now have a header – keeping in mind that we have adjusted all of our ranges to start at A1, not A2.

And the result is:

most frequently occurring word in a column in Google Sheets QUERY solution_bonus header
Click to Expand!
Add the header and frequency count to the formula

Now that we have our headers in place, let’s add the frequency column so that we know how many times these max values have appeared.

All that we need to do here is to add Col2 to our SELECT stage. Don’t forget to separate the columns by a comma.

Which will now look like this:

most frequently occurring word in a column in Google Sheets QUERY solution_bonus header and col2
Click to Expand!

Those headers don’t look great. Especially the frequency column. Let’s do something about that.

Add the header and frequency count to the formula with header LABELS

We can use the query language LABEL clause to create custom labels for any column.

Let’s change column one’s header to read ‘Top Mystery Word/s’ and column two to read ‘Frequency’. To do this we add the LABEL clause followed by the column and then in single quotation ('   ') we add our new label. We separate each label group with a comma.

Our formula will look like this now.

And our end result is this:

most frequently occurring word in a column in Google Sheets QUERY solution_bonus header and col2 with labels
Click to Expand!

Isn’t it pretty?


If you would like the complete Google Sheet with all the examples you can get it here:

Get the most common words in a column – complete examples.googleSheet

If you have found the tutorial helpful, why not shout me a coffee? I'd really appreciate it.

I really love hearing how you use these projects or build on them in the comments below.

Did you enjoy the tutorial? Want to upskill and get a solid step-by-step course to become a pro at Google Sheets? Check out my course, Google Sheets: Learn the Essentials with Three Detailed Projects. Sign up today.

Google Sheets Shortcuts Mousepad
Google Sheets Shortcuts Mousepad
Want a fast track to boost your Spreadsheet efficiency? Grab one of these handy Google Sheets Shortcuts mousepads that I created from my store.
Google Sheets Shortcuts Mousepad Gel
Google Sheets Shortcuts Mousepad Ge