Fill Doc Template

A Doc full of {{Client}} and {{Amount}} placeholders, a sheet row with those headers, and a Drive folder for the finished copies. fillDocTemplate(templateId, folder, rowObj) copies the template into the folder, replaces every {{key}} with the matching value from the row object (blank if the key is missing), and returns the new file's URL.

When to use

  • One filled Doc per sheet row: invoices, offer letters, client kickoffs
  • A shared template that non-coders edit in Docs, while the script only fills values
  • Writing the resulting link back into the sheet so the row points at its Doc

How to use this snippet

/** * Copy a Docs template into a folder and fill {{placeholders}} from a row object. * Missing keys become blank. Returns the new file's URL. * * @param {string} templateId Drive file id of the template Doc * @param {Folder|string} folder destination Folder, or its id * @param {Object} rowObj keys match placeholder names (header → value) * @return {string} URL of the filled copy */ function fillDocTemplate(templateId, folder, rowObj) { rowObj = rowObj || {}; var folderObj = typeof folder === 'string' ? DriveApp.getFolderById(folder) : folder; var copy = DriveApp.getFileById(templateId).makeCopy(folderObj); var doc = DocumentApp.openById(copy.getId()); var body = doc.getBody(); var keys = {}; var text = body.getText(); var re = /\{\{\s*([^{}]+?)\s*\}\}/g; var m; while ((m = re.exec(text)) !== null) keys[m[1].trim()] = true; Object.keys(keys).forEach(function (key) { var val = Object.prototype.hasOwnProperty.call(rowObj, key) ? rowObj[key] : ''; if (val == null) val = ''; body.replaceText('\\{\\{\\s*' + key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '\\s*\\}\\}', String(val)); }); doc.saveAndClose(); return copy.getUrl(); }

Example

function fillInvoiceForRow(row) { var folderId = PropertiesService.getScriptProperties().getProperty('INVOICE_FOLDER'); var url = fillDocTemplate('1abcTEMPLATE', folderId, row); DriveApp.getFileById(extractDriveFileId(url)) .setName('Invoice ' + row.InvoiceId + ' — ' + row.Client); return url; } // Template body: "Invoice {{InvoiceId}} for {{Client}}: ${{Amount}}" // row = { InvoiceId: 'INV-9', Client: 'Ada', Amount: '1200' }

Tips:

  • Placeholders are matched by exact key, with optional spaces inside the braces ({{ Client }} works). Unknown keys write a blank, so typos in the template show up as empty spots instead of leftover {{Tyop}}.
  • The copy keeps Drive's default name (Copy of …). Rename it after, from a column on the row, so filenames stay searchable.
  • folder accepts a Folder object or an id string. Pass the object when you're already iterating a folder tree.
  • Pair with extractDriveFileId when you need the id back from the URL to setName or share.

Tip: NitroGAS keeps fillDocTemplate in the snippet catalog. Paste your template's placeholder list and ask Co-Pilot to wire the sheet headers to the call.

Happy Coding!

NitroGAS Chrome Extension

Want this snippet handy inside the Apps Script editor? NitroGAS gives you free snippets — plus optional Co-Pilot when you want a boost (Day Pass — $3, or 1-week, 1-month, or yearly passes — no subscription). Happy Coding!

Get the Extension