Google Apps Script not replacing placeholders when copying template document from sheet data

Issue with Document Template Population

I’m working on a script that should create new Google Docs from a template using data from a Google Sheet. The script runs without errors and successfully creates new documents with the right names, but the placeholder text isn’t getting replaced with actual data from the spreadsheet.

My Current Script

function setupMenu() {
  const interface = SpreadsheetApp.getUi();
  const customMenu = interface.createMenu('Document Generator');
  customMenu.addItem('Generate Documents', 'generateDocsFromSheet');
  customMenu.addToUi();
}

function generateDocsFromSheet() {
  const templateDoc = DriveApp.getFileById('your-template-id-here');
  const targetFolder = DriveApp.getFolderById('your-folder-id-here');
  const activeSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Survey Results');
  const dataRows = activeSheet.getDataRange().getValues();

  dataRows.forEach(function(currentRow, rowIndex){
    if (rowIndex === 0) return; // Skip header
    if (currentRow[6]) return; // Skip if already processed
    
    const newDoc = templateDoc.makeCopy(`${currentRow[0]} Profile Document`, targetFolder);
    const document = DocumentApp.openById(newDoc.getId());
    const docBody = document.getBody();

    docBody.replaceText('{{Student Name}}', currentRow[0]);
    docBody.replaceText('{{Pronouns}}', currentRow[1]);
    docBody.replaceText('{{Personal Email}}', currentRow[2]);
    docBody.replaceText('{{School Email}}', currentRow[3]);
    docBody.replaceText('{{Phone Number}}', currentRow[4]);
    docBody.replaceText('{{Additional Notes}}', currentRow[5]);

    document.saveAndClose();
    const documentUrl = document.getUrl();
    activeSheet.getRange(rowIndex + 1, 7).setValue(documentUrl);
  });
}

Template Structure

My template document contains:

  • Name: {{Student Name}} ({{Pronouns}})
  • Contact: {{Personal Email}}
  • School Email: {{School Email}}
  • Phone: {{Phone Number}}
  • Notes: {{Additional Notes}}

The spreadsheet columns match up correctly but nothing gets replaced. What could be causing this problem?

Your code’s probably trying to open the document too fast after copying it. Google Docs needs a second to make the copy available - I’ve hit this bug tons of times.

Add Utilities.sleep(500) between makeCopy() and DocumentApp.openById(). Also throw in SpreadsheetApp.flush() after you set the URL value so the sheet actually updates.

One more thing - double-check your template has the exact placeholder text. Google Docs loves to split text runs when you edit stuff, especially placeholders. Just retype them fresh in the template without any formatting.

Been dealing with this exact headache for years. Google Apps Script has weird timing quirks and gets clunky with lots of documents.

Your placeholders are probably fine, but GAS doesn’t always flush changes properly. The real problem? You’re manually managing API calls and timing issues.

I ditched GAS and automated the whole workflow instead. Set up triggers that watch your Google Sheet for new rows, then auto-generate docs with proper error handling and retry logic. No more timing issues or failed replacements.

The automation handles document creation, placeholder replacement, and updates your sheet with final URLs. Plus you get proper logging to see exactly what broke.

Way cleaner than debugging GAS timing issues and sleep statements. Set it up once and forget about it.

I had the same problem with placeholders not getting replaced. Turns out the document copy wasn’t ready for editing right after makeCopy(). Here’s what fixed it: I restructured my workflow. Instead of opening the document immediately after copying, I process all the data first, then handle document operations in a separate loop. This gives Google Drive time to create the copy properly before you try modifying it. Also check your replaceText() calls - they need to handle cases where spreadsheet cells have formulas or formatted numbers. I’ve seen cells that look like plain text but actually contain formula references, making replacement fail silently. Converting everything to strings with toString() before replacement fixed those edge cases for me. Your script structure looks fine, so it’s probably a timing or data type issue, not logic problems.

This is probably a timing issue. You’re calling document.saveAndClose() right after the replace operations, but Google Apps Script needs a second to process those text replacements. I ran into this exact same problem on a project last year.

Try throwing in Utilities.sleep(1000) before document.saveAndClose() - gives the replacements time to finish. Also double-check that your template placeholders don’t have weird formatting or hidden characters. Copy-pasting from other sources loves to sneak in invisible Unicode stuff that breaks exact matching.

One more thing - make sure your spreadsheet data doesn’t have null or undefined values. replaceText() gets weird with those. Adding null checks like currentRow[0] || '' in your replace statements handles empty cells way better.

check for trailing spaces or line breaks in your sheet data - they’ll mess up replaceText matching. try getDisplayValue() instead of raw cell values since formatting can break replacements. i hit this same issue last month and it was weird whitespace characters in some cells.