Free Support Forum - aspose.com

Find an replace plain text by a MergeField System.NullReferenceException was caught

Hi,
I am using a Aspose.Words evalutation version.
I need to change hundreds of documents which I need to replace the place holders from plain text to merged fiels.
using find a replace somehow I get an exception.

System.NullReferenceException was caught
Message="Object reference not set to an instance of an object."

This is the code I am using:

doc = new Document(filepath);<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

string regExp = Regex.Escape("[") + "%[0-9A-Z-_ öüä]*%" + Regex.Escape("]");

doc.Range.Replace(new Regex(regExp, RegexOptions.IgnoreCase),new ReplaceEvaluator(ReplaceEvaluator1), true);

private ReplaceAction ReplaceEvaluator1(object sender, ReplaceEvaluatorArgs e)

{

DocumentBuilder builder = new DocumentBuilder(e.MatchNode.Document);

string fieldName = e.Match.Value;

builder.MoveTo(e.MatchNode);

builder.InsertField(string.Format("MERGEFIELD {0}", fieldName), string.Format("«{0}»", fieldName));

builder.Write("");

return ReplaceAction.Replace;

}

Please see templates:

Thanks Josue

Hi

Thank for your inquiry. I modified your code a little. I hope that this will solve your problem.

public void TestReplace_108314()

{

string filepath = @"448_108314_CmJoshua\in1.doc";

//Open document

Document doc = new Document(filepath);

//Create regex

string regExp = Regex.Escape("[") + "%(?.*?)%" + Regex.Escape("]");

//Replace text

doc.Range.Replace(new Regex(regExp, RegexOptions.IgnoreCase), new ReplaceEvaluator(ReplaceEvaluator_108314), false);

//save document

doc.Save(@"448_108314_CmJoshua\out.doc");

}

int test = 0;

private ReplaceAction ReplaceEvaluator_108314(object sender, ReplaceEvaluatorArgs e)

{

//Create document builder

DocumentBuilder builder = new DocumentBuilder(e.MatchNode.Document);

Run run = new Run(e.MatchNode.Document);

e.MatchNode.ParentNode.InsertAfter(run, e.MatchNode);

//get name of mergefield

string fieldName = e.Match.Groups["text"].Value;

//Move to match node

builder.MoveTo(run);

//insert mergefield

builder.InsertField(string.Format("MERGEFIELD {0}", fieldName), string.Format("«{0}»", fieldName));

return ReplaceAction.Replace;

}

Best regards.

Thanks a lot for your support.
Unfortunately the actual result for your solution posted is not exactly as I expect.
I have different plain texts [%PlaceHolder1%], [%PlaceHolder2%] .. etc.

I need to convert all these plain texts to merge fields like this «[%PlaceHolder1%]», «[%PlaceHolder2%]» without changing anything else but these. The reason of desiring these fields in this strange format ( «[%..%]» ) are because we depend from other systems and we can't change that.

I attach some documents where I illustrate the current result and the desired result.

I hope you can help me, thanks again for your support.

Best regards
Joshua

Hi

Thanks for your inquiry. There is some problem with your document. If you open your document using DocumentExplorer (Demo application) then you can see that [%Name%] is represented as 3 runs. You can solve this problem using one more Replace evaluator. I think that the following code will solve your task.

public void TestReplace_108314()

{

string filepath = @"448_108314_CmJoshua\in2.doc";

//Open document

Document doc = new Document(filepath);

//Create regex

string regExp = Regex.Escape("[") + "%(?.*?)%" + Regex.Escape("]");

//Replace text

doc.Range.Replace(new Regex(regExp, RegexOptions.IgnoreCase), new ReplaceEvaluator(ReplaceEvaluator_108314), true);

doc.Range.Replace(new Regex(regExp, RegexOptions.IgnoreCase), new ReplaceEvaluator(ReplaceEvaluator2_108314), false);

//save document

doc.Save(@"448_108314_CmJoshua\out.doc");

}

private ReplaceAction ReplaceEvaluator_108314(object sender, ReplaceEvaluatorArgs e)

{

//merge runs if text of place holder is represented as several runs

e.Replacement = e.Match.Value;

return ReplaceAction.Replace;

}

private ReplaceAction ReplaceEvaluator2_108314(object sender, ReplaceEvaluatorArgs e)

{

//Get text from match node

string runText = (e.MatchNode as Run).Text;

//Create document builder

DocumentBuilder builder = new DocumentBuilder(e.MatchNode.Document);

//clone match node to preserve formation of text.

Run run = (Run)e.MatchNode.Clone(false);

//split text of match node

run.Text = runText.Substring(runText.IndexOf(e.Match.Value) + e.Match.Value.Length);

(e.MatchNode as Run).Text = runText.Substring(0, runText.IndexOf(e.Match.Value));

//insert created run after match node

e.MatchNode.ParentNode.InsertAfter(run, e.MatchNode);

//get name of mergefield

string fieldName = e.Match.Value;

//Move to run

builder.MoveTo(run);

//insert mergefield

builder.InsertField(string.Format("MERGEFIELD {0}", fieldName), string.Format("«{0}»", fieldName));

return ReplaceAction.Skip;

}

Best regards.

Hi alexey,

Excellent work!!!, it works just perfect. I appreciate your help.

Regards
Joshua

I believe this is very similar to something I am trying to do but I am not sure how to translate this code into VB. Can anyone show me how this code would be written in VB?

thanks

Hi<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Thanks for your request. Here is code in VB.

Sub <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />Main()

Dim lic As Aspose.Words.License = New Aspose.Words.License()

lic.SetLicense("Aspose.Words.lic")

Dim filepath As String = "in.doc"

'Open document

Dim doc As Document = New Document(filepath)

'Create regex

Dim regExp As String = Regex.Escape("[") + "%(?.*?)%" + Regex.Escape("]")

'Replace text

doc.Range.Replace(New Regex(regExp, RegexOptions.IgnoreCase), New ReplaceEvaluator(AddressOf ReplaceEvaluator_108314), True)

doc.Range.Replace(New Regex(regExp, RegexOptions.IgnoreCase), New ReplaceEvaluator(AddressOf ReplaceEvaluator2_108314), False)

'save document

doc.Save("out.doc")

End Sub

Private Function ReplaceEvaluator_108314(ByVal sender As Object, ByVal e As ReplaceEvaluatorArgs) As ReplaceAction

'merge runs if text of place holder is represented as several runs

e.Replacement = e.Match.Value

Return ReplaceAction.Replace

End Function

Private Function ReplaceEvaluator2_108314(ByVal sender As Object, ByVal e As ReplaceEvaluatorArgs) As ReplaceAction

'Get text from match node

Dim runText As String = CType(e.MatchNode, Run).Text

'Create document builder

Dim builder As DocumentBuilder = New DocumentBuilder(e.MatchNode.Document)

'Clone match node to preserve formation of text.

Dim run As Run = CType(e.MatchNode.Clone(False), Run)

'split text of match node

run.Text = runText.Substring(runText.IndexOf(e.Match.Value) + e.Match.Value.Length)

CType(e.MatchNode, Run).Text = runText.Substring(0, runText.IndexOf(e.Match.Value))

'insert created run after match node

e.MatchNode.ParentNode.InsertAfter(run, e.MatchNode)

'get name of mergefield

Dim fieldName As String = e.Match.Value

'Move to run

builder.MoveTo(run)

'insert mergefield

builder.InsertField(String.Format("MERGEFIELD {0}", fieldName), String.Format("«{0}»", fieldName))

Return ReplaceAction.Skip

End Function

Best regards.