Basics
Bound scripts and standalone scripts
Every Apps Script project is either attached to one Google file or standing on its own. The kind of project affects how your code opens files, who can see the code, and where you find it later.
1 of 6
A bound script belongs to one file
When you open a spreadsheet and choose Extensions, then Apps Script, the project you get is container bound. Bound means it is part of that spreadsheet, the way a comment is part of it. The same is true of a Doc, a Form, or a Slides deck.
Because the project belongs to the file, it has a shortcut to it. SpreadsheetApp.getActiveSpreadsheet() returns that spreadsheet with no id and no setup. In a Doc it is DocumentApp.getActiveDocument(), and in a Form it is FormApp.getActiveForm().
A bound project travels with the file. Copy the spreadsheet and the copy has its own copy of the code. Move the file to another folder and the code goes along. Put the file in the trash and the code goes to the trash with it.
- Custom menus and simple triggers such as onOpen and onEdit only make sense here, because there is a file to attach them to.
- Custom spreadsheet functions that you type into a cell must live in the bound project of that spreadsheet.
- The project does not appear in your Drive as a separate file.
2 of 6
A standalone script is its own file
A project you create at script.google.com with New project is standalone. It sits in your Drive as its own file, like a document does, and it is not attached to any spreadsheet.
A standalone project has no active spreadsheet, so getActiveSpreadsheet has nothing to return. You name the file you want instead. SpreadsheetApp.openById takes the long id from the middle of the spreadsheet URL, and SpreadsheetApp.openByUrl takes the whole address.
The id is the part of the address between /d/ and /edit. Copy it out of the browser bar and paste it in place of the placeholder below.
function logSpreadsheetName() {
const spreadsheetId = 'PASTE_THE_ID_FROM_YOUR_SPREADSHEET_URL';
const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
const firstSheet = spreadsheet.getSheets()[0];
Logger.log('Opened ' + spreadsheet.getName() + ', first tab ' + firstSheet.getName() + '.');
} 3 of 6
Which one to choose
Choose bound when the code is about one file and the people who use that file. For example: a menu for your team's tracker, a timestamp that fills in when somebody edits a row, or a custom function for one spreadsheet. Anyone who can edit the file can run the code from the menu without hunting for a project.
Choose standalone when the code is about several files, or about no file at all. For example: a nightly job that reads three spreadsheets, a script that files Gmail attachments into Drive, or code you want to reuse across projects as a library.
When you are unsure, start bound. It is the shorter path, and you can move the code into a standalone project later by pasting it and swapping getActiveSpreadsheet for openById.
4 of 6
Finding your scripts again
Go to https://script.google.com/home. That page lists your projects, both kinds together, most recent first. Bound projects show the name of the file they belong to, so you can tell them apart.
You can also reach a bound project the way you made it, with Extensions, then Apps Script, on the file. That is often faster when you already have the file open.
Standalone projects appear in Drive too. Search Drive for the project name, or filter by the Google Apps Script type.
6 of 6
Moving code between the two
There is no button that converts one into the other. You copy the text of your functions into a project of the other kind and adjust the first line or two.
Going from bound to standalone, replace SpreadsheetApp.getActiveSpreadsheet() with SpreadsheetApp.openById(id) and put the id in a named constant at the top. Going the other way, replace openById with getActiveSpreadsheet and delete the id.
Two things do not move. Simple triggers such as onEdit and custom functions used in cells only work in the bound project of that file. Installable triggers are not copied either, so create them again in the new project and approve the access once.
Remember
The short version
- A bound project is created with Extensions, then Apps Script. It belongs to one file and can call getActiveSpreadsheet.
- A standalone project is created at script.google.com and reaches files with openById or openByUrl.
- Bound code is visible to people who can view the file, and a permitted copy includes the code, so keep confidential values out of it.
- https://script.google.com/home lists both kinds of project in one place.
- Menus, simple triggers, and custom cell functions need a bound project.
Keep going
Put it to work
- Task guide Add a custom menu to a Google Sheet
Add a menu named Helpful tools to the menu bar of a Google Sheet. Its one item shows which cell is selected. Save the script, reload the Sheet, and the menu appears.
- Task guide Write a custom function in Google Sheets
Write your own formula for Google Sheets. This one converts Celsius to Fahrenheit, works on one cell or a whole range, and shows a clear message when a cell holds text instead of a number.
- Task guide Back up a spreadsheet to Drive every week
Keep a dated copy of a spreadsheet in a Drive folder. Run the setup function once, and every Monday morning the script saves a new copy with the date in its name.
- Task guide Save labeled Gmail attachments to Drive
Copy the attachments from chosen Gmail conversations into one Drive folder. You pick the conversations by adding a label to them, and the script saves every attachment it finds there.
- Basics Run your first Apps Script function
Your first script, from opening the editor to reading its output. You replace the starter function, save, click Run, and read what Logger.log printed in the Execution log.
- Basics Google Apps Script triggers explained
Google Apps Script triggers run functions automatically when a file opens, a cell changes, a form is submitted, or a scheduled time arrives. Use a simple onEdit or onOpen for work in the bound file. Choose an installable trigger for a schedule, form submission, or work that needs authorization.
- Basics Apps Script permissions and authorization
Before a script can read your sheet or send your mail, you give it permission to access a list of OAuth scopes. This page walks through each authorization screen, explains @OnlyCurrentDoc, and shows how to revoke access.
- Basics Custom functions in Google Sheets
A custom function runs from a cell formula. Each call has 30 seconds, receives cell values instead of ranges, and cannot use your personal data or edit other cells.