function onOpen() { const ui = SpreadsheetApp.getUi(); ui.createMenu('CMS Document Generation') .addItem('Generate document for current row', 'generateForCurrentRow') .addToUi(); } function copyElement( source_element: GoogleAppsScript.Document.Element, dest: GoogleAppsScript.Document.Body, index?: number ) { const element = source_element.copy(); // based on https://stackoverflow.com/questions/6783819/google-app-script-copy-document-page if (element.getType() == DocumentApp.ElementType.PARAGRAPH) if (index) dest.insertParagraph(index, element.asParagraph()); else dest.appendParagraph(element.asParagraph()); else if (element.getType() == DocumentApp.ElementType.TABLE) if (index) dest.insertTable(index, element.asTable()); else dest.appendTable(element.asTable()); else if (element.getType() == DocumentApp.ElementType.LIST_ITEM) if (index) dest.insertListItem(index, element.asListItem()); else dest.appendListItem(element.asListItem()); else if (element.getType() == DocumentApp.ElementType.INLINE_IMAGE) if (index) dest.insertImage(index, element.asInlineImage()); else dest.appendImage(element.asInlineImage()); else throw new Error( "According to the doc this type couldn't appear in the body: " + element.getType() ); } function copyBody( source: GoogleAppsScript.Document.Body, dest: GoogleAppsScript.Document.Body, index?: number ) { var totalElements = source.getNumChildren(); for (var j = 0; j < totalElements; ++j) { if (index) copyElement(source.getChild(j), dest, index + j); else copyElement(source.getChild(j), dest); } } function generateForCurrentRow() { const cell = SpreadsheetApp.getActive().getCurrentCell(); const template = DocumentApp.openById( '1V0uMuM80BGpjpdt1AmuzlU97tDI_u-y2rOfdl4tkqmc' ); const source_doc = DocumentApp.openById( '1tB9--ilbfDixuQAEMk0_D6KqNFToQzs-au6NiotCH5M' ); const out_doc = template; // TODO: make a copy of template, and write to that const insert_point = out_doc .getBody() .findText('{{body}}') ?.getElement(); if (!insert_point) { throw new Error("Could not find insert point '{{body}}'"); } // find the parent element that is a direct descendant of the body let parent = insert_point; while (parent.getParent().getType() != DocumentApp.ElementType.BODY_SECTION) { parent = parent.getParent(); } const index = out_doc.getBody().getChildIndex(parent); // insert with index 0 is an append, for some reason copyBody(source_doc.getBody(), out_doc.getBody(), index + 1); out_doc.getBody().removeChild(parent); }