Scriptdrill

Gmail, Drive and Calendar Updated November 2026

Create a Google Doc from a template

Make a copy of the template file with DriveApp.getFileById(templateId).makeCopy(name, folder), open the copy with DocumentApp.openById(copy.getId()), call body.replaceText("{{Name}}", value) for each placeholder, then doc.saveAndClose(). Loop sheet rows to create one document per row and write the document URL back into the sheet.

Syntax

DriveApp.getFileById(id).makeCopy(name, folder) then DocumentApp.openById(id).getBody().replaceText(pattern, replacement)
PartWhat it is
makeCopy(name, folder)New Drive file with that name in the folder; returns the File
replaceText(pattern, text)Pattern is a regular expression string, so escape special characters
doc.saveAndClose()Commits changes; needed before exporting or emailing
doc.getAs("application/pdf")Blob of the document as PDF

Examples

const template = DriveApp.getFileById("1Tmp...");
const folder = DriveApp.getFolderById("1Out...");
const copy = template.makeCopy("Offer for Ana", folder);
const doc = DocumentApp.openById(copy.getId());
const body = doc.getBody();
body.replaceText("{{Name}}", "Ana");
body.replaceText("{{Amount}}", "1,250.00");
doc.saveAndClose();
Logger.log(copy.getUrl());

Result: A new doc Offer for Ana with both placeholders replaced; its URL is logged

const sheet = SpreadsheetApp.getActiveSheet();
const rows = sheet.getRange(2, 1, sheet.getLastRow() - 1, 3).getValues();
rows.forEach((r, i) => {
  if (r[2]) return; // already has a URL
  const copy = template.makeCopy("Letter " + r[0], folder);
  const doc = DocumentApp.openById(copy.getId());
  doc.getBody().replaceText("{{Name}}", r[0]).replaceText("{{Date}}", Utilities.formatDate(new Date(), "Europe/Amsterdam", "d MMMM yyyy"));
  doc.saveAndClose();
  sheet.getRange(i + 2, 3).setValue(copy.getUrl());
});

Result: One letter per row without a URL; column C receives each document link

const pdf = doc.getAs("application/pdf").setName("Offer for Ana.pdf");
folder.createFile(pdf);
MailApp.sendEmail("ana@example.com", "Your offer", "Attached.", {attachments: [pdf]});

Result: PDF saved to the folder and emailed

Call saveAndClose and reopen, or use DriveApp.getFileById(id).getAs, to make sure the PDF has the latest text.

Common mistakes

  • Placeholders are not replaced: the text in the Doc is split across formatting runs (for example a typo corrected mid-word); retype the placeholder in one go without formatting changes.
  • replaceText with {{Total (USD)}} fails: parentheses are regex characters; escape them as \\( and \\) or keep placeholders to letters and underscores.
  • The exported PDF shows the old placeholders: the document was not saved; call doc.saveAndClose() before getAs.
  • Hundreds of copies hit the execution limit: process a batch per run and mark done rows, then continue on a trigger.

Practice Create a Google Doc from a template

These drills check your answer on live data, free, no account needed.

  • Truncate with an ellipsisIf `s` has at most `max` characters, return it unchanged. Otherwise keep the first `max - 1` characters and add the ellipsis character `"…"`, so the result is exactly `max` characters long. Count characters as Unicode code points, so a character outside the Basic Multilingual Plane, such as 𝒳, is never cut in half. `max` is at least 1.
  • Format moneyFormat `amount` as money in the given ISO currency code (like `"USD"` or `"JPY"`) and locale, the way `Intl.NumberFormat` does with `style: "currency"`. Each currency keeps its usual number of decimals, and each locale its own grouping.
  • Run tasks in sequence`tasks` is an array of functions; each returns a Promise or a plain value. Run them one at a time, in order, starting each only after the previous one has finished, and resolve with the array of their results. If a task fails, reject and do not start the remaining tasks. Tests run on a fake clock: `setTimeout`, `clearTimeout` and `Date.now` are simulated, so waits are instant and exact.

Questions

Can I replace placeholders in headers, footers and tables?

Tables are part of the body and are covered. Headers and footers are separate: call doc.getHeader().replaceText and doc.getFooter().replaceText too.

Can I do the same with a Slides or Sheets template?

Yes: SlidesApp.openById(id).replaceAllText(find, replace) for Slides; for Sheets, copy the file and write values with setValues.

Related

  • List files in DriveList Google Drive files with Apps Script: get a folder by id, iterate getFiles with hasNext and next, read name, URL, size and dates, include subfolders.
  • Send email from a sheetSend email from Google Sheets with Apps Script: MailApp.sendEmail and GmailApp.sendEmail with HTML body, cc and attachments, loop a list of recipients, quota.
  • Utilities.formatDateFormat dates in Google Apps Script with Utilities.formatDate: the time zone argument, Java pattern letters like yyyy MM dd HH mm, month names, MM versus mm.
  • Loop through rowsLoop through rows in Google Sheets with Apps Script: read the data once with getValues, loop the 2D array with for, for...of or forEach, then write back.

Previous: Gmail search and labelsNext: List files in Drive