As the title suggests I am trying to find the index of a placeholder text element in a google doc table so that I can replace it with text stored in a different doc.
I can get the pre-formatted text to be added to the document - not the place in the table required - using other examples I have found on stackoverflow.
However I am unclear as how to find the index of the placeholder element within one of many tables in the template document.
I need the index of the placeholder text to be able to use the insertParagraph function.
To add slightly more detail: I am able to find the placeholder text and insert an image using the below code.
function replaceTextToImage(body, searchText, image, width) {
var next = body.findText(searchText);
if (!next) return;
var r = next.getElement();
r.asText().setText("");
var img = r.getParent().asParagraph().insertInlineImage(0, image);
if (width && typeof width == "number") {
var w = img.getWidth();
var h = img.getHeight();
img.setWidth(width);
img.setHeight(width * h / w);
}
return next;
};
However, I need to preserve the formatting of the doc I want to import. So I open the document with the formatted text and then loop through the different element types with a conditional to insert the text/image if the element type is matched. This is why I need the index of the placeholder text. See for function below:
function replaceTextWithDoc(body, searchText, id) {
let doc = DocumentApp.openById(id)
var numElements = body.getNumChildren();
var index = numElements;
for (var i = 0; i < numElements; i ) {
var child = body.getChild(i);
if (child.asText().getText() == searchText){
index = i;
body.removeChild(child);
break;
}
}
var totalElements = doc.getNumChildren();
for( var j = 0; j < totalElements; j ) {
var element = doc.getChild(j).copy();
var type = element.getType();
if( type == DocumentApp.ElementType.PARAGRAPH )
body.insertParagraph(index, element);
else if( type == DocumentApp.ElementType.TABLE )
body.insertTable(index, element);
else if( type == DocumentApp.ElementType.LIST_ITEM )
body.insertParagraph(index, element);
else
throw new Error("According to the doc this type couldn't appear in the body: " type);
}
}
Here is an example of the placeholder text ( {iText} ) in a table: https://docs.google.com/document/d/1mZWpQqk4gYAF6UCRALrT8S99-01RYNfwni_kqDzOg7E/edit?usp=sharing
Here is an example of text and images that I need to replace the placeholder text with - maintaining all/any formatting. https://docs.google.com/document/d/1wuX0g5W2GL0YJ7admiv3TNEepb_zVwQleKwazCiAMBU/edit?usp=sharing
CodePudding user response:
Issue:
If I understand you correctly, you want to copy the contents of one document (made up of text and inline images) to certain table cells that contain a certain placeholder text.
Solution:
In that case, I'd suggest the following:
- Iterate through all tables in the target document, using Body.getTables().
- For each table, iterate through all its cells.
- For each cell, check whether its text contains the placeholder.
- If the placeholder is included, clear the current cell content via TableCell.clear().
- Iterate through all source document elements (see for example, this answer).
- For each element, check its type (Element.getType()).
- If the element is a paragraph, append the paragraph to the cell via TableCell.appendParagraph.
- If the element is an image, append it via TableCell.appendImage.
Code sample:
const PLACEHOLDER = "{iText}";
function myFunction() {
const doc = DocumentApp.openById(TARGET_ID);
const sourceDoc = DocumentApp.openById(SOURCE_ID);
const body = doc.getBody();
const tables = body.getTables();
tables.forEach(table => {
const numRows = table.getNumRows();
for (let i = 0; i < numRows; i ) {
const row = table.getRow(i);
const numCells = row.getNumCells();
for (let j = 0; j < numCells; j ) {
const cell = row.getCell(j);
const cellText = cell.editAsText();
const text = cellText.getText();
if (text.includes(PLACEHOLDER)) {
cell.clear();
appendSourceContent(sourceDoc, cell);
}
}
}
});
}
function appendSourceContent(doc, cell) {
const numChildren = doc.getNumChildren();
for (let j = 0; j < numChildren; j ) {
const element = doc.getChild(j).copy();
const type = element.getType();
if (type == DocumentApp.ElementType.PARAGRAPH) {
cell.appendParagraph(element);
} else if (type == DocumentApp.ElementType.INLINE_IMAGE) {
cell.appendImage(element);
}
}
}
Note:
- Add additional
else if
blocks if the source content can have differentElementTypes
than paragraphs and inline images. - I assumed that you want to preserve none of the current content in the table cell.