Error in UpdateFields when use of bookmarks

I’m using cross-refferences in a Word document. The format is that i’m reffering to chapter headings with numbers (1.2 My heading). In Word it says only “1.2” when I reffer, but after doc.UpdateFields() is run it says “My Heading” instead.

Document doc = new Document(filepath);
doc.UpdateFields();
doc.Save(filepath + ".UpdateFields.docx");

Version of Aspose.Words is 9.4.0.0
Attaching Word document before and after UpdateFields() is run.

Hi

Thank you for reporting this problem to us. I managed to reproduce it on my side. Your request has been linked to the appropriate issue. You will be notified as soon as it is resolved.
Best regards,

Hi Christian,
Thanks for your inquiry.
In the mean time while you are waiting for this fix you can use the work around below. There are sufficent API members to very easily implement this update manually. Please see the code below which achieves this.

Document doc = new Document("Testing.docx");
doc.UpdateFields();
// Update REF fields with the proper values.
UpdateRefFields(doc);
doc.Save("Testing Out.docx");
public static void UpdateRefFields(CompositeNode node)
{
    // The document that this node belongs to.
    Document doc = (Document)node.Document;
    // Update list labels so we can get the list numbers of the paragraphs.
    doc.UpdateListLabels();
    // Iterate through all FieldRefs in the Document or CompositeNode. CompositeNode means that this code
    // can run on only certain parts of the document e.g a specific section.
    foreach (FieldStart start in node.GetChildNodes(NodeType.FieldStart, true))
    {
        if (start.FieldType == FieldType.FieldRef)
        {
            // Parse the FieldCode.
            Regex regex = new Regex(@"\s*(?\S+)\s+(?\S+)\s+(?.+)");
            Match match = regex.Match(GetFieldCode(start));
            // See if the field contains the switch we are interested in.
            if (match.Groups["switches"].Value.Contains("\\r"))
            {
                // Get the paragraph referenced by this field.
                Bookmark bookmark = doc.Range.Bookmarks[match.Groups["bookmark"].Value];
                if (bookmark != null)
                {
                    // Get the paragraph that the reference bookmark is contained in.
                    Paragraph bookmarkPara = (Paragraph)bookmark.BookmarkStart.ParentNode;
                    // Get the current field result.
                    string fieldResult = GetFieldResult(start);
                    // Get the list number of the paragraph which is the proper result for this switch.
                    string newResult = bookmarkPara.ListLabel.LabelString.TrimEnd('.');
                    // Replace the current field result with the new result. This should retain formatting.
                    start.ParentParagraph.Range.Replace(fieldResult, newResult, false, false);
                }
            }
        }
    }
}

private static string GetFieldCode(Aspose.Words.Fields.FieldStart fieldStart)
{
    StringBuilder builder = new StringBuilder();
    for (Node node = fieldStart; node != null && node.NodeType != NodeType.FieldSeparator && node.NodeType != NodeType.FieldEnd; node = node.NextPreOrder(node.Document))
    {
        // Use the text only of Run nodes to avoid duplication.
        if (node.NodeType == NodeType.Run)
            builder.Append(node.GetText());
    }
    return builder.ToString();
}

private static string GetFieldResult(Aspose.Words.Fields.FieldStart fieldStart)
{
    StringBuilder builder = new StringBuilder();
    bool isAtSeparator = false;
    for (Node node = fieldStart; node != null && node.NodeType != NodeType.FieldEnd; node = node.NextPreOrder(node.Document))
    {
        if (node.NodeType == NodeType.FieldSeparator)
        {
            isAtSeparator = true;
        }
        // Use text only of Run nodes to avoid duplication.
        if (isAtSeparator && node.NodeType == NodeType.Run)
            builder.Append(node.GetText());
    }
    return builder.ToString();
}

Thanks,

Closing in, but you still have have the same problem if you are reffering to a section that is reffering to another section.
See attached file for result after use of above code and compare to original file attached in first post.

Hi Christian,
Thanks for this additional information.
Please try adding in the code below to the original method.

// Get the paragraph that the reference bookmark is contained in.
Paragraph bookmarkPara = (Paragraph) bookmark.BookmarkStart.ParentNode;
// Remove any fields from the current field result
RemoveFieldsFromResult(start);
// Get the current field result.
string fieldResult = GetFieldResult(start);
private static string RemoveFieldsFromResult(FieldStart fieldStart)
{
    StringBuilder builder = new StringBuilder();
    // Use a stack to keep track of any nested fields.
    Stack fieldStack = new Stack();
    // Add the base field start to the stack.
    fieldStack.Push(fieldStart);
    // Have we encountered the separator of the base field yet.
    bool isAtSeparator = false;
    Node node = fieldStart.NextPreOrder(fieldStart.Document);
    // Iterate through all nodes between the FieldStart and FieldEnd of the base field.
    while (node != null && fieldStack.Count != 0)
    {
        Node removeNode = null;
        if (node.NodeType == NodeType.FieldStart)
        {
            // Encountered a nested field. Add it to the stack.
            fieldStack.Push(fieldStart);
        }
        // If this FieldSeparator belongs to the base field then set that we are now at the FieldSeparator
        if (node.NodeType == NodeType.FieldSeparator && fieldStack.Count == 1)
            isAtSeparator = true;
        // Remove the content of fields that are found in the field result.
        if (isAtSeparator && fieldStack.Count> 1)
        {
            removeNode = node;
        }
        // FieldEnd has been visited, remove this field from the stack.
        if (node.NodeType == NodeType.FieldEnd)
            fieldStack.Pop();
        // Visit the next node in the document.
        node = node.NextPreOrder(node.Document);
        // Remove a node if there is one to remove.
        if (removeNode != null)
            removeNode.Remove();
    }
    // Return the field result.
    return builder.ToString();
}

Thanks,

Almost there. Last referrence is not correct, see attachement. Still I would prefer to not use this workaround but to have it included in the “UpdateFields()” method.
When is this bug fix included in product? What is the estimate date for it?

Hi

Thanks for your request. I just consulted with the developer, who is responsible for this feature. He promised that the issue will be resolved in few weeks. We will notify you once it is fixed.
Best regards.

Hi Christian,
Thanks for your inquiry.
As Alexey has mentioned this is just a temporary work around. This will be supported in the next version of Aspose.Words.
To get the last reference to work correcty please use this updated code below.

private static string RemoveFieldsFromResult(FieldStart fieldStart)
{
    StringBuilder builder = new StringBuilder();
    // Use a stack to keep track of any nested fields.
    Stack fieldStack = new Stack();
    // Add the base field start to the stack.
    fieldStack.Push(fieldStart);
    // Have we encountered the separator of the base field yet.
    bool isAtSeparator = false;
    bool encounteredRun = false;
    Node node = fieldStart.NextPreOrder(fieldStart.Document);
    // Iterate through all nodes between the FieldStart and FieldEnd of the base field.
    while (node != null && fieldStack.Count != 0)
    {
        Node removeNode = null;
        if (node.NodeType == NodeType.FieldStart)
        {
            // Encountered a nested field. Add it to the stack.
            fieldStack.Push(fieldStart);
        }
        if (isAtSeparator)
        {
            if (!encounteredRun && node.NodeType == NodeType.Run)
            {
                // Mark the first run encountered to ensure the field result is unique.
                Run currentRun = (Run) node;
                currentRun.Text = "%FieldResult%";
                encounteredRun = true;
            }
            else
            {
                // Node is found within the field result of the base field so remove it.
                removeNode = node;
            }
        }
        // If this FieldSeparator belongs to the base field then set that we are now at the FieldSeparator
        // This is checked after the removal check above so the base field's separator is not removed.
        if (node.NodeType == NodeType.FieldSeparator && fieldStack.Count == 1)
        {
            isAtSeparator = true;
            if (string.IsNullOrEmpty(GetFieldResult(fieldStart)))
            {
                // If field result is empty create a new run and insert it in the field result.
                Run run = new Run(fieldStart.Document);
                fieldStart.ParentParagraph.InsertAfter(run, node);
            }
        }
        node = node.NextPreOrder(node.Document);
        if (removeNode != null)
            removeNode.Remove();
        // FieldEnd has been visited, remove this field from the stack.
        // Check this just before the loop is reevaluated so the fieldend of the base field is not removed.
        if (node.NodeType == NodeType.FieldEnd)
            fieldStack.Pop();
    }
    // Return the field result.
    return builder.ToString();
}

Thanks,

The issues you have found earlier (filed as 25487) have been fixed in this update.

This message was posted using Notification2Forum from Downloads module by aspose.notifier.
(48)

The issues you have found earlier (filed as WORDSNET-3788) have been fixed in this .NET update and in this Java update.

This message was posted using Notification2Forum from Downloads module by aspose.notifier.
(91)