I’ve just tried this code in
Vb.net 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.
In the Word file I write: [[FirstName]] - [[Surname]] ( [[City]] )
the result is
“Paul Smith London - ()” and not “Paul - Smith (London)”
How Can I Solve?
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:
- Your input word document you’re getting this problem with
- Your output word document which shows the undesired behavior.
- Your expected word document which shows the correct results. You can create this document using Microsoft Word.
- 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.
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
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)
' 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)
' 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)
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
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)
I hope, this helps.