I’m working with Google Apps Script to insert/copy text from one Google Document into another. These text can include various types of content, including bullet and numbered lists. However, I’m encountering two issues:
- When inserting a bullet list, all bullet icons are not preserved, resulting in a plain list without the intended bullet styling.
- When inserting a numbered list, the numbering continues from the last number, rather than restarting from 1. For example, if I insert a text with a list numbered from 1 to 5, and then insert it again, it continues numbering from 6 instead of restarting from 1.
Original document
After Insert
Bellow is my code and I have attached screenshots of original document and when inserting/copying that into new document.
I am expecting that when inserting the clause/text it should preserve as it is with original list formatting which is there in original document shared in screenshots.
How to Use:
- Create a new Google Apps Script project and paste the above code.
- Save and authorize the script.
- Run the script in any Google Document to test it out. The script will add a “Clause Manager” menu from which you can insert clauses by providing a Document ID.
This script should work as an add-on that you can use directly in any Google Document.
function onOpen() {
DocumentApp.getUi().createMenu('Clause Manager')
.addItem('Insert Clause', 'insertClause')
.addToUi();
}
function insertClause() {
const ui = DocumentApp.getUi();
const response = ui.prompt('Enter the Clause Document ID:');
if (response.getSelectedButton() == ui.Button.OK) {
const clauseId = response.getResponseText();
const document = DocumentApp.getActiveDocument();
const cursor = document.getCursor();
if (!cursor) {
ui.alert('Cannot find a cursor in the document.');
return;
}
const element = cursor.getElement();
insertClauseInsideDocumentBody(document, element, clauseId, 'ClauseName');
}
}
function insertClauseInsideDocumentBody(document, element, clauseId, clauseName) {
try {
const documentBody = document.getBody();
let index = documentBody.getChildIndex(element);
const clauseDocument = DocumentApp.openById(clauseId);
const clauseBody = clauseDocument.getBody();
if (clauseBody.getNumChildren() === 0) {
DocumentApp.getUi().alert('The clause document is empty.');
return;
}
const clauseElements = [];
for (let i = 0; i < clauseBody.getNumChildren(); i++) {
const child = clauseBody.getChild(i);
const childContent = child.copy();
let clauseElement;
switch (child.getType()) {
case DocumentApp.ElementType.PARAGRAPH: {
const paraElement = documentBody.insertParagraph(index, childContent);
clauseElement = paraElement;
index++;
break;
}
case DocumentApp.ElementType.LIST_ITEM: {
const listElement = documentBody.insertListItem(index, childContent);
listElement.setAttributes(child.getAttributes());
clauseElement = listElement;
index++;
break;
}
case DocumentApp.ElementType.TABLE: {
const tableElement = documentBody.insertTable(index, childContent);
clauseElement = tableElement;
index++;
break;
}
case DocumentApp.ElementType.INLINE_IMAGE: {
const imageElement = documentBody.insertImage(index, childContent);
clauseElement = imageElement;
index++;
break;
}
default:
clauseElement = null;
break;
}
if (clauseElement) {
clauseElements.push(clauseElement);
}
}
const rangeBuilder = document.newRange();
rangeBuilder.addElementsBetween(clauseElements[0].editAsText(), 1, clauseElements[clauseElements.length - 1].editAsText(), clauseElements[clauseElements.length - 1].editAsText().getText().length - 1);
document.addNamedRange(clauseName, rangeBuilder.build());
DocumentApp.getUi().alert('Clause inserted successfully.');
} catch (error) {
DocumentApp.getUi().alert('An error occurred: ' + error.message);
}
}
Pankaj Sakhare is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.