yarn clasp version "description"
- change version in https://developers.google.com/gsuite/add-ons/how-tos/update-editor-addons#update_a_marketplace_listing
Enable the Google Apps Script API (script.google.com/home/usersettings):
- yarn install
- yarn clasp_login
- yarn setup
- yarn build
- yarn deploy
This worked for Taimur:
yarn install
yarn clasp login
yarn build
yarn setup
yarn deploy
The above installation instructions create a new Google Sheets spreadsheet and 'bound' Apps Script, and saves the credentials to a .clasp.json
file in the root directory. If you want to use an existing sheet's script file, then simply copy the scriptId into the .clasp.json
file as below. You can find the script's scriptId by opening your sheet, selecting Tools > Script Editor, then File > Project properties.
Paste the scriptId
into the .clasp.json
file. *Make sure to include "rootDir": "dist"
in this file:
// .clasp.json
{"rootDir": "dist", "scriptId":"...paste scriptId here..."}
Modify the server-side and client-side source code in the src
folder using ES6/7 and React. Change the scopes in appsscript.json
if needed. When you're ready, build the app and deploy! You can run yarn deploy
to build and deploy, or yarn build
just to build the bundled files in the ./dist
directory.
"Google Apps Script is based on JavaScript 1.6 with some portions of 1.7 and 1.8 and provides subset of ECMAScript 5 API."
That means many JavaScript tools used today in modern web development will not work in the Google Apps Script environment, including let
/const
declarations, arrow functions, spread operator, etc.
This project circumvents those restrictions by transpiling newer code to older code that Google Apps Script understands using Babel, and also bundles separate files and modules using Webpack.
On the client-side, Google Apps Scripts has restrictions on the way HTML dialogs are used. While in normal web development you can simply reference a separate css file, e.g.
<link rel="stylesheet" href="styles.css">
in the Google Apps Script environment you need to use HTML templates, which can be cumbersome to work with. With this project, all files are bundled together by inlining .css and .js files. Using a transpiler and bundling tool also allows us to use JSX syntax, and external libraries such as React.
- Support for JSX syntax:
return <div>Name: {person.firstName}</div>
- Support for external packages. Simply install with npm or from a file and
import
:
$ npm install react-addons-css-transition-group
// index.jsx
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import
CSS from another file:
import "./styles.css";
- Use promises with e.g.
.then
/.catch
instead ofgoogle.script.run
:
// instead of this:
google.script.run
.withSuccessHandler(successHandler)
.withFailureHandler(failureHandler)
.getSheetsData()
// you can do this:
import server from '../server';
// access all your server functions here:
const { getSheetsData } = server;
addSheet(newSheetTitle)
.then(successHandler)
.catch(failureHandler);
How does this work? We rewrite google.script.run
to support Promises:
// ./src/client/server.js
const serverMethods = {};
// skip the reserved methods
const ignoredMethods = [
'withFailureHandler',
'withLogger',
'withSuccessHandler',
'withUserObject',
];
for (const method in google.script.run) {
if (!ignoredMethods.includes(method)) {
serverMethods[method] = (...args) => {
return new Promise((resolve, reject) => {
google.script.run
.withSuccessHandler(resolve)
.withFailureHandler(reject)[method](...args);
});
};
}
}
export default serverMethods;
Now we can use familiar Promises in our client-side code and have easy access to all server functions!
- Use newer ES6/7 code, including arrow functions, spread operators,
const
/let
, and more:
const getSheetsData = () => {
let activeSheetName = getActiveSheetName();
return getSheets().map((sheet, index) => {
let sheetName = sheet.getName();
return {
text: sheetName,
sheetIndex: index,
isActive: sheetName === activeSheetName,
};
});
};
This project includes support for GAS definitions and autocomplete through a Tern plugin. Tern is a code-analysis engine for JavaScript, providing many useful tools for developing. See Tern's site for setup instructions for many popular code editors, such as Sublime, Vim and others.
Tern provides many indispensable tools for working with Google Apps Script, such as autocompletion on variables and properties, function argument hints and querying the type of an expression.
-
Autocomplete example. Lists all available methods from the appropriate Google Apps Script API:
-
Full definitions with links to official documentation, plus information on argument and return type:
- You can split up server-side code into multiple files and folders using
import
andexport
statements. - Make sure to expose all public functions including
onOpen
and any functions you are calling from the client. Example below shows assignment toglobal
object:
const onOpen = () => {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Dialog')
.addItem('Add sheets', 'openDialog')
.addToUi();
}
global.onOpen = onOpen
- You may wish to remove automatic linting when running Webpack. You can do so by editing the Webpack config file and commenting out the eslintConfig line in client or server settings:
// webpack.config.js
const clientConfig = Object.assign({}, sharedConfigSettings, {
...
module: {
rules: [
// eslintConfig,
{
This project now supports multiple dialogs and sidebars. Here is an example of the server
code for a 'main.html' dialog and an 'about.html' sidebar:
// ./src/server/sheets-utilities.js
const openDialog = () => {
const html = HtmlService.createHtmlOutputFromFile('main')
.setWidth(400)
.setHeight(600);
SpreadsheetApp
.getUi() // Or DocumentApp or FormApp.
.showModalDialog(html, 'Sheet Editor');
};
const openSidebar = () => {
const html = HtmlService.createHtmlOutputFromFile('about');
SpreadsheetApp
.getUi()
.showSidebar(html);
};
And here is the configuration in webpack that creates multiple html files. You will need to edit this if you want to add more dialog html files:
// ./webpack.config.js
// Client entrypoints:
const clientEntrypoints = [
{
name: "CLIENT - main dialog",
entry: "./src/client/main.jsx",
filename: "main.html"
},
{
name: "CLIENT - about sidebar",
entry: "./src/client/about.jsx",
filename: "about.html"
},
];
- for some reason the addon doesn't work if you're logged in with multiple google accounts