I’m building a plugin/macro that can duplicate the content of a Word document, search&replace placeholders, and then append the new content as a new page of the existing document.
var document = Api.GetDocument(); // get current document
var elements = document.GetAllParagraphs(); // get all paragaph of current document
let newPage = Api.CreateParagraph(); // create a page break
newPage.AddPageBreak();
var clone = [newPage]; // start the cloned page with a page beak
elements.forEach(element => {
clone.push(element.Copy()); // clone the paragraph
});
document.InsertContent(clone); // apend the new page
This “works” if the page has only paragraphs (and shockingly, images), but not if the page contains any tables.
What’s the best way to clone a document and append it as a new page?
To retrieve tables, you can try using either this method (getalltables) or this one (getalltablesonpage).
And I also recommend looking into this method: (getelement).
The issue with GetAllParagraphs() and GetAllTables() is that I will not be able to clone a document, because I will not know in which order to push the different elements.
I was able to make it work this way:
var newPage = Api.CreateParagraph(); // create a page break
newPage.AddPageBreak();
var clone = [newPage]; // start the cloned page with a page beak
var document = Api.GetDocument(); // get current document
var element = null;
var i = 0;
while (element = document.GetElement(i)) { // walk though all elements in the document
i++;
clone.push(element.Copy()); // clone the paragraph, table, whatever
};
// @todo, position cursor at the end of the document
// document.???
// finally:
document.InsertContent(clone); // append all cloned elements to the document```
var contacts = [
{ firstName: 'John', lastName: 'Smith', email: 'john.smith@example.com', address: '123 Main St, Anytown, USA' },
{ firstName: 'Emily', lastName: 'Johnson', email: 'emily.johnson@example.com', address: '456 Elm St, Smalltown, USA' },
// and more...
];
var template = [];
var document = Api.GetDocument(); // get current document
var n = document.GetElementsCount();
// generate template based on current content
for (var i = 0; i < n; i++) {
var element = document.GetElement(i);
template.push(element.Copy());
};
// delete content as it's aleady in the template array
for (var i = n; i > 0; i--) { // delete fom bottom to top as walking through each element, skips half of them
var element = document.GetElement(i - 1);
element.Delete();
};
contacts.forEach(contact => {
let newPage = Api.CreateParagraph(); // create a page break
newPage.AddPageBreak();
var clone = [newPage]; // start the cloned page with a page beak
template.forEach(element => {
clone.push(element.Copy()); // copy each element of the template
});
document.InsertContent(clone); // apend the cloned content
// search and replace the injected template
document.SearchAndReplace({matchCase: false, searchString: "«FirstName»", replaceString: contact.firstName});
document.SearchAndReplace({matchCase: false, searchString: "«LastName»", replaceString: contact.lastName});
document.SearchAndReplace({matchCase: false, searchString: "«address»", replaceString: contact.address});
});
As you can see, it copies the table, the paragraphs inside the table, and even the image in the table, BUT not the image for the signature. What may I be doing wrong?
We have filed a bug for this behavior in the API builder.
“When pasting, the second element (drawing) is ignored.”
Possible solution:
Separately copy the specific image or change the drawing property to another one before copying.
var oDocument = Api.GetDocument()
var arrDrawings = oDocument.GetAllDrawingObjects()
var oDrawing = arrDrawings[1].Copy()
oDocument.GetElement(0).AddDrawing(oDrawing)