Re: Replace text with merge field

I’ve just tried this code in and works.
There is only one problem.
When in e.MatchNode there are more than one “custom field” to Replace, the result is not correct.

For example:
In the Word file I write: [[FirstName]] - [[Surname]] ( [[City]] )
the result is
“Paul Smith London - ()” and not “Paul - Smith (London)”

How Can I Solve?


Hi Matteo,

Thanks for your inquiry. After an initial test with Aspose.Words for Java 14.5.0 and this code, I was unable to reproduce this issue on my side. Could you please upgrade to the latest version and see how it goes on your side.

In case the problem still remains, please attach the following resources here for testing:

  1. Your input word document you’re getting this problem with
  2. Your output word document which shows the undesired behavior.
  3. Your expected word document which shows the correct results. You can create this document using Microsoft Word.
  4. Complete source code you used to generate output document in point 2

As soon as you get these pieces of information ready, we’ll start further investigation into your issue and provide you more information.

Best regards,

Hell Awais,
I attach you my project. In folder “Data” you can find Template and Result.doc.
I also attach you DesiredResult.Doc.


N.B.I’ m using Aspose.Words.NET

Hi Matteo,

Thanks for the additional information. Please change your “ReplaceWithMergeFields” class as follows:

Public Class ReplaceWithMergeFields Implements IReplacingCallback

Private Function IReplacingCallback_Replacing(ByVal e As ReplacingArgs) As ReplaceAction Implements IReplacingCallback.Replacing

        ' This is a Run node that contains either the beginning or the complete match.
        Dim currentNode As Node = e.MatchNode
        ' The first (and may be the only) run can contain text before the match,

        ' in this case it is necessary to split the run.
        If e.MatchOffset > 0 Then
            currentNode = SplitRun(DirectCast(currentNode, Run), e.MatchOffset)

        End If
        ' This array is used to store all nodes of the match for further removing.
        Dim runs As New ArrayList()

        ' Find all runs that contain parts of the match string.
        Dim remainingLength As Integer = e.Match.Value.Length
        While (remainingLength > 0) AndAlso (currentNode IsNot Nothing) AndAlso (currentNode.GetText().Length <= remainingLength)
            remainingLength = remainingLength - currentNode.GetText().Length

            ' Select the next Run node.
            ' Have to loop because there could be other nodes such as BookmarkStart etc.
                currentNode = currentNode.NextSibling
            Loop While (currentNode IsNot Nothing) AndAlso (currentNode.NodeType <> NodeType.Run)
        End While
        ' Split the last run that contains the match if there is any text left.
        If (currentNode IsNot Nothing) AndAlso (remainingLength > 0) Then
            SplitRun(DirectCast(currentNode, Run), remainingLength)
        End If
        Dim builder As New DocumentBuilder(DirectCast(e.MatchNode.Document, Document))
        builder.MoveTo(CType(runs(runs.Count - 1), Run))

        builder.InsertField("MERGEFIELD " & e.Match.ToString.Replace("«", "").Replace("»", "") & " \* MERGEFORMAT" & " " & "MERGEFIELD " & e.Match.ToString.Replace("«", "").Replace("»", "") & " \* MERGEFORMAT")
        For Each run As Run In runs
        Next run
        Return ReplaceAction.Skip
    End Function
    Private Shared Function SplitRun(ByVal run As Run, ByVal position As Integer) As Run
        Dim afterRun As Run = CType(run.Clone(True), Run)
        afterRun.Text = run.Text.Substring(position)
        run.Text = run.Text.Substring(0, position)
        run.ParentNode.InsertAfter(afterRun, run)

        Return afterRun
    End Function
End Class

I hope, this helps.

Best regards,