100 Common Google Docs Apps Script Examples

This document provides a comprehensive collection of Google Apps Script examples tailored for Google Docs. Each script is designed to automate common tasks, enhance productivity, and extend the functionality of your documents.

1. Basic Document Access & Creation

These scripts cover the fundamental ways to access existing documents, create new ones, and get references to their main content.

1.1. Open the Active Document

What it achieves: Gets a reference to the Google Doc that the script is currently bound to or running from. This is the most common starting point for Docs scripts.

function getActiveDoc() {
  const doc = DocumentApp.getActiveDocument();
  Logger.log(‘Active Document Name: ‘ + doc.getName());
}

1.2. Create a New Blank Document

What it achieves: Creates a brand new, empty Google Doc in your Google Drive.

function createNewDoc() {
  const newDoc = DocumentApp.create(‘My New Blank Document’);
  Logger.log(‘New Document URL: ‘ + newDoc.getUrl());
}

1.3. Open a Document by ID

What it achieves: Opens a specific Google Doc using its unique ID. You can find the ID in the document’s URL (e.g., https://docs.google.com/document/d/YOUR_DOCUMENT_ID/edit).

function openDocById() {
  const docId = ‘YOUR_DOCUMENT_ID_HERE’; // Replace with your document ID
  const doc = DocumentApp.openById(docId);
  Logger.log(‘Opened Document Name: ‘ + doc.getName());
}

1.4. Open a Document by Name

What it achieves: Opens the first Google Doc found in your Drive with a specific name. Be cautious, as this might not be the exact document you intend if multiple documents share the same name.

function openDocByName() {
  const docName = ‘My Specific Document’; // Replace with your document name
  const files = DriveApp.getFilesByName(docName);
  if (files.hasNext()) {
    const file = files.next();
    const doc = DocumentApp.openById(file.getId());
    Logger.log(‘Opened Document Name: ‘ + doc.getName());
  } else {
    Logger.log(‘Document not found.’);
  }
}

1.5. Get Document Body Content

What it achieves: Retrieves the main content area (the body) of the active document. Most text, paragraphs, tables, and images reside within the body.

function getDocBody() {
  const body = DocumentApp.getActiveDocument().getBody();
  Logger.log(‘Body content type: ‘ + body.getType());
}

1.6. Append Text to Document

What it achieves: Adds a new paragraph of text to the very end of the document’s body.

function appendText() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendParagraph(‘This is new text appended by a script.’);
  Logger.log(‘Text appended.’);
}

1.7. Insert Text at Cursor Position

What it achieves: If the script is run from an open document and the user has a cursor active, this inserts text at that specific point.

function insertTextAtCursor() {
  const cursor = DocumentApp.getActiveDocument().getCursor();
  if (cursor) {
    cursor.insertText(‘Text inserted at cursor.’);
    Logger.log(‘Text inserted at cursor.’);
  } else {
    DocumentApp.getUi().alert(‘Please place your cursor in the document before running this script.’);
  }
}

1.8. Clear All Document Content

What it achieves: Deletes all content (paragraphs, tables, images, etc.) from the document body, leaving it blank.

function clearAllContent() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.clear();
  Logger.log(‘Document content cleared.’);
}

1.9. Save and Close Document (Not explicitly needed for bound scripts)

What it achieves: While Apps Script automatically saves changes, this example demonstrates how you might conceptually “save” by ensuring operations are complete. saveAndClose() is typically used when opening a document by ID and you want to ensure changes are flushed before closing the programmatic reference.

function saveAndCloseDoc() {
  const doc = DocumentApp.getActiveDocument(); // Or DocumentApp.openById(‘ID’)
  // Perform some operations here, e.g., doc.getBody().appendParagraph(‘…’);
  doc.saveAndClose(); // Flushes changes and closes the programmatic access
  Logger.log(‘Document saved and closed (programmatically).’);
}

1.10. Rename the Active Document

What it achieves: Changes the title (name) of the active Google Doc.

function renameDocument() {
  const doc = DocumentApp.getActiveDocument();
  doc.setName(‘My Renamed Document – ‘ + new Date().toLocaleDateString());
  Logger.log(‘Document renamed.’);
}

2. Text & Paragraph Manipulation

These scripts focus on handling text blocks and entire paragraphs within your Google Doc.

2.11. Get All Paragraphs

What it achieves: Retrieves all paragraph elements from the document body.

function getAllParagraphs() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  Logger.log(‘Total paragraphs: ‘ + paragraphs.length);
  paragraphs.forEach((paragraph, index) => {
    Logger.log(`Paragraph ${index + 1}: ${paragraph.getText().substring(0, 50)}…`);
  });
}

2.12. Get Text of a Specific Paragraph

What it achieves: Accesses the text content of a paragraph at a given index.

function getSpecificParagraphText() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    const firstParagraphText = paragraphs[0].getText();
    Logger.log(‘Text of first paragraph: ‘ + firstParagraphText);
  } else {
    Logger.log(‘No paragraphs found.’);
  }
}

2.13. Set Text of a Specific Paragraph

What it achieves: Replaces the entire text content of a specific paragraph.

function setSpecificParagraphText() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setText(‘This is the new text for the first paragraph.’);
    Logger.log(‘First paragraph text updated.’);
  } else {
    Logger.log(‘No paragraphs found to update.’);
  }
}

2.14. Append Text to an Existing Paragraph

What it achieves: Adds text to the end of an existing paragraph without replacing its current content.

function appendToParagraph() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    const paragraph = paragraphs[0];
    paragraph.appendText(‘ — Appended more text.’);
    Logger.log(‘Text appended to first paragraph.’);
  } else {
    body.appendParagraph(‘Initial paragraph.’);
    Logger.log(‘Created initial paragraph as none existed.’);
  }
}

2.15. Delete a Specific Paragraph

What it achieves: Removes a paragraph from the document.

function deleteSpecificParagraph() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 1) { // Ensure there’s at least two to delete the second one
    const paragraphToDelete = paragraphs[1]; // Delete the second paragraph
    paragraphToDelete.removeFromParent();
    Logger.log(‘Second paragraph deleted.’);
  } else {
    Logger.log(‘Not enough paragraphs to delete the second one.’);
  }
}

2.16. Insert a Paragraph Before Another

What it achieves: Adds a new paragraph immediately before an existing one.

function insertParagraphBefore() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    const targetParagraph = paragraphs[0];
    body.insertParagraph(body.getChildIndex(targetParagraph), ‘This paragraph was inserted before the first one.’);
    Logger.log(‘Paragraph inserted before the first.’);
  } else {
    body.appendParagraph(‘First paragraph.’);
    Logger.log(‘Created initial paragraph as none existed.’);
  }
}

2.17. Set Paragraph Alignment (Left, Center, Right, Justify)

What it achieves: Changes the horizontal alignment of a paragraph.

function setParagraphAlignment() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setAlignment(DocumentApp.HorizontalAlignment.CENTER);
    Logger.log(‘First paragraph aligned to center.’);
    if (paragraphs.length > 1) {
      paragraphs[1].setAlignment(DocumentApp.HorizontalAlignment.RIGHT);
      Logger.log(‘Second paragraph aligned to right.’);
    }
  } else {
    body.appendParagraph(‘This is a paragraph to center.’).setAlignment(DocumentApp.HorizontalAlignment.CENTER);
    body.appendParagraph(‘This is a paragraph to right align.’).setAlignment(DocumentApp.HorizontalAlignment.RIGHT);
    Logger.log(‘Created and aligned new paragraphs.’);
  }
}

2.18. Set Paragraph Spacing (Line Spacing)

What it achieves: Adjusts the line spacing (e.g., single, 1.5, double) for a paragraph.

function setParagraphLineSpacing() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setLineSpacing(1.5); // 1.5 line spacing
    Logger.log(‘First paragraph line spacing set to 1.5.’);
  } else {
    body.appendParagraph(‘This paragraph will have 1.5 line spacing.’).setLineSpacing(1.5);
    Logger.log(‘Created new paragraph with 1.5 line spacing.’);
  }
}

2.19. Set Paragraph Indentation (First Line)

What it achieves: Sets the indentation for the first line of a paragraph.

function setFirstLineIndent() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setFirstLineIndent(36); // 36 points = 0.5 inch
    Logger.log(‘First paragraph first line indented by 36 points.’);
  } else {
    body.appendParagraph(‘This paragraph will have its first line indented.’).setFirstLineIndent(36);
    Logger.log(‘Created new paragraph with first line indent.’);
  }
}

2.20. Set Paragraph Indentation (Left & Right)

What it achieves: Sets the left and right indentation for an entire paragraph.

function setLeftRightIndent() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setIndentStart(72).setIndentEnd(36); // Left indent 72pt, Right indent 36pt
    Logger.log(‘First paragraph left indented by 72 points and right indented by 36 points.’);
  } else {
    body.appendParagraph(‘This paragraph will have left and right indentation.’).setIndentStart(72).setIndentEnd(36);
    Logger.log(‘Created new paragraph with left and right indent.’);
  }
}

3. Formatting (Font, Color, Style)

These scripts deal with applying various formatting styles to text.

3.21. Set Font Family

What it achieves: Changes the font of a specific paragraph or text range.

function setFontFamily() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setFontFamily(‘Arial’);
    Logger.log(‘First paragraph font set to Arial.’);
  } else {
    body.appendParagraph(‘This text will be Arial.’).setFontFamily(‘Arial’);
    Logger.log(‘Created new paragraph with Arial font.’);
  }
}

3.22. Set Font Size

What it achieves: Changes the size of the font.

function setFontSize() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setFontSize(18);
    Logger.log(‘First paragraph font size set to 18.’);
  } else {
    body.appendParagraph(‘This text will be size 18.’).setFontSize(18);
    Logger.log(‘Created new paragraph with font size 18.’);
  }
}

3.23. Apply Bold Formatting

What it achieves: Makes text bold.

function applyBold() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    // Make the entire first paragraph bold
    paragraphs[0].setBold(true);
    Logger.log(‘First paragraph set to bold.’);
  } else {
    body.appendParagraph(‘This text will be bold.’).setBold(true);
    Logger.log(‘Created new paragraph with bold text.’);
  }
}

3.24. Apply Italic Formatting

What it achieves: Makes text italic.

function applyItalic() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setItalic(true);
    Logger.log(‘First paragraph set to italic.’);
  } else {
    body.appendParagraph(‘This text will be italic.’).setItalic(true);
    Logger.log(‘Created new paragraph with italic text.’);
  }
}

3.25. Apply Underline Formatting

What it achieves: Underlines text.

function applyUnderline() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setUnderline(true);
    Logger.log(‘First paragraph set to underlined.’);
  } else {
    body.appendParagraph(‘This text will be underlined.’).setUnderline(true);
    Logger.log(‘Created new paragraph with underlined text.’);
  }
}

3.26. Set Text Color

What it achieves: Changes the color of text.

function setTextColor() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setForegroundColor(‘#FF0000’); // Red color
    Logger.log(‘First paragraph text color set to red.’);
  } else {
    body.appendParagraph(‘This text will be red.’).setForegroundColor(‘#FF0000’);
    Logger.log(‘Created new paragraph with red text.’);
  }
}

3.27. Set Background Color (Highlight)

What it achieves: Applies a background highlight color to text.

function setBackgroundColor() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setBackgroundColor(‘#FFFF00’); // Yellow highlight
    Logger.log(‘First paragraph background color set to yellow.’);
  } else {
    body.appendParagraph(‘This text will be highlighted yellow.’).setBackgroundColor(‘#FFFF00’);
    Logger.log(‘Created new paragraph with yellow highlight.’);
  }
}

3.28. Apply Heading Style (Heading 1)

What it achieves: Applies a predefined heading style (e.g., Heading 1) to a paragraph.

function applyHeading1() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraph = body.appendParagraph(‘This is a Main Heading’);
  paragraph.setHeading(DocumentApp.ParagraphHeading.HEADING1);
  Logger.log(‘New paragraph set as Heading 1.’);
}

3.29. Apply Normal Text Style

What it achieves: Resets a paragraph to the default “Normal text” style.

function applyNormalText() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].setHeading(DocumentApp.ParagraphHeading.NORMAL);
    Logger.log(‘First paragraph set to Normal text style.’);
  } else {
    body.appendParagraph(‘This is normal text.’).setHeading(DocumentApp.ParagraphHeading.NORMAL);
    Logger.log(‘Created new paragraph with normal text style.’);
  }
}

3.30. Remove All Formatting from a Paragraph

What it achieves: Clears all direct formatting (bold, italic, color, size, etc.) from a paragraph, reverting it to the default style of its parent.

function removeAllFormatting() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    paragraphs[0].clearAttributes();
    Logger.log(‘All formatting removed from first paragraph.’);
  } else {
    body.appendParagraph(‘Formatted text to clear.’).setBold(true).setFontSize(20).setForegroundColor(‘#0000FF’);
    body.getParagraphs()[0].clearAttributes();
    Logger.log(‘Created and cleared formatting from new paragraph.’);
  }
}

4. Lists (Bulleted & Numbered)

Scripts for creating and manipulating bulleted and numbered lists.

4.31. Create a Simple Bulleted List

What it achieves: Adds a new bulleted list to the document.

function createBulletedList() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendListItem(‘Item 1’).setGlyphType(DocumentApp.GlyphType.BULLET);
  body.appendListItem(‘Item 2’).setGlyphType(DocumentApp.GlyphType.BULLET);
  body.appendListItem(‘Item 3’).setGlyphType(DocumentApp.GlyphType.BULLET);
  Logger.log(‘Bulleted list created.’);
}

4.32. Create a Simple Numbered List

What it achieves: Adds a new numbered list.

function createNumberedList() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendListItem(‘First item’).setGlyphType(DocumentApp.GlyphType.NUMBER);
  body.appendListItem(‘Second item’).setGlyphType(DocumentApp.GlyphType.NUMBER);
  body.appendListItem(‘Third item’).setGlyphType(DocumentApp.GlyphType.NUMBER);
  Logger.log(‘Numbered list created.’);
}

4.33. Indent a List Item (Sub-item)

What it achieves: Moves a list item to a lower level of indentation, creating a sub-item.

function indentListItem() {
  const body = DocumentApp.getActiveDocument().getBody();
  // Ensure there’s a list to work with
  body.appendListItem(‘Main Item 1’).setGlyphType(DocumentApp.GlyphType.BULLET);
  body.appendListItem(‘Sub Item 1.1’).setGlyphType(DocumentApp.GlyphType.BULLET);
  body.appendListItem(‘Main Item 2’).setGlyphType(DocumentApp.GlyphType.BULLET);

  const listItems = body.getListItems();
  if (listItems.length >= 2) {
    listItems[1].setIndentStart(36); // Indent by 36 points (0.5 inch)
    Logger.log(‘Second list item indented.’);
  } else {
    Logger.log(‘Not enough list items to indent.’);
  }
}

4.34. Outdent a List Item

What it achieves: Moves a list item to a higher level of indentation.

function outdentListItem() {
  const body = DocumentApp.getActiveDocument().getBody();
  // Create a list with an indented item
  body.appendListItem(‘Main Item’).setGlyphType(DocumentApp.GlyphType.BULLET);
  body.appendListItem(‘Sub Item’).setGlyphType(DocumentApp.GlyphType.BULLET).setIndentStart(36);

  const listItems = body.getListItems();
  if (listItems.length >= 2) {
    listItems[1].setIndentStart(0); // Remove indentation
    Logger.log(‘Second list item outdented.’);
  } else {
    Logger.log(‘Not enough list items or no indented item to outdent.’);
  }
}

4.35. Change List Glyph Type (e.g., from Bullet to Square)

What it achieves: Changes the visual marker for a bulleted list item.

function changeListGlyph() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendListItem(‘Item with square bullet’).setGlyphType(DocumentApp.GlyphType.SQUARE);
  Logger.log(‘New list item with square bullet created.’);
}

5. Tables

Scripts for creating, manipulating, and populating tables.

5.36. Create a Simple Table

What it achieves: Inserts a new table with specified rows and columns into the document.

function createSimpleTable() {
  const body = DocumentApp.getActiveDocument().getBody();
  const table = body.appendTable([
    [‘Header 1’, ‘Header 2’],
    [‘Row 1, Col 1’, ‘Row 1, Col 2’],
    [‘Row 2, Col 1’, ‘Row 2, Col 2’]
  ]);
  Logger.log(‘Simple table created.’);
}

5.37. Get a Specific Table Cell Content

What it achieves: Retrieves the text from a cell at a given row and column index.

function getTableCellContent() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    const cell = table.getCell(1, 0); // Row 1, Column 0 (second row, first column)
    Logger.log(‘Content of cell (1,0): ‘ + cell.getText());
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.38. Set a Specific Table Cell Content

What it achieves: Updates the text content of a specific table cell.

function setTableCellContent() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    const cell = table.getCell(0, 0); // Row 0, Column 0 (first row, first column)
    cell.setText(‘Updated Header 1’);
    Logger.log(‘Cell (0,0) content updated.’);
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.39. Add a New Row to a Table

What it achieves: Inserts a new row at the end of an existing table.

function addRowToTable() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    table.appendTableRow([‘New Row Col 1’, ‘New Row Col 2’]);
    Logger.log(‘New row added to table.’);
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.40. Add a New Column to a Table

What it achieves: Inserts a new column into an existing table. This requires iterating through rows.

function addColumnToTable() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    const numRows = table.getNumRows();
    for (let i = 0; i < numRows; i++) {
      const row = table.getRow(i);
      row.appendTableCell(‘New Column Data’);
    }
    Logger.log(‘New column added to table.’);
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.41. Delete a Row from a Table

What it achieves: Removes a specific row from a table.

function deleteRowFromTable() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    if (table.getNumRows() > 1) { // Ensure there’s more than one row to delete
      table.removeRow(1); // Remove the second row (index 1)
      Logger.log(‘Second row deleted from table.’);
    } else {
      Logger.log(‘Table has only one row, cannot delete.’);
    }
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.42. Set Table Border (Width, Color)

What it achieves: Sets the width and color of the table borders.

function setTableBorder() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    table.setBorderWidth(1); // 1 point width
    table.setBorderColor(‘#0000FF’); // Blue color
    Logger.log(‘Table border set to 1pt blue.’);
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.43. Merge Table Cells

What it achieves: Merges a range of cells into a single cell.

function mergeTableCells() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    // Merge cells from (0,0) to (0,1) – first row, first two columns
    table.mergeCells(0, 0, 0, 1); // startRow, startCol, endRow, endCol
    Logger.log(‘Cells (0,0) and (0,1) merged.’);
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.44. Unmerge Table Cells

What it achieves: Unmerges previously merged cells.

function unmergeTableCells() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    // This assumes cells (0,0) and (0,1) were previously merged
    // You need to know the original structure or check if it’s merged
    // For demonstration, let’s assume a merged cell exists at (0,0)
    try {
      table.getCell(0, 0).asTableCell().unmerge();
      Logger.log(‘Cell (0,0) unmerged.’);
    } catch (e) {
      Logger.log(‘Could not unmerge cell (0,0). It might not be a merged cell or an error occurred: ‘ + e.message);
    }
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

5.45. Set Cell Background Color

What it achieves: Changes the background color of a specific table cell.

function setCellBackgroundColor() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  if (tables.length > 0) {
    const table = tables[0];
    const cell = table.getCell(0, 0);
    cell.setBackgroundColor(‘#ADD8E6’); // Light blue
    Logger.log(‘Cell (0,0) background color set to light blue.’);
  } else {
    Logger.log(‘No tables found. Please run createSimpleTable first.’);
  }
}

6. Images & Drawings

Scripts for inserting and manipulating images and drawings.

6.46. Insert an Image by URL

What it achieves: Inserts an image into the document using its public URL.

function insertImageFromUrl() {
  const body = DocumentApp.getActiveDocument().getBody();
  const imageUrl = ‘https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png’; // Example Google logo
  try {
    const image = UrlFetchApp.fetch(imageUrl).getBlob();
    body.appendImage(image);
    Logger.log(‘Image inserted from URL.’);
  } catch (e) {
    Logger.log(‘Error inserting image: ‘ + e.message + ‘. Ensure the URL is valid and publicly accessible.’);
  }
}

6.47. Insert an Image from Google Drive by ID

What it achieves: Inserts an image that is already stored in your Google Drive.

function insertImageFromDrive() {
  const body = DocumentApp.getActiveDocument().getBody();
  const imageFileId = ‘YOUR_IMAGE_FILE_ID_HERE’; // Replace with your image file ID from Drive
  try {
    const imageBlob = DriveApp.getFileById(imageFileId).getBlob();
    body.appendImage(imageBlob);
    Logger.log(‘Image inserted from Google Drive.’);
  } catch (e) {
    Logger.log(‘Error inserting image from Drive: ‘ + e.message + ‘. Ensure the ID is correct and you have permission.’);
  }
}

6.48. Set Image Width and Height

What it achieves: Resizes an image within the document.

function setImageSize() {
  const body = DocumentApp.getActiveDocument().getBody();
  const images = body.getImages();
  if (images.length > 0) {
    const image = images[0];
    image.setWidth(150).setHeight(50); // Set width to 150px, height to 50px
    Logger.log(‘First image resized.’);
  } else {
    Logger.log(‘No images found to resize. Please insert an image first.’);
  }
}

6.49. Delete an Image

What it achieves: Removes an image from the document.

function deleteImage() {
  const body = DocumentApp.getActiveDocument().getBody();
  const images = body.getImages();
  if (images.length > 0) {
    images[0].removeFromParent();
    Logger.log(‘First image deleted.’);
  } else {
    Logger.log(‘No images found to delete.’);
  }
}

6.50. Insert a Drawing (Placeholder)

What it achieves: While Apps Script doesn’t directly create complex drawings, it can insert a placeholder for a drawing or interact with existing ones. This example shows how to add a simple paragraph to represent where a drawing might go. Direct drawing manipulation is limited.

function insertDrawingPlaceholder() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendParagraph(‘— [Drawing Placeholder] —‘);
  Logger.log(‘Drawing placeholder added.’);
}

7. Hyperlinks & Bookmarks

Scripts for managing links and internal document navigation.

7.51. Insert a Hyperlink

What it achieves: Inserts text that acts as a clickable link to a URL.

function insertHyperlink() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraph = body.appendParagraph(‘Visit Google’);
  paragraph.setLinkUrl(‘https://www.google.com’);
  Logger.log(‘Hyperlink inserted.’);
}

7.52. Get Hyperlink URL from Text

What it achieves: Retrieves the URL associated with a piece of linked text.

function getHyperlinkUrl() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    const paragraph = paragraphs[0];
    const linkUrl = paragraph.getLinkUrl();
    if (linkUrl) {
      Logger.log(‘Link URL of first paragraph: ‘ + linkUrl);
    } else {
      Logger.log(‘First paragraph does not contain a hyperlink.’);
    }
  } else {
    Logger.log(‘No paragraphs found.’);
  }
}

7.53. Remove a Hyperlink

What it achieves: Removes the link functionality from text, leaving the text itself.

function removeHyperlink() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    const paragraph = paragraphs[0];
    if (paragraph.getLinkUrl()) {
      paragraph.setLinkUrl(null); // Setting URL to null removes the link
      Logger.log(‘Hyperlink removed from first paragraph.’);
    } else {
      Logger.log(‘First paragraph does not have a hyperlink to remove.’);
    }
  } else {
    Logger.log(‘No paragraphs found.’);
  }
}

7.54. Create a Bookmark

What it achieves: Adds a named bookmark at the current cursor position or at the end of the document.

function createBookmark() {
  const doc = DocumentApp.getActiveDocument();
  const cursor = doc.getCursor();
  if (cursor) {
    const bookmark = doc.addBookmark(cursor);
    Logger.log(‘Bookmark created at cursor position with ID: ‘ + bookmark.getId());
  } else {
    // If no cursor, add at the end of the document
    const body = doc.getBody();
    body.appendParagraph(‘Bookmark Target’);
    const bookmark = doc.addBookmark(body.getChild(body.getNumChildren() – 1).asParagraph().editAsText().getRange());
    Logger.log(‘Bookmark created at end of document with ID: ‘ + bookmark.getId());
  }
}

7.55. Get All Bookmarks

What it achieves: Lists all bookmarks present in the document.

function getAllBookmarks() {
  const doc = DocumentApp.getActiveDocument();
  const bookmarks = doc.getBookmarks();
  if (bookmarks.length > 0) {
    Logger.log(‘Bookmarks in document:’);
    bookmarks.forEach((bookmark, index) => {
      Logger.log(`- Bookmark ${index + 1} (ID: ${bookmark.getId()})`);
    });
  } else {
    Logger.log(‘No bookmarks found in this document.’);
  }
}

8. Headers, Footers & Page Breaks

Scripts for managing document sections, page breaks, and recurring content in headers/footers.

8.56. Add a Header

What it achieves: Adds text to the document’s header section.

function addHeaderContent() {
  const header = DocumentApp.getActiveDocument().getHeader();
  if (header) {
    header.clear(); // Clear existing header content
    header.appendParagraph(‘Document Header – ‘ + new Date().toLocaleDateString());
    Logger.log(‘Header content updated.’);
  } else {
    Logger.log(‘No header section found or created by default. You might need to manually add one first.’);
  }
}

8.57. Add a Footer

What it achieves: Adds text to the document’s footer section.

function addFooterContent() {
  const footer = DocumentApp.getActiveDocument().getFooter();
  if (footer) {
    footer.clear(); // Clear existing footer content
    footer.appendParagraph(‘Page ‘ + DocumentApp.PageNumberType.PAGE_NUMBER); // Example: Add page number
    Logger.log(‘Footer content updated with page number.’);
  } else {
    Logger.log(‘No footer section found or created by default. You might need to manually add one first.’);
  }
}

8.58. Insert a Page Break

What it achieves: Inserts a new page break at the current cursor position or at the end of the document.

function insertPageBreak() {
  const doc = DocumentApp.getActiveDocument();
  const cursor = doc.getCursor();
  if (cursor) {
    cursor.insertPageBreak();
    Logger.log(‘Page break inserted at cursor.’);
  } else {
    doc.getBody().appendPageBreak();
    Logger.log(‘Page break inserted at end of document.’);
  }
}

8.59. Insert a Section Break (Next Page)

What it achieves: Inserts a section break that starts the new section on the next page. This allows for different page formatting (e.g., headers/footers) in different sections.

function insertSectionBreakNextPage() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendPageBreak().asPageBreak().setPageBreakType(DocumentApp.PageBreakType.SECTION_BREAK_NEW_PAGE);
  Logger.log(‘Section break (next page) inserted.’);
}

8.60. Get Page Number (using footer example)

What it achieves: Demonstrates how to insert dynamic page numbers into the footer. (This is typically done by setting the PageNumberType property of a footer paragraph, as shown in 8.57).

function addPageNumberToFooter() {
  const footer = DocumentApp.getActiveDocument().getFooter();
  if (footer) {
    footer.clear();
    const paragraph = footer.appendParagraph(‘Page ‘);
    paragraph.appendPageNumber(DocumentApp.PageNumberType.PAGE_NUMBER);
    Logger.log(‘Page number added to footer.’);
  } else {
    Logger.log(‘No footer found. Add one manually first.’);
  }
}

9. Comments & Suggestions

Scripts for adding, resolving, and interacting with comments and suggestions.

9.61. Add a Comment to a Text Range

What it achieves: Adds a comment to a specific selection of text.

function addCommentToText() {
  const doc = DocumentApp.getActiveDocument();
  const body = doc.getBody();
  // Ensure some text exists to comment on
  if (body.getText().length < 10) {
    body.appendParagraph(‘This is some text that will receive a comment.’);
  }
  const range = doc.newRange().select(body.getChild(0).asParagraph().editAsText().getRange(0, 5)).build(); // Select first 5 chars of first paragraph
  doc.addComment(‘This is a new comment from the script.’, range);
  Logger.log(‘Comment added to the first 5 characters of the first paragraph.’);
}

9.62. Resolve a Comment

What it achieves: Marks an existing comment as resolved.

function resolveComment() {
  const doc = DocumentApp.getActiveDocument();
  const comments = doc.getComments();
  if (comments.length > 0) {
    comments[0].setResolved(true);
    Logger.log(‘First comment resolved.’);
  } else {
    Logger.log(‘No comments found to resolve. Please add one first.’);
  }
}

9.63. Reopen a Resolved Comment

What it achieves: Changes a resolved comment back to an open state.

function reopenComment() {
  const doc = DocumentApp.getActiveDocument();
  const comments = doc.getComments();
  if (comments.length > 0) {
    comments[0].setResolved(false);
    Logger.log(‘First comment reopened.’);
  } else {
    Logger.log(‘No comments found to reopen. Please add one first.’);
  }
}

9.64. Get All Open Comments

What it achieves: Retrieves a list of all unresolved comments in the document.

function getOpenComments() {
  const doc = DocumentApp.getActiveDocument();
  const comments = doc.getComments();
  const openComments = comments.filter(comment => !comment.isResolved());
  if (openComments.length > 0) {
    Logger.log(‘Open Comments:’);
    openComments.forEach((comment, index) => {
      Logger.log(`- Comment ${index + 1}: ${comment.getText()}`);
    });
  } else {
    Logger.log(‘No open comments found.’);
  }
}

9.65. Add a Suggestion (Not directly supported as a separate object)

What it achieves: Apps Script doesn’t have a direct addSuggestion method like addComment. Suggestions are part of the “Suggesting” editing mode. To simulate, you would typically add a comment and instruct the user to use suggesting mode. This example adds a regular comment as the closest programmatic equivalent.

function addSuggestionComment() {
  const doc = DocumentApp.getActiveDocument();
  const body = doc.getBody();
  if (body.getText().length < 10) {
    body.appendParagraph(‘Text for a suggested change.’);
  }
  const range = doc.newRange().select(body.getChild(0).asParagraph().editAsText().getRange(0, 4)).build();
  doc.addComment(‘Consider changing “Text” to “Content”.’, range);
  Logger.log(‘Comment added for a “suggestion”. User needs to be in Suggesting mode to apply.’);
}

10. Document Properties & Information

Scripts for accessing and modifying metadata about the document itself.

10.66. Get Document Name

What it achieves: Retrieves the title of the active document.

function getDocName() {
  const doc = DocumentApp.getActiveDocument();
  Logger.log(‘Document Name: ‘ + doc.getName());
}

10.67. Get Document ID

What it achieves: Retrieves the unique identifier of the active document.

function getDocId() {
  const doc = DocumentApp.getActiveDocument();
  Logger.log(‘Document ID: ‘ + doc.getId());
}

10.68. Get Document URL

What it achieves: Retrieves the web URL of the active document.

function getDocUrl() {
  const doc = DocumentApp.getActiveDocument();
  Logger.log(‘Document URL: ‘ + doc.getUrl());
}

10.69. Get Document Owner

What it achieves: Retrieves the email address of the document owner.

function getDocOwner() {
  const doc = DocumentApp.getActiveDocument();
  const owner = doc.getOwner();
  if (owner) {
    Logger.log(‘Document Owner: ‘ + owner.getEmail());
  } else {
    Logger.log(‘Could not determine document owner.’);
  }
}

10.70. Get Last Updated Time

What it achieves: Retrieves the timestamp of the last modification to the document.

function getLastUpdatedTime() {
  const doc = DocumentApp.getActiveDocument();
  const lastUpdated = doc.getLastUpdated();
  Logger.log(‘Last Updated: ‘ + lastUpdated.toLocaleString());
}

11. Search & Replace

Scripts for finding and replacing text within the document.

11.71. Simple Search and Replace (First Occurrence)

What it achieves: Finds the first occurrence of a string and replaces it.

function simpleSearchReplace() {
  const body = DocumentApp.getActiveDocument().getBody();
  const foundElement = body.findText(‘old text’);
  if (foundElement) {
    foundElement.getElement().asText().setText(‘new text’);
    Logger.log(‘First occurrence of “old text” replaced with “new text”.’);
  } else {
    Logger.log(‘”old text” not found.’);
  }
}

11.72. Global Search and Replace (All Occurrences)

What it achieves: Finds all occurrences of a string and replaces them.

function globalSearchReplace() {
  const body = DocumentApp.getActiveDocument().getBody();
  let foundElement = body.findText(‘search_term’);
  let count = 0;
  while (foundElement) {
    foundElement.getElement().asText().setText(‘replacement_text’);
    count++;
    foundElement = body.findText(‘search_term’); // Find next after replacement
  }
  Logger.log(`Replaced “search_term” with “replacement_text” ${count} times.`);
}

11.73. Search and Replace with Regular Expressions

What it achieves: Uses regular expressions for more complex search patterns.

function regexSearchReplace() {
  const body = DocumentApp.getActiveDocument().getBody();
  // Example: Replace all numbers with ‘NUMBER’
  let foundElement = body.findText(‘\\d+’); // Regex to find one or more digits
  let count = 0;
  while (foundElement) {
    foundElement.getElement().asText().setText(‘NUMBER’);
    count++;
    foundElement = body.findText(‘\\d+’);
  }
  Logger.log(`Replaced numbers with “NUMBER” ${count} times.`);
}

11.74. Get All Occurrences of a Word

What it achieves: Finds and logs the text of all elements containing a specific word.

function getAllOccurrences() {
  const body = DocumentApp.getActiveDocument().getBody();
  const searchTerm = ‘example’;
  const foundElements = body.findAll(searchTerm);
  if (foundElements.length > 0) {
    Logger.log(`Found “${searchTerm}” in the following elements:`);
    foundElements.forEach((element, index) => {
      Logger.log(`- Match ${index + 1}: ${element.getElement().getText().substring(0, 100)}…`);
    });
  } else {
    Logger.log(`”${searchTerm}” not found.`);
  }
}

11.75. Replace Text in a Specific Paragraph

What it achieves: Limits search and replace to a single paragraph.

function replaceInSpecificParagraph() {
  const body = DocumentApp.getActiveDocument().getBody();
  const paragraphs = body.getParagraphs();
  if (paragraphs.length > 0) {
    const targetParagraph = paragraphs[0];
    const originalText = targetParagraph.getText();
    const newText = originalText.replace(/old/g, ‘new’); // Replace all ‘old’ with ‘new’
    targetParagraph.setText(newText);
    Logger.log(‘Replaced “old” with “new” in the first paragraph.’);
  } else {
    Logger.log(‘No paragraphs found.’);
  }
}

12. Content Extraction

Scripts for pulling out specific types of content from the document.

12.76. Get All Document Text

What it achieves: Extracts all visible text content from the document.

function getAllDocumentText() {
  const body = DocumentApp.getActiveDocument().getBody();
  const fullText = body.getText();
  Logger.log(‘Full Document Text (first 500 chars): \n’ + fullText.substring(0, 500) + ‘…’);
}

12.77. Get All Tables as Data (Array of Arrays)

What it achieves: Extracts data from all tables in the document into a JavaScript array of arrays.

function getTablesAsData() {
  const body = DocumentApp.getActiveDocument().getBody();
  const tables = body.getTables();
  const allTableData = [];

  tables.forEach((table, tableIndex) => {
    const tableData = [];
    const numRows = table.getNumRows();
    for (let i = 0; i < numRows; i++) {
      const row = table.getRow(i);
      const rowData = [];
      const numCells = row.getNumCells();
      for (let j = 0; j < numCells; j++) {
        rowData.push(row.getCell(j).getText());
      }
      tableData.push(rowData);
    }
    allTableData.push({ tableIndex: tableIndex, data: tableData });
    Logger.log(`Table ${tableIndex + 1} Data: ${JSON.stringify(tableData)}`);
  });
  if (tables.length === 0) {
    Logger.log(‘No tables found in the document.’);
  }
  return allTableData;
}

12.78. Get All Images (URLs or IDs if from Drive)

What it achieves: Lists information about all images in the document.

function getAllImagesInfo() {
  const body = DocumentApp.getActiveDocument().getBody();
  const images = body.getImages();
  if (images.length > 0) {
    Logger.log(‘Images in document:’);
    images.forEach((image, index) => {
      Logger.log(`- Image ${index + 1}:`);
      Logger.log(`  Width: ${image.getWidth()}, Height: ${image.getHeight()}`);
      // Note: Apps Script doesn’t directly expose the original URL for inserted images.
      // If inserted from Drive, you might be able to infer the ID if you stored it.
      // For images, you typically get a Blob.
    });
  } else {
    Logger.log(‘No images found.’);
  }
}

12.79. Extract Specific Section by Heading

What it achieves: Extracts text content between two specific headings.

function extractSectionByHeading() {
  const body = DocumentApp.getActiveDocument().getBody();
  const elements = body.getNumChildren();
  let inSection = false;
  let sectionContent = [];
  const startHeadingText = ‘Introduction’; // Replace with your start heading
  const endHeadingText = ‘Conclusion’;   // Replace with your end heading

  for (let i = 0; i < elements; i++) {
    const element = body.getChild(i);
    if (element.getType() === DocumentApp.ElementType.PARAGRAPH) {
      const paragraph = element.asParagraph();
      const text = paragraph.getText().trim();
      const heading = paragraph.getHeading();

      if (text === startHeadingText && heading !== DocumentApp.ParagraphHeading.NORMAL) {
        inSection = true;
        continue; // Don’t include the start heading itself
      }
      if (text === endHeadingText && heading !== DocumentApp.ParagraphHeading.NORMAL) {
        inSection = false;
        break; // Stop after finding the end heading
      }
      if (inSection) {
        sectionContent.push(text);
      }
    }
  }
  if (sectionContent.length > 0) {
    Logger.log(`Content between “${startHeadingText}” and “${endHeadingText}”:`);
    Logger.log(sectionContent.join(‘\n’));
  } else {
    Logger.log(‘Section not found or empty.’);
  }
}

12.80. Get Number of Words in Document

What it achieves: Counts the total number of words in the document.

function getWordCount() {
  const body = DocumentApp.getActiveDocument().getBody();
  const text = body.getText();
  // Simple word count: split by whitespace and filter out empty strings
  const words = text.split(/\s+/).filter(word => word.length > 0);
  Logger.log(‘Word Count: ‘ + words.length);
}

13. Sharing & Permissions

Scripts for managing who can access and edit your document.

13.81. Share Document with Editor Permissions

What it achieves: Grants editing access to a specific email address.

function shareAsEditor() {
  const doc = DocumentApp.getActiveDocument();
  const email = ‘user@example.com’; // Replace with the email address
  doc.addEditor(email);
  Logger.log(`Document shared with ${email} as editor.`);
}

13.82. Share Document with Viewer Permissions

What it achieves: Grants viewing access to a specific email address.

function shareAsViewer() {
  const doc = DocumentApp.getActiveDocument();
  const email = ‘user@example.com’; // Replace with the email address
  doc.addViewer(email);
  Logger.log(`Document shared with ${email} as viewer.`);
}

13.83. Remove Permissions for a User

What it achieves: Revokes access for a specific user.

function removeUserPermissions() {
  const doc = DocumentApp.getActiveDocument();
  const email = ‘user@example.com’; // Replace with the email address
  const users = doc.getEditors().concat(doc.getViewers());
  users.forEach(user => {
    if (user.getEmail() === email) {
      doc.removeEditor(user); // Try removing as editor
      doc.removeViewer(user); // Try removing as viewer
      Logger.log(`Permissions removed for ${email}.`);
      return;
    }
  });
  Logger.log(`No active permissions found for ${email} to remove.`);
}

13.84. Make Document Public (Anyone with Link can View)

What it achieves: Changes the document’s sharing settings so anyone with the link can view it.

function makePublicViewable() {
  const doc = DocumentApp.getActiveDocument();
  doc.setSharing(DocumentApp.Access.ANYONE_WITH_LINK, DocumentApp.Permission.VIEW);
  Logger.log(‘Document sharing set to “Anyone with the link can view”.’);
}

13.85. Make Document Private (Only Specific Users)

What it achieves: Changes the document’s sharing settings back to private, meaning only explicitly added users can access it.

function makePrivate() {
  const doc = DocumentApp.getActiveDocument();
  doc.setSharing(DocumentApp.Access.PRIVATE, DocumentApp.Permission.NONE);
  Logger.log(‘Document sharing set to “Private”.’);
}

14. Custom Menus & UI

Scripts for adding custom menu items to the Google Docs interface.

14.86. Add a Simple Custom Menu

What it achieves: Creates a new top-level menu in the Docs UI with a single item that runs a function.

function onOpen() {
  DocumentApp.getUi()
      .createMenu(‘My Custom Menu’)
      .addItem(‘Run My Function’, ‘mySimpleFunction’)
      .addToUi();
}

function mySimpleFunction() {
  DocumentApp.getUi().alert(‘Custom Function’, ‘You clicked the custom menu item!’, DocumentApp.getUi().ButtonSet.OK);
}

To run this, save the script, close the document, and reopen it. A new menu “My Custom Menu” will appear.

14.87. Add a Sub-Menu

What it achieves: Creates a menu with nested sub-menus for better organization.

function onOpen() {
  DocumentApp.getUi()
      .createMenu(‘Docs Tools’)
      .addItem(‘Show Alert’, ‘showAlert’)
      .addSeparator() // Adds a horizontal line
      .addSubMenu(DocumentApp.getUi().createMenu(‘Formatting’)
          .addItem(‘Make Bold’, ‘makeSelectedTextBold’)
          .addItem(‘Make Italic’, ‘makeSelectedTextItalic’))
      .addToUi();
}

function showAlert() {
  DocumentApp.getUi().alert(‘Hello’, ‘This is an alert from Docs Tools!’, DocumentApp.getUi().ButtonSet.OK);
}

function makeSelectedTextBold() {
  const selection = DocumentApp.getActiveDocument().getSelection();
  if (selection) {
    const elements = selection.getRangeElements();
    elements.forEach(element => {
      if (element.isPartial()) {
        element.getRange().setTextAttribute(DocumentApp.Attribute.BOLD, true);
      } else {
        element.getElement().asParagraph().setBold(true);
      }
    });
    DocumentApp.getUi().alert(‘Success’, ‘Selected text made bold.’, DocumentApp.getUi().ButtonSet.OK);
  } else {
    DocumentApp.getUi().alert(‘Error’, ‘No text selected.’, DocumentApp.getUi().ButtonSet.OK);
  }
}

function makeSelectedTextItalic() {
  const selection = DocumentApp.getActiveDocument().getSelection();
  if (selection) {
    const elements = selection.getRangeElements();
    elements.forEach(element => {
      if (element.isPartial()) {
        element.getRange().setTextAttribute(DocumentApp.Attribute.ITALIC, true);
      } else {
        element.getElement().asParagraph().setItalic(true);
      }
    });
    DocumentApp.getUi().alert(‘Success’, ‘Selected text made italic.’, DocumentApp.getUi().ButtonSet.OK);
  } else {
    DocumentApp.getUi().alert(‘Error’, ‘No text selected.’, DocumentApp.getUi().ButtonSet.OK);
  }
}

To run this, save the script, close the document, and reopen it.

14.88. Show a Custom Dialog (HTML Service)

What it achieves: Displays a custom HTML-based dialog window within Google Docs.

function showCustomDialog() {
  const htmlOutput = HtmlService.createHtmlOutputFromFile(‘DialogPage’)
      .setWidth(400)
      .setHeight(300);
  DocumentApp.getUi().showModalDialog(htmlOutput, ‘My Custom Dialog’);
}

// Create a new HTML file named `DialogPage.html` in the same Apps Script project:
/*
<!DOCTYPE html>
<html>
  <head>
    <base target=”_top”>
    <style>
      body { font-family: ‘Inter’, sans-serif; padding: 20px; }
      h1 { color: #4285F4; }
    </style>
  </head>
  <body>
    <h1>Welcome to the Dialog!</h1>
    <p>This is content from an HTML file.</p>
    <button onclick=”google.script.host.close()”>Close</button>
  </body>
</html>
*/

You need to create a new HTML file named DialogPage.html in your Apps Script project for this to work.

14.89. Show a Sidebar (HTML Service)

What it achieves: Opens a custom HTML-based sidebar on the right side of the Google Docs interface.

function showCustomSidebar() {
  const htmlOutput = HtmlService.createHtmlOutputFromFile(‘SidebarPage’)
      .setTitle(‘My Custom Sidebar’);
  DocumentApp.getUi().showSidebar(htmlOutput);
}

// Create a new HTML file named `SidebarPage.html` in the same Apps Script project:
/*
<!DOCTYPE html>
<html>
  <head>
    <base target=”_top”>
    <style>
      body { font-family: ‘Inter’, sans-serif; padding: 10px; }
      h2 { color: #DB4437; }
    </style>
  </head>
  <body>
    <h2>Sidebar Content</h2>
    <p>You can put various tools and information here.</p>
    <button onclick=”google.script.run.doSomethingInDocs()”>Do Something</button>
    <script>
      function doSomethingInDocs() {
        google.script.run.withSuccessHandler(function() {
          console.log(‘Action completed!’);
        }).appendTimestamp(); // Call a server-side function
      }
    </script>
  </body>
</html>
*/

function appendTimestamp() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendParagraph(‘Timestamp from Sidebar: ‘ + new Date().toLocaleString());
  Logger.log(‘Timestamp appended from sidebar request.’);
}

You need to create a new HTML file named SidebarPage.html in your Apps Script project for this to work.

14.90. Get User Input with Prompt

What it achieves: Displays a simple input box to get text from the user.

function getUserInput() {
  const ui = DocumentApp.getUi();
  const response = ui.prompt(
      ‘Enter Text’,
      ‘Please enter some text:’,
      ui.ButtonSet.OK_CANCEL);

  if (response.getSelectedButton() === ui.Button.OK) {
    const inputText = response.getResponseText();
    DocumentApp.getActiveDocument().getBody().appendParagraph(‘User entered: ‘ + inputText);
    Logger.log(‘User entered: ‘ + inputText);
  } else {
    Logger.log(‘User cancelled the input.’);
  }
}

15. Triggers (Time-driven, On Open)

Scripts that run automatically based on events or time.

15.91. On Open Trigger (already used in custom menus)

What it achieves: A special function onOpen() that runs automatically when the document is opened. This is commonly used to build custom menus.

// See example 14.86 and 14.87 for implementation.
// The onOpen() function is automatically triggered by Google Docs.

15.92. Create a Time-Driven Trigger

What it achieves: Sets up a script to run automatically at a specific interval (e.g., every hour, daily).

function createDailyTrigger() {
  // Delete existing triggers to avoid duplicates
  const triggers = ScriptApp.getProjectTriggers();
  triggers.forEach(trigger => {
    if (trigger.getHandlerFunction() === ‘dailyDocumentBackup’) {
      ScriptApp.deleteTrigger(trigger);
    }
  });

  // Create a new trigger to run daily at a specific time (e.g., between 1 AM and 2 AM)
  ScriptApp.newTrigger(‘dailyDocumentBackup’)
      .timeBased()
      .atHour(1)
      .everyDays(1)
      .create();
  Logger.log(‘Daily trigger for “dailyDocumentBackup” created.’);
}

function dailyDocumentBackup() {
  const doc = DocumentApp.getActiveDocument();
  const docName = doc.getName();
  const docId = doc.getId();

  // Create a copy of the document
  const copyName = `${docName} – Backup ${new Date().toLocaleDateString()}`;
  const copy = DriveApp.getFileById(docId).makeCopy(copyName);

  Logger.log(`Document “${docName}” backed up to “${copyName}” (ID: ${copy.getId()})`);
}

You need to run createDailyTrigger() once manually to set up the trigger. The dailyDocumentBackup() function will then run automatically.

15.93. Delete All Triggers for a Script

What it achieves: Removes all programmatic triggers associated with the current Apps Script project.

function deleteAllTriggers() {
  const triggers = ScriptApp.getProjectTriggers();
  triggers.forEach(trigger => {
    ScriptApp.deleteTrigger(trigger);
    Logger.log(‘Deleted trigger: ‘ + trigger.getHandlerFunction());
  });
  Logger.log(‘All triggers for this script deleted.’);
}

15.94. On Edit Trigger (Not directly for Docs, but for Sheets/Forms)

What it achieves: While onEdit is primarily for Google Sheets, it’s a common trigger concept. For Docs, changes are often captured via version history or by polling, not a direct onEdit event on content. This example shows a placeholder.

// function onEdit(e) {
//   // This function is for Google Sheets.
//   // Google Docs does not have a direct onEdit trigger for content changes.
//   // You would typically use time-driven triggers or custom UI actions.
//   Logger.log(‘onEdit trigger fired (Note: This is for Sheets, not Docs content edits).’);
// }

16. Integration with Google Sheets (Basic)

Scripts that demonstrate basic data transfer between Docs and Sheets.

16.95. Read Data from Google Sheet and Insert into Doc

What it achieves: Fetches data from a specified Google Sheet and inserts it into the active Google Doc.

function readSheetDataToDoc() {
  const spreadsheetId = ‘YOUR_SPREADSHEET_ID_HERE’; // Replace with your Sheet ID
  const sheetName = ‘Sheet1’; // Replace with your sheet name
  const rangeName = ‘A1:B3’; // Replace with the range you want to read

  try {
    const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
    const sheet = spreadsheet.getSheetByName(sheetName);
    if (!sheet) {
      Logger.log(`Sheet “${sheetName}” not found.`);
      return;
    }
    const data = sheet.getRange(rangeName).getValues();

    const body = DocumentApp.getActiveDocument().getBody();
    body.appendParagraph(‘Data from Google Sheet:’);
    body.appendTable(data);
    Logger.log(‘Data from Sheet inserted into document.’);

  } catch (e) {
    Logger.log(‘Error reading from Sheet: ‘ + e.message);
  }
}

16.96. Write Doc Content to Google Sheet

What it achieves: Extracts paragraphs from the Google Doc and writes them into a Google Sheet.

function writeDocContentToSheet() {
  const spreadsheetId = ‘YOUR_SPREADSHEET_ID_HERE’; // Replace with your Sheet ID
  const sheetName = ‘DocContent’; // Sheet to write to

  try {
    const spreadsheet = SpreadsheetApp.openById(spreadsheetId);
    let sheet = spreadsheet.getSheetByName(sheetName);
    if (!sheet) {
      sheet = spreadsheet.insertSheet(sheetName);
    }

    const body = DocumentApp.getActiveDocument().getBody();
    const paragraphs = body.getParagraphs();
    const dataToWrite = [[‘Paragraph Text’]]; // Header row
    paragraphs.forEach(paragraph => {
      dataToWrite.push([paragraph.getText()]);
    });

    sheet.clearContents(); // Clear existing content
    sheet.getRange(1, 1, dataToWrite.length, dataToWrite[0].length).setValues(dataToWrite);
    Logger.log(‘Document paragraphs written to Google Sheet.’);

  } catch (e) {
    Logger.log(‘Error writing to Sheet: ‘ + e.message);
  }
}

17. Mail Merge & Templating (Simple)

Basic examples of replacing placeholders in a document.

17.97. Simple Placeholder Replacement

What it achieves: Replaces {{placeholder}} text with dynamic values.

function simpleMailMerge() {
  const doc = DocumentApp.getActiveDocument();
  const body = doc.getBody();

  // Ensure placeholders exist in the document for testing
  // body.appendParagraph(‘Dear {{Name}},’);
  // body.appendParagraph(‘Your order number is {{OrderNumber}}.’);

  const data = {
    ‘{{Name}}’: ‘John Doe’,
    ‘{{OrderNumber}}’: ‘12345’
  };

  for (const placeholder in data) {
    body.replaceText(placeholder, data[placeholder]);
  }
  Logger.log(‘Placeholders replaced.’);
}

17.98. Generate Multiple Documents from Template

What it achieves: Creates multiple copies of a template document, each populated with different data.

function generateMultipleDocsFromTemplate() {
  const templateDocId = ‘YOUR_TEMPLATE_DOC_ID_HERE’; // ID of your template document
  const folderId = ‘YOUR_OUTPUT_FOLDER_ID_HERE’; // Folder where new docs will be saved

  const recipientsData = [
    { name: ‘Alice’, email: ‘alice@example.com’, amount: ‘$100’ },
    { name: ‘Bob’, email: ‘bob@example.com’, amount: ‘$150’ },
    { name: ‘Charlie’, email: ‘charlie@example.com’, amount: ‘$200’ }
  ];

  const templateFile = DriveApp.getFileById(templateDocId);
  const outputFolder = DriveApp.getFolderById(folderId);

  recipientsData.forEach(data => {
    const newDocName = `Invoice for ${data.name}`;
    const newDocFile = templateFile.makeCopy(newDocName, outputFolder);
    const newDoc = DocumentApp.openById(newDocFile.getId());
    const body = newDoc.getBody();

    body.replaceText(‘{{Name}}’, data.name);
    body.replaceText(‘{{Email}}’, data.email);
    body.replaceText(‘{{Amount}}’, data.amount);

    newDoc.saveAndClose();
    Logger.log(`Generated document for ${data.name}: ${newDoc.getUrl()}`);
  });
  Logger.log(‘Finished generating documents.’);
}

You need a template document with placeholders like {{Name}}, {{Email}}, {{Amount}} and an output folder in your Drive for this to work.

18. Advanced Document Structure

Scripts for manipulating more complex document elements.

18.99. Insert a Horizontal Rule (Line)

What it achieves: Inserts a horizontal line (HR) element into the document.

function insertHorizontalRule() {
  const body = DocumentApp.getActiveDocument().getBody();
  body.appendHorizontalRule();
  Logger.log(‘Horizontal rule inserted.’);
}

18.100. Get All Elements in Document (Iterate through types)

What it achieves: Iterates through every element in the document body and logs its type and some content. This is a powerful way to understand document structure.

function inspectDocumentElements() {
  const body = DocumentApp.getActiveDocument().getBody();
  const numChildren = body.getNumChildren();
  Logger.log(‘Inspecting Document Elements:’);

  for (let i = 0; i < numChildren; i++) {
    const child = body.getChild(i);
    const type = child.getType();
    Logger.log(`Element ${i + 1} Type: ${type}`);

    switch (type) {
      case DocumentApp.ElementType.PARAGRAPH:
        Logger.log(`  Text: “${child.asParagraph().getText().substring(0, 50)}…”`);
        break;
      case DocumentApp.ElementType.TABLE:
        Logger.log(`  Table with ${child.asTable().getNumRows()} rows.`);
        break;
      case DocumentApp.ElementType.LIST_ITEM:
        Logger.log(`  List Item: “${child.asListItem().getText().substring(0, 50)}…”`);
        break;
      case DocumentApp.ElementType.IMAGE:
        Logger.log(`  Image (Width: ${child.asImage().getWidth()}, Height: ${child.asImage().getHeight()})`);
        break;
      case DocumentApp.ElementType.HORIZONTAL_RULE:
        Logger.log(`  Horizontal Rule`);
        break;
      case DocumentApp.ElementType.PAGE_BREAK:
        Logger.log(`  Page Break`);
        break;
      // Add more cases for other element types as needed
      default:
        Logger.log(`  Unhandled Element Type: ${type}`);
        break;
    }
  }
  Logger.log(‘Document inspection complete.’);
}