Fixing and Understanding Google Apps Script Code: A Detailed Breakdown

If you’re working with Google Apps Script to automate tasks in Google Sheets, you may encounter issues that require debugging and improvements. In this blog post, we’ll analyze a given script, fix potential issues, and improve the overall functionality.


Understanding the Code

The script creates a custom menu in Google Sheets and provides various functions:

  1. onOpen(e) – Adds an “Advanced” menu with options to trigger other functions.
  2. findSheetData(sheetNameSel) – Retrieves data from a specified sheet.
  3. showDashboard() – Displays a modal dialog listing all sheet names.
  4. showInfo() – Displays an informational modal dialog.
  5. addFormula() – Inserts a formula into a specific sheet.
  6. buildContent() – Creates new sheets, fills them with random data, and copies values from a “main” sheet.

Identified Issues and Fixes

Issue 1: onOpen(e) Missing Semicolon

The onOpen() function is missing a semicolon at the end of addToUi(). While Apps Script often tolerates missing semicolons, it’s best practice to include them for consistency.

Fix:

function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Advanced')
.addItem('Content', 'buildContent')
.addItem('Formula', 'addFormula')
.addSeparator()
.addItem('Info', 'showInfo')
.addItem('Dashboard', 'showDashboard')
.addToUi();
}

Issue 2: Hardcoded Spreadsheet ID

The script references a specific spreadsheet using SpreadsheetApp.openById('1T6tej_vhVdzlGtIEL2G7x8-Ri_m_lfZMIHLVYMMBWnQ'). If the script is meant to be used across multiple spreadsheets, this approach is limiting.

Fix: Use SpreadsheetApp.getActiveSpreadsheet()

var ss = SpreadsheetApp.getActiveSpreadsheet();

This ensures that the script works regardless of which spreadsheet it’s deployed in.

Example Update for findSheetData()

function findSheetData(sheetNameSel) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(sheetNameSel);

if (sheet) {
var data = sheet.getDataRange().getValues();
Logger.log(data);
return { success: true, sheetNameSel: sheetNameSel, data: data };
}

return { success: false, sheetNameSel: sheetNameSel };
}

Issue 3: Missing Null Check for addFormula()

The function addFormula() assumes that “New Sheet 1” exists. If it doesn’t, the script will throw an error.

Fix: Check for Null Before Using the Sheet

function addFormula() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('New Sheet 1');

if (!sheet) {
Logger.log("Sheet 'New Sheet 1' not found.");
return;
}

var range = sheet.getRange('E1:E10');
range.setFormula('=B1+C1+D1'); // Corrected formula syntax
range.setFontColor('red');
range.setFontWeight('bold');
}

Issue 4: buildContent() Creates Unnamed Sheets

The script creates and deletes sheets but doesn’t explicitly define where new sheets should be created. If “main” doesn’t exist, an error occurs.

Fix: Check for Main Sheet Existence

function buildContent() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var mainSheet = ss.getSheetByName('main');

if (!mainSheet) {
Logger.log("Main sheet not found. Exiting.");
return;
}

var valueToCopy = mainSheet.getRange(1, 1, 10, 1).getValues();

for (var x = 1; x <= 4; x++) {
var sheetName = 'New Sheet ' + x;
var sheet = ss.getSheetByName(sheetName);

if (sheet) {
ss.deleteSheet(sheet);
}

sheet = ss.insertSheet(sheetName);

for (var col = 1; col <= 3; col++) {
for (var row = 1; row <= 10; row++) {
sheet.getRange(row, col).setValue(Math.ceil(Math.random() * 1000));
}
}

sheet.insertColumnBefore(1);
sheet.getRange(1, 1, 10, 1).setValues(valueToCopy);
}

Logger.log('Content built successfully.');
}

Issue 5: showDashboard() and showInfo() Reuse Variables Incorrectly

Both functions reuse variables that might cause unexpected results.

Fix: Use Unique Variables and Add Error Handling

function showDashboard() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
var sheetNames = sheets.map(sheet => sheet.getName());

var t = HtmlService.createTemplateFromFile('dashboard');
t.data = { sheets: sheetNames };

var html = t.evaluate().setWidth(1200).setHeight(600);
SpreadsheetApp.getUi().showModalDialog(html, 'Project Dashboard');
}

function showInfo() {
Logger.log('Displaying info');
var t = HtmlService.createTemplateFromFile('info');

var html = t.evaluate().setWidth(1200).setHeight(600);
SpreadsheetApp.getUi().showModalDialog(html, 'Project Info');
}

Final Thoughts

These fixes improve the script’s robustness, maintainability, and error handling. Here’s a summary of the key improvements:

✅ Added missing semicolons for consistency
✅ Replaced hardcoded spreadsheet ID with getActiveSpreadsheet()
✅ Added null checks before using sheets
✅ Fixed incorrect formula syntax in addFormula()
✅ Ensured sheets are properly created and deleted in buildContent()
✅ Refactored showDashboard() and showInfo() for better variable usage

These changes will make your script more reliable and adaptable for different spreadsheets. Happy coding! 🚀