Numbering Formatting lost in document

I have a problem with numbering formating durring proccesing of the word document.
I load some word document that contains numbering format (See attachment). I run through all word bookmarks and perform the following code:

mDocument.Range.Bookmarks["START" + wField.Id].Text = mDocument.Range.Bookmarks["START" + wField.Id].Text.Replace("[", " ").Replace("]", " ");

As you can see from the attachment Bookmark text in VS does not contain numering.
Is this a bug? Or i am doing something wrong?

Hi
Thanks for your request. no, this is not a bug. List labels are no stored in the document, they are calculated by MS Word on the fly. That is why you do not see them.
If you need to get a list label of the paragraph, you can use Paragraph.ListLabel property:
https://reference.aspose.com/words/net/aspose.words/paragraph/listlabel/
Hope this helps.
Best regards,

The problem is that after i run the code that i mentioned in the post and save the document, word desnt calculates the numbering anymore. When i open this document with word the numbering is not shown.
See attachment (before and after).
How can i solve this problem? All that i need is to remove brackets [ ] from the begining and from the end of the bookmark text?

Hello

Thanks for your request. The brackets around bookmark are invisible during rendering/printing etc. It is MS Word options. If you would like to hide brackets, you should go to “Word Options” -> “Advanced” and uncheck “Show Bookmarks” option. After these changes, brackets will become invisible in MS Word.
Best regards,

These are not word bookmark brackets. These are brackets that we are adding in code to emphasize to the user where he can enter a text. This part is done in client side where we are using word. At the end of the process we are removing them in code. The code that removes these brackets will run in server and we want to use aspose for that. But we encountered several problems that we are trying to solve.

Hello

Thanks for your request. Could you please attach your input and output documents here? I will investigate the issue and provide you more information.
Best regards,

Sure,
see attachments.

Hello
Thank you for additional information. Please try using the suggestions provided here:
https://forum.aspose.com/t/70321
Best regards,

Thank you.

That is exactly the problem here. When i am removing brackets from bookmark that points to the text with numbering and save the document, numbering is not displayed anymore. Did you succeeded to reproduce this problem with the attached document?

Hello

Thanks for your inquiry. Please try using the following code:

foreach(Bookmark bookmark in doc.Range.Bookmarks)
{
    Node curNode = bookmark.BookmarkStart;
    while (curNode != null && !curNode.Equals(bookmark.BookmarkEnd))
    {
        // Move to next node
        Node nextNode = curNode.NextPreOrder(doc);
        // Check whether current contains end node
        if (curNode.IsComposite)
        {
            if (!((CompositeNode) curNode).GetChildNodes(NodeType.Any, true).Contains(bookmark.BookmarkEnd) &&
                !((CompositeNode) curNode).GetChildNodes(NodeType.Any, true).Contains(bookmark.BookmarkStart))
            {
                nextNode = curNode.NextSibling;
                curNode.Range.Replace(new Regex("[\\[\\]]"), " ");
            }
        }
        else
        {
            curNode.Range.Replace(new Regex("[\\[\\]]"), " ");
        }
        curNode = nextNode;
    }
}

Best regards,

Thank you very much!

This code looks very promising. Looks like it solved all problems i mentioned before (numbering, scroll and right to left issue). I will perform more testing next week. Thank you again.

Just another question regarding the numbering format. Is there a way to copy all bookmark text including formating (like numbering) from one bookmark to another?

Hello

Thanks for your inquiry. Of course, Aspose.Words provides functionality for easy copying and moving fragments between Microsoft Word documents. This is known as “importing nodes”. Before you can insert a fragment from one document into another, you need to “import” it. Importing creates a deep clone of the original node, ready to be inserted into the destination document.
Please see the following link to learn more about NodeImporter:
https://reference.aspose.com/words/net/aspose.words/nodeimporter/
Hope this helps.
Best regards,

Oh, i don’t mean copying fragments between different documents. I talking about copying bookmark’s content from one bookmark to another within the same document, but i cant use bookmark’s 'Text" property because in this way i cant copy formating (like numbering). Is there a way copy all it’s content including formating?

i tried ti use the following code example that i found on this forum:

https://forum.aspose.com/t/74740

https://forum.aspose.com/t/114203

public Document ExtractContentFromBookmark(Document srcDoc, string bookmarkName)
{
    Bookmark bookmark = srcDoc.Range.Bookmarks[bookmarkName];
    if (bookmark == null)
        throw new Exception("There is no bookmark with specified name");

    Paragraph startNode = (Paragraph)bookmark.BookmarkStart.GetAncestor(NodeType.Paragraph);
    Paragraph endNode = (Paragraph)bookmark.BookmarkEnd.GetAncestor(NodeType.Paragraph);

    // Make sure that start and end nodes are children of the same story.
    if (!startNode.ParentNode.Equals(endNode.ParentNode))
        throw new Exception("Start and end nodes should be children of the same story");

    // Clone the original document, this is needed to preserve styles of the original document
    Document dstDoc = srcDoc.Clone();
    dstDoc.RemoveAllChildren();

    // The destination document should contain at lean one section.
    dstDoc.EnsureMinimum();
    dstDoc.FirstSection.Body.RemoveAllChildren();

    // We will use NodeImporter to import nodes from one document to another.
    NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.UseDestinationStyles);

    Node currNode = startNode;
    Node dstNode;
    // Copy content
    while (currNode != null && !currNode.Equals(endNode))
    {
        // Import node
        dstNode = importer.ImportNode(currNode, true);

        dstDoc.LastSection.Body.AppendChild(dstNode);

        // Move to the next node
        Node nextNode = currNode.NextSibling;
        // Move to the next section
        if (nextNode == null && currNode.ParentNode.NodeType == NodeType.Body)
        {
            Node sect = currNode.GetAncestor(NodeType.Section);
            if (sect.NextSibling != null)
            {
                dstNode = importer.ImportNode(sect.NextSibling, true);
                dstDoc.AppendChild(dstNode);
                dstDoc.LastSection.Body.RemoveAllChildren();
                nextNode = ((Section)sect.NextSibling).Body.FirstChild;
            }
        }

        currNode = nextNode;
    }
    // If the bookmark end is the last child of the last paragraph we need to copy it as well.
    if (endNode.LastChild.Equals(bookmark.BookmarkEnd))
    {
        dstNode = dstDoc.ImportNode(endNode, true, ImportFormatMode.UseDestinationStyles);
        dstDoc.LastSection.Body.AppendChild(dstNode);
    }

    dstDoc.Save("C:\Temp\Temp.doc");

    return dstDoc;
}

public void InsertDocumentAtBookmark(string bookmarkName, Document dstDoc, Document srcDoc)
{
    NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.UseDestinationStyles);
    // Create DocumentBuilder
    DocumentBuilder builder = new DocumentBuilder(dstDoc);
    // Move cursor to bookmark and insert paragraph break
    builder.MoveToBookmark(bookmarkName);
    builder.Writeln();
    // If current paragraph is a list item, we should clear its formating.
    if (builder.CurrentParagraph.IsListItem)
        builder.ListFormat.RemoveNumbers();
    // Content of srcdoc will be inserted after this node
    Node insertAfterNode = builder.CurrentParagraph.PreviousSibling;
    // Content of first paragraph of srcDoc will be apended to this parafraph
    Paragraph insertAfterParagraph = null;
    if (insertAfterNode.NodeType == NodeType.Paragraph)
        insertAfterParagraph = (Paragraph)insertAfterNode;
    // Content of last paragraph of srcDoc will be apended to this parafraph
    Paragraph insertBeforeParagraph = builder.CurrentParagraph;
    // We will be inserting into the parent of the destination paragraph.
    CompositeNode dstStory = insertAfterNode.ParentNode;
    // Remove empty paragraphs from the end of document
    while (!((CompositeNode)srcDoc.LastSection.Body.LastChild).HasChildNodes)
    {
        srcDoc.LastSection.Body.LastParagraph.Remove();
        if (srcDoc.LastSection.Body.LastChild == null)
            break;
    }
    // Loop through all sections in the source document.

    foreach (Section srcSection in srcDoc.Sections)
    {
        // Loop through all block level nodes (paragraphs and tables) in the body of the section.
        for (int nodeIdx = 0; nodeIdx < srcSection.Body.ChildNodes.Count; nodeIdx++)
        {
            Node srcNode = srcSection.Body.ChildNodes[nodeIdx];
            // Do not insert node if it is a last empty paragarph in the section.
            Paragraph para = null;
            if (srcNode.NodeType == NodeType.Paragraph)
                para = (Paragraph)srcNode;

            if ((para != null) && para.IsEndOfSection && (!para.HasChildNodes))
                break;

            // If current paragraph is first paragraph of srcDoc
            // then appent its content to insertAfterParagraph
            bool nodeInserted = false;
            if (para != null && para.Equals(srcDoc.FirstSection.Body.FirstChild))
            {
                nodeInserted = true; // set this flag to know that we already processed this node.
                for (int i = 0; i < para.ChildNodes.Count; i++)
                {
                    Node node = para.ChildNodes[i];
                    Node dstNode = importer.ImportNode(node, true);
                    insertAfterParagraph.AppendChild(dstNode);
                }

                // If subdocument contains only one paragraph
                // then copy content of insertBeforeParagraph to insertAfterParagraph
                // and remove insertBeforeParagraph
                if (srcDoc.FirstSection.Body.FirstParagraph.Equals(srcDoc.LastSection.Body.LastChild))
                {
                    while (insertBeforeParagraph.HasChildNodes)
                        insertAfterParagraph.AppendChild(insertBeforeParagraph.FirstChild);

                    insertBeforeParagraph.Remove();
                }
            }
            // If current paragraph is last paragraph of srcDoc
            // then appent its content to insertBeforeParagraph
            if (para != null && para.Equals(srcDoc.LastSection.Body.LastChild))
            {
                nodeInserted = true; // set this flag to know that we already processed this node.
                Node previouseNode = null;
                for (int i = 0; i < para.ChildNodes.Count; i++)
                {
                    Node node = para.ChildNodes[i];
                    Node dstNode = importer.ImportNode(node, true);
                    if (previouseNode == null)
                        insertBeforeParagraph.InsertBefore(dstNode, insertBeforeParagraph.FirstChild);
                    else
                        insertBeforeParagraph.InsertAfter(dstNode, previouseNode);

                    previouseNode = dstNode;
                }
            }

            if (!nodeInserted)
            {
                // This creates a clone of the node, suitable for insertion into the destination document.
                Node newNode = dstDoc.ImportNode(srcNode, true);
                // Insert new node after the reference node.
                dstStory.InsertAfter(newNode, insertAfterNode);
                insertAfterNode = newNode;
            }
        }
    }
}

I used it in this way:

private void button2_Click(object sender, EventArgs e)
{
    Document doc = new Document("C:\Temp\Source.doc");
    DocumentBuilder builder = new DocumentBuilder(doc);

    builder.MoveToBookmark("START12634388900839794510F");

    Document docTmp = ExtractContentFromBookmark(doc, "START23634388903025253034F");

    InsertDocumentAtBookmark("START12634388900839794510F", doc, docTmp);

    doc.Save("C:\Temp\AfterCopy.doc");
}

But i got several problems.

  1. Numbering is wrong.
  2. Last line lost its bullets.

Please see an attachment

Can you please check what is wrong with a code?

i succeed to solve the problem that i mentioned in previous post with the another code that i found on this forum. My goal is to take bookmark’s content with all formating and append it to another bookmark (that already may have some content). I am using for this the following code:

private void button3_Click(object sender, EventArgs e)
{
    Document doc = new Document("C:\Temp\Source2.doc");

    Document docTmp1 = ExtractContentFromBookmark(doc, "START57634309578388128307F");
    Document docTmp2 = ExtractContentFromBookmark(doc, "START93634390078433273520F");

    docTmp1.AppendDocument(docTmp2, ImportFormatMode.KeepSourceFormatting);

    doc.Range.Bookmarks["START92634390078323432537F"].Text = " ";

    InsertDocumentAtBookmark("START92634390078323432537F", doc, docTmp1);

    doc.Save("C:\Temp\AfterCopy4.doc");
}

public Document ExtractContentFromBookmark(Document srcDoc, string bookmarkName)
{
    Bookmark bookmark = srcDoc.Range.Bookmarks[bookmarkName];
    if (bookmark == null)
        throw new Exception("There is no bookmark with specified name");

    Paragraph startNode = (Paragraph) bookmark.BookmarkStart.GetAncestor(NodeType.Paragraph);
    Paragraph endNode = (Paragraph) bookmark.BookmarkEnd.GetAncestor(NodeType.Paragraph);

    // Make sure that start and end nodes are children of the same story.
    if (!startNode.ParentNode.Equals(endNode.ParentNode))
        throw new Exception("Start and end nodes should be children of the same story");

    // Clone the original document, this is needed to preserve styles of the original document
    Document dstDoc = srcDoc.Clone();
    dstDoc.RemoveAllChildren();

    // The destination document should contain at lean one section.
    dstDoc.EnsureMinimum();
    dstDoc.FirstSection.Body.RemoveAllChildren();

    // We will use NodeImporter to import nodes from one document to another.
    NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.UseDestinationStyles);

    Node currNode = startNode;
    Node dstNode;
    // Copy content
    while (currNode != null && !currNode.Equals(endNode))
    {
        // Import node
        dstNode = importer.ImportNode(currNode, true);

        dstDoc.LastSection.Body.AppendChild(dstNode);

        // Move to the next node
        Node nextNode = currNode.NextSibling;
        // Move to the next section
        if (nextNode == null && currNode.ParentNode.NodeType == NodeType.Body)
        {
            Node sect = currNode.GetAncestor(NodeType.Section);
            if (sect.NextSibling != null)
            {
                dstNode = importer.ImportNode(sect.NextSibling, true);
                dstDoc.AppendChild(dstNode);
                dstDoc.LastSection.Body.RemoveAllChildren();
                nextNode = ((Section) sect.NextSibling).Body.FirstChild;
            }
        }

        currNode = nextNode;
    }
    // If the bookmark end is the last child of the last paragraph we need to copy it as well.
    if (endNode.LastChild.Equals(bookmark.BookmarkEnd))
    {
        dstNode = dstDoc.ImportNode(endNode, true, ImportFormatMode.UseDestinationStyles);
        dstDoc.LastSection.Body.AppendChild(dstNode);
    }

    return dstDoc;
}

public void InsertDocumentAtBookmark(string bookmarkName, Document dstDoc, Document srcDoc)
{
    NodeImporter importer = new NodeImporter(srcDoc, dstDoc, ImportFormatMode.KeepSourceFormatting);
    // Create DocumentBuilder
    DocumentBuilder builder = new DocumentBuilder(dstDoc);
    // Move cursor to bookmark and insert paragraph break
    builder.MoveToBookmark(bookmarkName);
    builder.Writeln();
    // If current paragraph is a list item, we should clear its formating.
    if (builder.CurrentParagraph.IsListItem)
        builder.ListFormat.RemoveNumbers();
    // Content of srcdoc will be inserted after this node
    Node insertAfterNode = builder.CurrentParagraph.PreviousSibling;
    // Content of first paragraph of srcDoc will be apended to this parafraph
    Paragraph insertAfterParagraph = null;
    if (insertAfterNode.NodeType == NodeType.Paragraph)
        insertAfterParagraph = (Paragraph) insertAfterNode;
    // Content of last paragraph of srcDoc will be apended to this parafraph
    Paragraph insertBeforeParagraph = builder.CurrentParagraph;
    // We will be inserting into the parent of the destination paragraph.
    CompositeNode dstStory = insertAfterNode.ParentNode;
    // Remove empty paragraphs from the end of document
    while (!((CompositeNode) srcDoc.LastSection.Body.LastChild).HasChildNodes)
    {
        srcDoc.LastSection.Body.LastParagraph.Remove();
        if (srcDoc.LastSection.Body.LastChild == null)
            break;
    }

    Node originalInsertNode = insertAfterNode;

    bool isFirstNode = true;

    // Loop through all sections in the source document.
    foreach(Section srcSection in srcDoc.Sections)
    {
        // Loop through all block level nodes (paragraphs and tables) in the body of the section.
        foreach(CompositeNode srcNode in srcSection.Body)
        {
            // Let's skip the node if it is a last empty paragarph in a section.
            if (srcNode.NodeType.Equals(NodeType.Paragraph))
            {
                Paragraph para = (Paragraph) srcNode;
                if (para.IsEndOfSection && !para.HasChildNodes)
                    continue;
            }

            bool processedNode = false;

            if (isFirstNode)
            {
                if (srcNode.NodeType == NodeType.Paragraph && insertAfterNode.NodeType != NodeType.Table)
                {
                    Node currentInlineNode = null;
                    Paragraph insertParagraph = null;

                    if (insertAfterNode.NodeType == NodeType.Paragraph)
                    {
                        currentInlineNode = ((Paragraph) insertAfterNode).LastChild;
                        insertParagraph = (Paragraph) insertAfterNode;
                    }
                    else if (insertAfterNode.ParentNode.NodeType == NodeType.Paragraph)
                    {
                        currentInlineNode = insertAfterNode;
                        insertParagraph = (Paragraph) insertAfterNode.ParentNode;
                    }

                    foreach(Node node in srcNode.ChildNodes)
                    {
                        Node inlineNode = importer.ImportNode(node, true);
                        insertParagraph.InsertAfter(inlineNode, currentInlineNode);
                        currentInlineNode = inlineNode;
                    }

                    processedNode = true;

                }

                isFirstNode = false;
            }

            if (!processedNode)
            {
                // This creates a clone of the node, suitable for insertion into the destination document.
                Node newNode = importer.ImportNode(srcNode, true);

                // Insert new node after the reference node.
                dstStory.InsertAfter(newNode, insertAfterNode);
                insertAfterNode = newNode;
            }
        }
    }

    if (originalInsertNode is CompositeNode && string.IsNullOrEmpty(originalInsertNode.ToTxt().Trim()))
        originalInsertNode.Remove();
}

Is there an easier and faster way to do that?

Hi Stanislav,
It is perfect that you managed to resolve the problem. I think you can simplify the code and avoid creating an intermediate document that you later insert into the bookmark. Since you are working within one document, you should not import nodes to another document. You should combine these methods to avoid creating an intermediate document.
Best regards,

Hi Alexey

I have very strange issue with a code that extracts bookmark content that i took from
https://docs.aspose.com/words/net/how-to-extract-selected-content-between-nodes-in-a-document/

bookmarkStart = dstBookmark.BookmarkStart;
bookmarkEnd = dstBookmark.BookmarkEnd;

// Firstly extract the content between these nodes including the bookmark.
extractedNodes = ExtractContent(bookmarkStart, bookmarkEnd, false);

Document dstBookmarkContent = GenerateDocument(mDocument, extractedNodes);

I am extracting content from one bookmark and inserting it to another.
If i insert dstBookmarkContent to other bookmark in my document, it is or not inserted correctly or will throw error next time ill try to use this bookmark content.

If i am adding after GenerateDocument this code line:

dstBookmarkContent.Save(@"C:/Temp/temp3.doc");

everything works fine. Do you know what could be a reason for this?

Hi Alexey,

This issue is very important for us. Can you please give me an answer as soon is possible.

Hi Stanislav,
Thanks for your request. You can try using code like the following to copy/move content between bookmarks:

[Test]
public void Test001()
{
    Document doc = new Document(@"Test001\in.doc");
    CopyBookmarkContent(doc.Range.Bookmarks["src"], doc.Range.Bookmarks["dst"], true);
    doc.Save(@"Test001\out.doc");
}
///
/// Copies content from one bookmark to another.
///
/// Bookmark to copy from.
/// Bookmark to copy to.
/// Flag indicates whether we should copy or move content from source bookamrk to destination
private static void CopyBookmarkContent(Bookmark src, Bookmark dst, bool clearSrc)
{
    // Nodes between which we need to copy content.
    Node start = src.BookmarkStart;
    Node end = src.BookmarkEnd;
    Node insertAfter = dst.BookmarkStart;
    // DocumentBuilder will help us to insert content into the destination bookmark.
    DocumentBuilder builder = new DocumentBuilder((Document) src.BookmarkStart.Document);
    builder.MoveToBookmark(dst.Name, true, true);
    Node curNode = start.NextPreOrder(start.Document);
    while (curNode != null && !curNode.Equals(end))
    {
        // Move to next node
        Node nextNode = curNode.NextPreOrder(start.Document);
        // Check whether current contains end node
        if (curNode.IsComposite)
        {
            if (!((CompositeNode) curNode).GetChildNodes(NodeType.Any, true).Contains(end) &&
                !((CompositeNode) curNode).GetChildNodes(NodeType.Any, true).Contains(start))
            {
                nextNode = curNode.NextSibling;
                // If the current node is composite and the Documentbuidler cursor is in paragraph,
                // where bookmark start is located, we should insert a paragraph break.
                if (builder.CurrentParagraph.GetChildNodes(NodeType.Any, true).Contains(dst.BookmarkStart))
                {
                    insertAfter = builder.CurrentParagraph;
                    builder.Writeln();
                }
                // If we need to copy content we should clone node if we should move just insert the original node.
                Node nodeToInsert = clearSrc ? curNode : curNode.Clone(true);
                insertAfter.ParentNode.InsertAfter(nodeToInsert, insertAfter);
                // Insert after node should be also changed.
                insertAfter = nodeToInsert;
            }
        }
        else
        {
            builder.InsertNode(clearSrc ? curNode : curNode.Clone(true));
        }
        curNode = nextNode;
    }
}

Hope this helps.
Best regards,