How to clone a document page?

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?

Thank you in advance.

DocumentBuilder version: 8.0
Installation method: destop
OS: GNU/Linux, Debian 12

1 Like

Hi @str
I will check if these capabilities are provided in the API and get back to you.

Hi @Nikolas, thank you for trying to help me.

I tried with document.GetAllContentControls(), thinking it will return all content, not just paragraphs, but it returned an empty array.

I can’t find a way to get all elements in a document.

Nevermind, “content controls” are actually “form controls”. I thought they were “generic/non-specific-content-type controls”.

@str :saluting_face:

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```

OK, this is my final code:

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});
});

And I’m adding the document I’m using for testing. (114.1 KB)

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?

Thank you.

1 Like

@str
Sorry, I missed your post. :pleading_face:
The week has been extremely busy.
We’ll take a look, and I’ll get back to you.

@str

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)