Setup Google Apps Script Word Completion in Sublime Text

When working on Google Apps Script projects locally with CLASP, it can be handy to have text completion for the Apps Script classes and methods.

I’m currently shopping for a new IDE or text editor (the developer’s existential crisis) and have decided to pick up Sublime Text again after a 9-year hiatus after a mediocre three-week trial of Neovim.

After a fresh install of Sublime Text 4 here is what I needed to do:

Requirements

  • Sublime Text 4 …  I mean… c’mon.
  • NPM to install CLASP and the text completion package.
  • CLASP – The command line Apps Script tool for local development.
  • Git (possibly) – If the TypeScript Sublime package is missing, you must install it via Git.

Setup

Google gracefully created a text completion package that uses Definitely Typed a TypeScript repository for type definitions that can be used with both TypeScript and vanilla JavaScript.

Install the TypeScript Package for Sublime Text

Check for the TypeScript Package

First, we check if the TypeScript package has been added to Sublime Text.

Select ctrl shift P (cmd ⌘ should replace ctrl for Apple) to get the Command Pallete and start typing: Package Control: List Packages and select it.

Sublime 4 Package control list
Sublime 4 Package control list

If the TypeScript package is present, move on to adding the Apps Script type package.

Add the TypeScript Package

Head back to the Command Pallete ( ctrl shift P ) and this time start typing Package Control: Install Package.

This will load the Sublime package. Search for ‘TypeScript’. The name must be exact. If it is in the package list (It wasn’t for me) install it and move on to adding the Apps Script type package installation.

If the package is not on the list we will need to use git to clone the package from the Windows GitHub repo for the TypeScrpt-Sublime-Plugin.

Linux

Windows

Mac

 

You may need to close and reopen Sublime Text to see the effects.

Install the Google Apps Script Type Package

In your terminal or shell, run the following:

npm install --save @types/google-apps-script

This will install the autocomplete types for all of the Google Apps Script Classes and Methods.

Testing the Google Apps Script text completion in Sublime Text

Go ahead and open Sublime Text and create a JavaSript *.js file or TypeScirpt *.ts file.

Navigating Autocomplete

Start typing a Google Apps Script class like SpreadsheetApp. You should see it appear in the list.

You can use the up-down (↑↓) arrow keys to navigate the list and enter to select the method or class.

Sublime 4 Google Apps Script Autocomplete selecting a method or class
Sublime 4 Google Apps Script Autocomplete selecting a method or class

Tooltips – Method argument instructions

Information for each method should appear as you enter the braces.

Sublime 4 Google Apps Script Autocomplete

Hovering over the method or class will reveal similar information.

Alt , will open the tooltip when the cursor is within the parentheses of the method.

Look at Multiple Arguments or tooltips

When there are multiple argument types, then you can click on the number to select from the list of types.

Sublime 4 Google Apps Script Autocomplete multiple argument types selection
Sublime 4 Google Apps Script Autocomplete multiple argument types selection

Or you can use the keyboard shortcuts:

Alt , – to open the tooltip if it is not available

Alt ↑ or Alt ↓ – to navigate to the next tooltip for the method.

Rename a Variable, Class or Function

Ctrl T Ctrl M – With your cursor over a variable, class, method or function you can rename it and all occurrences of it.

Formatting

You can also use the TypeScript plugin to format your document.

Ctrl T Ctrl F Formats the whole document

Ctrl T Ctrl F Formats the selection

Ctrl ; Formats the line

 

You can learn more shortcuts from the TypeScript Plugin for Sublime Text docs.

Getting *.gs files to display autocomplete

Sometimes we use the gs file ending for Google Apps Script files. To get these to autocomplete we need to pair them to either JavaScript or TypeScrit.

In Sublime Text first create any .gs file and ensure you are open in that file.

Then, go to View -> Syntax -> Open all with current extension as … . 

Select either JavaScript or TypeScript.

Now, when you edit the file, the Apps Script autocomplete will work as expected.

Conclusion

I’m not sure if I am going to stick with Sublime Text, but it is like slipping on a comfy pair of shoes after such a long break from it, so who knows?

I’d love to hear in the comments if you have used Sublime Text recently or are even using it for your own Apps Script projects. What do you love and not so love about it?

Oh, by the way, I recently built a little CLI tool to help update multiple Google Apps Script projects from a single source project. If this interests you, you can check it out here:

CLASPALL – Update Multiple Apps Script Projects From a Single Source

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

~Yagi

CLASPALL – Update Multiple Apps Script Projects From a Single Source

CLASPALL is a command line app that runs with CLASP, allowing you to update multiple Google Apps Script projects from a single core project file.

When developing for clients I typically have 3 separate projects:

  • Development
  • Testing
  • Production

CLASPALL allows me to update my Testing and Production projects from my Development project with a single command in my terminal: CLASPALL.

Requirements

CLASP -A tool that helps you develop Google Apps Script files locally. You can learn how to install CLASP here.

Features

  • Updates multiple projects from a source project with a single command.
  • Add multiple projects to the update list.
  • Edit projects in the update list.
  • Delete projects from the update list.
  • List projects in the update list.

Installation

You can download the latest version here:

https://github.com/Yagisanatode/claspall/releases/latest

Linux or Mac

Download the binary

You can download the binary for your system from here:

CLASPALL releases

To determine which Linux or Mac download you need, you can use the terminal command:

uname -m

To download via your terminal use:

 

For example:

 

Extracting the file

Navigate to your downloads folder or the location where you downloaded the file.

In the command line, use:

tar -xf <your_selected_claspall_binary>.gz

For example,

tar -xf claspall_Linux_x86_64.tar.gz

This will extract the claspall executable.

Set to path

You can choose to set the file to path so you can use it on any project by doing the following.

  1. mkdir -p ~/bin
    This will create a local bin folder if one does not yet exist.
  2. mv claspall ~/bin
    This moves the claspall executable to the bin folder.
    Note that this will overwrite any previous claspall downloads.

If you have already set your path to the bin folder then you are good to go, you can run claspall -v to get the current version to check if everything is running successfully.

If you haven’t set up the path:

  1. ~/bin/claspall -v
    This will display the current version if everything is successful

This will check if your system has a ~/.profile bash file and then append the bin file to the path in the file. If it doesn’t it will check for a ~/bash_profile file and do the same. If neither exists, it will create the ~/.profile bash file and add the bin to path.

Windows

Download the binary

You can download the binary for your system from here:

CLASPALL releases

To determine which Windows download you need, you can use the Windows command line:

echo %PROCESSOR_ARCHITECTURE%

You can download the zip file from the command line with:

For example:

 

Extracting the file

Head to your downloads folder and extract the zip file.

From the file manager, you can double-click on the zip file and copy and paste in the claspall.exe file into the parent file.

From the command line, you can:

<your_selected_claspall_binary>.zip

For example:

tar -xf claspall_Windows_x86_64.zip

Set to path

If you already have a directory for your local or system path copy and paste the claspall.exe file to this location.

If not, create a Path folder.

    1. mkdir -p C:\Path
      This will create a Path folder in C-drive.
    2. move claspall.exe C:\Path
      This will move your unzipped file to your Path folder. Make sure you are in the same directory (e.g. your downloads folder) as your extracted claspall.exe file.

    3. Optional. Ensure your Path folder is set to your local path. If it isn’t add it to your local path.
    4. claspall -v
      Test your claspall app. This should show the current version number.

Go

You can also build and install the Golang project.

 

How  to use CLASPALL

Cloning an Apps Script Project Locally

If you haven’t already cloned a project to your local drive, do so with:

clasp clone "your Google Apps Script project ID"

Alternatively, you can create a project from scratch locally with:

clasp create 

Then follow the prompts to create a project.

Both approaches will generate a .clasp.json file containing your main project ID.

This will be the primary project that you will edit and update.

Add all the projects you want to update

Next, we need to add all projects that you want to update automatically from your main project.

You can do this with the following tag:

claspall -add "title:Apps-Script-File-Id"

Between quotation marks add a name or title then a colon (:) and the file ID. Close quotation marks.

For example:

claspall -add "Prod:1_hg5Lj-lOXbZMm60FizXSEZBmYN27-ozK-JOX4fRmEWntroxQ"

You can edit, delete and list your current projects too. Check out the Tags section for more information.

Run CLASPALL

Once all of your projects have been added all you need to do is run:

CLASPALL

… in your project folder.

That’s it. Watch the magic unfold.

CLASPALL Tags

-add string

Add a new Apps Script file location:
[how] Between quotation marks add a name or title then
a colon (:) and the file id. Close quotation marks.
[syntax] claspall -add "title:Apps-Script-File-Id"
[example]
claspall -add "Prod:1_hg5Lj-lOXbZMm60FizXSEZBmYN27-ozK-JOX4fRmEWntroxQ"
[more]
— You might consider having a “Test” project and a “Production” project AppsScirpt file
— You can find the project id in the ‘Project Settings’ > ‘IDs’ section.
— Don’t include the current project you are working in. This will be your ‘Dev’ file.

-del int

Delete an Apps Script file location:
– [how] Select a Apps Script file reference to delete by number from the -list.
– [syntax] claspall -del Number
– [example]
claspall -del 1
[more]
— You can use the -list flag to get the selected file location to remove
— This will not delete the file. It will stop the delete file from being updated from the core file.

-edit string

Edit existing Apps Script file location information:
[how] Select an Apps Script file reference from the list and update the title and/or file ID.
[syntax] claspall -edit id:title:Apps-Script-File-Id
[example]
claspall -edit "1:Prod:1_hg5Lj-lOXbZMm60FizXSEZBmYN27-ozK-JOX4fRmEWntroxQ
[more]
— to edit just the Title: “1:New Title:”
— Leave out the id after the first colon.
— To edit just the Apps Script File ID:
"1::1_hg5Lj-lOXbZMm60FizXSEZBmYN27-ozK-JOX4fRmEWntroxQ"
— Leave out the name between the ID and the Apps Script File ID colon separators.

-list  or -ls

Lists all connected file locations

CLASPALL project list

-version or -v

The project version.

For example. 0.1.0.

-help or -h

The help flag lists all of the other flags and provides usage instructions.

CLASPALL project help

About The Project

This project was a small starter project to learn some Golang and a handy tool to use in my own projects.

You can check out the repo on Github here:

https://github.com/Yagisanatode/claspall

~Yagi

Prevent consecutive clicks of Google Sheets Image Buttons in with Lock Service and Google Apps Script

Ever seen an overzealous user madly clicking on an image button in Google Sheets to run an automation script? It’s maddening, frustrating and most importantly, may cause errors in your beautifully crafted code.

In this short tutorial, we explore how to use Google Apps Script’s Lock Service to prevent users from executing your code from your image button while the original instance of the code is still running.

Grab a copy of the starter sheet below to play along.

To the Starter Sheet

Continue reading “Prevent consecutive clicks of Google Sheets Image Buttons in with Lock Service and Google Apps Script”

Preventing Cross-Site Request Forgery (CSRF) in Google Apps Script Dialogs and Sidebars

Cross-Site Request Forgery (CSRF) is a web security vulnerability that allows a nefarious entity to take actions on a website that are unintended by the user.

Typically, this is done by tricking the user into using another website resembling the intended site and then submitting a form or clicking a button. The dodgy site then sends a request with its own payload of nasty stuff on the user’s behalf.

Google Workspace and Google Apps Script’s HMTL Service API protect the user with OAuth2 authorization standards and embed dialogues and sidebars in restrictive iframes to sandbox these environments. However, there may be a requirement to further protect your users from unintentionally sending form data using the google.script.run Client-side API that sends data back to Google Apps Script, with a server-side generated anti-CSRF token.

Indeed, when completing a CASA Tier 2 security assessment for a Google Workspace Editor add-on this was a requirement for me to not only pass the assessment but to also meet GDPR requirements.

An anti-CSRF token will allow us to create a unique ID for the current sidebar or dialogue session. We can store this token server-side in the User Properties of the Properties Service and then add the token to a hidden input element in our form client-side on our dialogues and sidebars. We can then send this token along with our form payload back to Apps Script where we can first validate the token before continuing.

The following script and tutorial provide a brief example of how to do this.

The Example Dialogue

We will first open a Google Sheet (but you can open a Google Doc or Slide and do the same thing) and create a bound Google Apps Script.

Our simple tasks will be to:

  1. Create a menu to access a modal dialogue in the Google Sheet.
  2. Create the modal dialogue with a form containing a radio selection and a submit button.
  3. On submission, the form is validated with the anti-CSRF token before

anti-CSRF token example Google Sheets DialogueCreate a Menu Item and Modal Dialogue in Google Sheets

First, let’s get our UIs out of the way.

Lines 5-12 generate the Google Apps Script simple trigger onOpen(). This will create our menu item that will access the dialogue using the Spreadsheet App Class’ getUi() method.

Next, we build the dialogue. Here, we invoke HtmlService to create a template from a file, referencing the ‘Index.html’ file as our source file. We will take this approach to use scriptlets in our HTML to define our CSRF token.

Finally, we will call the UI method again to display the HTML in a modal dialogue.

Hire a Google Workspace Developer for your Business Needs

Create the Front-end ‘Index’ HTML Page


<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
<div id="container">
<h1>Choose Your Goat</h1>
<form id="goatForm" onsubmit="event.preventDefault();">
<input type="hidden" name="_csrf" value="<?= getCsrfToken() ?>" />
<label for="goat_type">Type of Goat:</label><br>
<input type="radio" name="goat_type" id="goat_type_pygmy" value="pygmy">
<label for="goat_type_pygmy">Pygmy Goat</label><br>
<input type="radio" name="goat_type" id="goat_type_nigerian_dwarf" value="nigerian_dwarf">
<label for="goat_type_nigerian_dwarf">Nigerian Dwarf Goat</label><br>
<input type="radio" name="goat_type" id="goat_type_boer" value="boer">
<label for="goat_type_boer">Boer Goat</label><br>
</form>
<input type="button" value="Submit" onclick="submit()">
<div id="resp">Response: <span id="response">…</span></div>
</div>
</body>
<script>
/**
* When the validation process is completed successfully without Apps Scripting errors.
* @param {String.<Object>} e – event parameter containing 'hasError' boolean and 'text' string.
*/
function onSuccess(e){
const message = JSON.parse(e)
let color = message.hasError? "red" : "blue"
const resp = document.getElementById("response")
resp.innerText = message.text
resp.style.color = color
}
/**
* Submits the response back to Google Apps Script.
*/
function submit(){
const form = document.getElementById('goatForm');
// Create a FormData object
const formData = new FormData(form);
let payload = {}
// Iterate over the form data
for (const [key, value] of formData.entries()) {
console.log(key, value);
Object.assign(payload, {[key]: value})
}
console.log(payload)
google.script.run.withSuccessHandler(onSuccess).formInputs(JSON.stringify(payload));
}
</script>
</html>

view raw

Index.html

hosted with ❤ by GitHub

 The HTML form & CSRF token

Lines 10- 19: Here we are adding our form containing our three choices of goats for our survey.

Note the first input type in the form:

<input type="hidden" name="_csrf" value="<?= getCsrfToken() ?>" />

This is where we are inserting a custom token into the current dialogue session. we have named it “_csrf”. You can also see that we have used Google Apps Script’s HTML printing scriptlets to display the anti-CSRF token returned from the getCsrfToken() function.

This function is called from the Google Apps Script side and generated as a part of the HTML template-building process. More on this function later.

 

Line 20-21: The submit button is added outside the form so as not to generate an error when clicked.

A response line is also added to display if the token is correct or not.

Create and Publish Google Workspace Add-ons with Apps Script Course 300px

Submitting the Form

submit()

Lines 43-64

When the ‘Submit’ button is clicked, the submit() function is invoked.

Here we retrieve the form element and use the new FormData() constructor to gather all the form responses including our hidden CSRF token.

Next, we iterate over the form data entries sorting the keys and values in the payload object.

Finally, we use the google.script.run API to send a stringified version of the payload back serverside.

We also invoke the withSuccessHandler method to return a message once validation of the token has been carried out.

onSuccess(e)

Once the CSRF token has been validated against the stored token value serverside (Apps Script-side) a stringified object will be returned back to the HTML file containing a hasError boolean property and a text string property.

If there was no match between the sent CSRF token and the stored token, we change our message colour to red.

Then we report the message in the ‘response’ span under the submit button.

Generate the CSRF Token in Google Apps Script

This function is called from the Index.html file template when it is being generated.

The function uses the Apps Script Utilities Service to generate a Unique User ID using the getUuid() method.

Next, the token is stored in the user’s property service. This way the token is only accessible for that use for this script. We will generate and store this token each time the user opens dialogue to make it even more challenging for an attacker to breach.

Finally, the token is returned so it can be stored in the HTML file.

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

Validating the CSRF token in Apps Script

Lines 6-10: When the user submits the form, it is sent to the formInputs() function. Here we first parse the stringified form data back to an object and then set up a message object that we will return when our script is complete.

On line 14, we grab our stored CSRF token value so that we can compare it against the one coming in.

Then on lines 17- 27, we check if the form CSRF value matches the store CSRF token value. If it doesn’t, then we return the message variable with our error text.

If the tokens match, then you can carry on a validate your other form inputs before continuing with your data.

That’s it. That’s the whole script. Google Apps Script makes it really easy to implement this security token.

Is It Really Necessary to Add CSRF Tokens to your Google Workspace Dialogues and Sidebars?

Well…probably not. Particularly if you do not intend to publish your Add-on to the public. However, if you do have some restricted scopes that need to be authorised by your users then part of the CASA Tier 2 Assessment then it probably isn’t a huge deal.

The likelihood of someone finding or caring about your dialogues and then trying to exploit them along with Google OAuth and Iframe restrictions would make it pretty hard for a baddie to do any damage to your Google Workspace environment. But, you never know.

Create and Publish a Google Workspace Add-on with Apps Script Course

Need help with Google Workspace development?

My team of experts can help you with all of your needs, from custom app development to integrations and security. We have a proven track record of success in helping businesses of all sizes get the most out of Google Workspace.

Schedule a free consultation today to discuss your needs and get started or learn more about our services here.

~Yagi.

 

Add the Editor’s Email when they Tick the Check Box in Google Sheets with Apps Script

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.

  1. A simple right-click > Show edit history on any cell can reveal who has edited the cell in the past.
    Show cell history in Google Sheets
  2. 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.

    Google Sheets Version History
    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.

Let’s dive in!

Continue reading “Add the Editor’s Email when they Tick the Check Box in Google Sheets with Apps Script”