Cookbooks¶
Copy-paste ready recipes for common Google Apps Script workflows with gaslamp.
Each cookbook is a self-contained, practical example that you can adapt to your needs. Start with the scenario that matches your use case, learn the pattern, and apply it to your own data.
Why gaslamp: GAS API Best Practices¶
Google Apps Script has strict constraints:
- Execution time limit: 6 minutes per script run
- API call quota: Limited number of calls to Google services per day
Each call to Sheets API (like appendRow(), appendRows(), insertRow()) consumes time and quota.
This is the GAS golden rule:
❌ Don't: Loop and call appendRow() or insertRow() for each row
- 100 rows × 1 API call per row = 100 API calls (very expensive!)
✅ Do: Load all data, process in memory, write once with setValues()
- Load (1 API call) → Process in memory → Write (1 API call) = 2 API calls (efficient!)
The standard GAS pattern is:
- Load all data at once with
getValues()→ 2D array - Process the 2D array in memory
- Write all data at once with
setValues()→ 2D array
The problem: Manipulating 2D arrays in vanilla JavaScript is tedious. You must manually index columns by position, iterate through rows, and transform each cell:
- Find column index:
headers.indexOf('name') - Loop through rows:
for (const row of rows) - Manually transform:
row[nameIdx].trim().toLowerCase() - Rebuild array:
cleaned.push([name, email, ...])
This is where gaslamp sheds light. It wraps 2D arrays in a DataFrame so you work with column names instead of manual indexing. All recipes follow this efficient pattern automatically.
How Each Cookbook Is Structured¶
All cookbooks follow a consistent pattern to make them easy to read and adapt:
User Story¶
Describes a realistic scenario — who needs this, what are they trying to do, and why. This section helps you identify if the cookbook matches your use case before diving into code.
With gaslamp¶
Complete, runnable function using gaslamp. The code is commented to explain the key steps. Below the code, we highlight the gaslamp features being used and why they matter.
Without gaslamp¶
Shows how you would solve the same problem with vanilla JavaScript (Google Apps Script only, no libraries). This comparison helps you understand the problem gaslamp solves and appreciate the simplifications.
Key Techniques¶
Bullet points summarizing the pattern and best practices. Use these as a checklist when adapting the recipe to your own data.
Schema Validation: Type Checks and Enum Constraints¶
All cookbooks demonstrate schema validation — the practice of checking data types before processing. But validation goes beyond type checking:
Basic Type Validation¶
Use FlameGuards to check fundamental types:
const schema = {
name: gaslamp.FlameGuards.isString,
amount: gaslamp.FlameGuards.isNumber,
};
Constraint Validation with Enum¶
Use FlameWright to validate that values match predefined options (enums):
const schema = {
name: gaslamp.FlameGuards.isString,
category: gaslamp.FlameWright.enumOf(['Food', 'Transport', 'Equipment']),
status: gaslamp.FlameWright.enumOf(['Success', 'Failed', 'Partial']),
};
This ensures category values are only one of the allowed options. If a row has "Foo" instead of "Food", it's caught as a validation error.
Without Schema Validation¶
In vanilla JavaScript, you must manually define allowed values and check each row:
const validCategories = ['Food', 'Transport', 'Equipment'];
for (const row of rows) {
if (!validCategories.includes(row.category)) {
console.warn('Invalid category:', row.category);
continue;
}
// Process row
}
This is verbose, error-prone, and scattered throughout your code.
All cookbooks show this pattern in their "Without gaslamp" sections — notice how much repetition and manual checking is needed without schema validation.
Running Recipes Periodically¶
Most recipes are written as functions that you can call manually (from the Apps Script editor or a custom menu). To run them automatically on a schedule (e.g., every day, every hour), use Google Apps Script Triggers.
Using Triggers¶
- Time-driven triggers: Run on a fixed schedule (hourly, daily, weekly, etc.)
- Event-driven triggers: Run on specific events (spreadsheet open, form submit, etc.)
Example: Run a backup every day at 2 AM¶
function setupBackupTrigger() {
// Remove any existing triggers to avoid duplicates
ScriptApp.getProjectTriggers().forEach((trigger) => {
ScriptApp.deleteTrigger(trigger);
});
// Create a daily trigger at 2 AM
ScriptApp.newTrigger('cookbook_createBackup')
.timeBased()
.everyDays(1)
.atHour(2)
.create();
console.log('Backup trigger created: runs daily at 2 AM');
}
// Call this function once to set up the trigger
// setupBackupTrigger();
Trigger Options¶
Common time-based trigger patterns:
// Every N minutes
.everyMinutes(5)
// Every N hours
.everyHours(6)
// Every N days
.everyDays(1)
// Every week on a specific day
.everyWeeks(1).onWeeksDay(ScriptApp.WeekDay.MONDAY)
// On a specific day of the month
.onMonthDay(15) // 15th of each month
See the Apps Script Triggers documentation for all options.
Best Practices for Periodic Execution¶
- Validate before processing — Always include schema validation so errors are caught early
- Log execution — Add
console.log()statements so you can monitor runs in the execution logs - Add error handling — Wrap main logic in try-catch and log errors
- Remove old triggers — Before creating a new trigger, delete old ones to avoid duplicates (see example above)
- Test manually first — Always run the function manually from the editor before setting up a trigger
Next Steps¶
- Pick a cookbook that matches your use case
- Run the function manually to understand the flow
- Adapt the code to your own data and schema
- Set up a trigger if you need periodic execution
- See User Guides for detailed API reference and advanced patterns