Aspose.Word insert building block inside a document

Hello,

I need to insert a BuildingBlock’s content inside a document, however there are several requirements:

  1. I can’t insert it directly because it would insert a new section inside the document (and i want to insert it without creating any new section)

  2. The insertion has to be done at the cursor’s position (wich can be the current node/paragraph/section regarding wich one is null)

  3. I need to have the same behaviour as word, one specific example is inserting a paragraph containing a form feed caracter inside a cell.

  4. Once the insertion is done, the cursor needs to be moved to the correct position, as world would have done.

I have tried to do it but for now i have to manage every case possible (insert a node/paragraph/etc. inside a table/paragraph/etc.).
Is there a proper way to do it ?
It is especially hard to mimic word’s behaviour when it comes to insert a node at a specific location.

Sincerely.

@aaronArchest Inserting a building block is a process of importing and inserting nodes from one document to another. Please see our documentation to learn how to achieve this:
https://docs.aspose.com/words/net/insert-and-append-documents/#import-and-insert-nodes-manually

If you have specific requirements for inserting some building blocks it would be good if you attach your building block and target documents along with the code you use, current and expected result. We will check the issue and provide you more information.

In this example, i’m trying to insert a buildingblock at a bookmark’s position, you can see the result when i do it inside word :

and here is what i do programmatically :

mybuilder.MoveToBookmark("myBookMark", false, true);

then i call the following method to insert the buildingBlock

public static ArrayList insertBuildingBlockAtCurrentParagraph(BuildingBlock pBuildingblock, DocumentBuilder pBuilder)
{
    var res = new ArrayList();
    //
    foreach (Section section in pBuildingblock.Sections)
    {
        var importedSection = (Section)pBuilder.Document.ImportNode(section, true, ImportFormatMode.KeepDifferentStyles);
        //
        int childNodesCount = importedSection.Body.ChildNodes.Count;
        for (int i = 0; i < childNodesCount; i++)
        {
            var SectionChild = importedSection.Body.ChildNodes[0];
            //
            if (SectionChild.NodeType == NodeType.Paragraph)
            {
                insertionParagraphe(pBuilder, (Paragraph)SectionChild, res);
            }
            else if (SectionChild.NodeType == NodeType.Table)
            {
                insertionTable(pBuilder, (Table)SectionChild, res);
            }
            else
            {
                pBuilder.InsertNode(SectionChild);
                res.Add(SectionChild);
            }
        }
    }
    // Move to the end of the insertion
    if (res.Count > 0)
    {
        Node lastNodeInserted = (Node)res[res.Count - 1];
        if (lastNodeInserted is Row)
        {
            pBuilder.MoveTo(((Row)lastNodeInserted).LastCell.LastChild);
        }
        else
        {
            pBuilder.MoveTo(lastNodeInserted.NextSibling);
        }
    }
    //
    pBuilder.Document.UpdatePageLayout();
    return res;
}

private static void insertionTable(DocumentBuilder pBuilder, Table pTable, ArrayList pAddedNodes)
{
    if (pBuilder.CurrentParagraph.ParentNode.NodeType == NodeType.Cell)
    {
        // not relevant here
    }
    else
    {
        var newTable = pBuilder.StartTable();
        pBuilder.EndTable();
        foreach (Row row in pTable.Rows)
        {
            var newRow = pTable.RemoveChild(row);
            newTable.Rows.Add(newRow);
        }
        pTable.Remove();
        pAddedNodes.Add(newTable);
    }
}

however the final result is a bit different, the most problematic thing beeing that the bookmark’s position changed

Here is the test file
File.zip (17.8 KB)

Sincerely.

@aaronArchest You can use DocumentBuilder.InsertDocument to simplify your code. Please try using the following code:

Document doc = new Document(@"C:\Temp\in.dot");
DocumentBuilder builder = new DocumentBuilder(doc);

builder.MoveToBookmark("myBookMark", false, true);
InsertBuildingBlockAtCurrentParagraph(doc.GlossaryDocument.BuildingBlocks[0], builder);

builder.Write("This text will be inserted after buildng block");

doc.Save(@"C:\Temp\out.docx");
public static void InsertBuildingBlockAtCurrentParagraph(BuildingBlock pBuildingblock, DocumentBuilder pBuilder)
{
    Document tmp = (Document)pBuilder.Document.Clone(false);
    foreach (Section section in pBuildingblock.Sections)
        tmp.AppendChild(tmp.ImportNode(section, true, ImportFormatMode.KeepDifferentStyles));

    pBuilder.InsertDocument(tmp, ImportFormatMode.KeepSourceFormatting);

    // Move DocumentBuilder cursor the the previous paragraph.
    Paragraph currentParagraph = pBuilder.CurrentParagraph;
    Paragraph prevParagraph = (Paragraph)currentParagraph.PreviousSibling;
    pBuilder.MoveTo(prevParagraph);
    while (currentParagraph.HasChildNodes)
        prevParagraph.AppendChild(currentParagraph.FirstChild);
    currentParagraph.Remove();
}
1 Like

thank you so much, worked like a charm !

1 Like

Here is a new case while using the code you provided :

I try to insert an other autotext after a bookmark but this time inside a table. As you can see, with word, a new line is inserted and the bookmark is moved back down

but when i do it programmatically, the whole autotext seems to be inserted inside the cell containing the bookmark

Here is the file used in this example Original.zip (26.8 KB)

Sincerely.

@aaronArchest In this case it is required to use another approach. It is required to insert rows into the table before the row with bookmark. For example see the following code:

Document doc = new Document(@"C:\Temp\in.doc");

// Get the table that should be inserted.
Table tableToInsert = doc.FirstSection.Body.Tables[1];

// Get the row where the bookmark is located.
Row targetRow = (Row)doc.Range.Bookmarks["DebutPaillassePrlvt"].BookmarkStart.GetAncestor(NodeType.Row);

foreach (Row r in tableToInsert.Rows)
{
    // Insert copy of the row before the target row.
    targetRow.ParentNode.InsertBefore(r.Clone(true), targetRow);
}

doc.Save(@"C:\Temp\out.doc");

out.zip (23.1 KB)

1 Like

With this solution, if i need to insert several times a table containing a bookmark, the newly inserted bookmark will have its name changed (a number is added at the end) and the older bookmark is kept inside the document.
However in word, the old bookmark will be destroyed :

Is this behaviour normal ? If so, is there a way to disable it or do i have to check for every node before inserting it and delete some bookmarks if there might be a conflict ?

Sincerely.

@aaronArchest Aspose.Words preserves bookmarks by renaming them. If you do not need to preserve bookmarks, you can remove them before inserting content into the target document.

1 Like