An example that shows how to create your own MergeField class, that represents a single merge field in a Microsoft Word and allows to get or set its name.
Example RenameMergeFields
Shows how to rename merge fields in a Word document.
[C#]
using System;
using System.Text;
using System.Text.RegularExpressions;
using Aspose.Words;
using Aspose.Words.Fields;
namespace Examples
{
/// <summary>
/// Shows how to rename merge fields in a Word document.
/// </summary>
public class ExRenameMergeFields : ExBase
{
/// <summary>
/// Finds all merge fields in a Word document and changes their names.
/// </summary>
public void RenameMergeFields()
{
// Specify your document name here.
Document doc = new Document(MyDir + "RenameMergeFields.doc");
// Select all field start nodes so we can find the merge fields.
NodeCollection fieldStarts = doc.GetChildNodes(NodeType.FieldStart, true, false);
foreach (FieldStart fieldStart in fieldStarts)
{
if (fieldStart.FieldType.Equals(FieldType.FieldMergeField))
{
MergeField mergeField = new MergeField(fieldStart);
mergeField.Name = mergeField.Name + "_Renamed";
}
}
doc.Save(MyDir + "RenameMergeFields Out.doc");
}
}
/// <summary>
/// Represents a facade object for a merge field in a Microsoft Word document.
/// </summary>
internal class MergeField
{
internal MergeField(FieldStart fieldStart)
{
if (fieldStart.Equals(null))
throw new ArgumentNullException("fieldStart");
if (!fieldStart.FieldType.Equals(FieldType.FieldMergeField))
throw new ArgumentException("Field start type must be FieldMergeField.");
mFieldStart = fieldStart;
// Find the field separator node.
mFieldSeparator = FindNextSibling(mFieldStart, NodeType.FieldSeparator);
if (mFieldSeparator == null)
throw new InvalidOperationException("Cannot find field separator.");
// Find the field end node. Normally field end will always be found, but in the example document
// there happens to be a paragraph break included in the hyperlink and this puts the field end
// in the next paragraph. It will be much more complicated to handle fields which span several
// paragraphs correctly, but in this case allowing field end to be null is enough for our purposes.
mFieldEnd = FindNextSibling(mFieldSeparator, NodeType.FieldEnd);
}
/// <summary>
/// Gets or sets the name of the merge field.
/// </summary>
internal string Name
{
get
{
return GetTextSameParent(mFieldSeparator.NextSibling, mFieldEnd).Trim('�', '�');
}
set
{
// Merge field name is stored in the field result which is a Run
// node between field separator and field end.
Run fieldResult = (Run)mFieldSeparator.NextSibling;
fieldResult.Text = string.Format("�{0}�", value);
// But sometimes the field result can consist of more than one run, delete these runs.
RemoveSameParent(fieldResult.NextSibling, mFieldEnd);
UpdateFieldCode(value);
}
}
private void UpdateFieldCode(string fieldName)
{
// Field code is stored in a Run node between field start and field separator.
Run fieldCode = (Run)mFieldStart.NextSibling;
Match match = gRegex.Match(fieldCode.Text);
string newFieldCode = string.Format("{0} {1} {2}", match.Groups["start"].Value, fieldName, match.Groups["end"].Value);
fieldCode.Text = newFieldCode;
// But sometimes the field code can consist of more than one run, delete these runs.
RemoveSameParent(fieldCode.NextSibling, mFieldSeparator);
}
/// <summary>
/// Goes through siblings starting from the start node until it finds a node of the specified type or null.
/// </summary>
private static Node FindNextSibling(Node startNode, NodeType nodeType)
{
for (Node node = startNode; node != null; node = node.NextSibling)
{
if (node.NodeType.Equals(nodeType))
return node;
}
return null;
}
/// <summary>
/// Retrieves text from start up to but not including the end node.
/// </summary>
private static string GetTextSameParent(Node startNode, Node endNode)
{
if ((endNode != null) && (startNode.ParentNode != endNode.ParentNode))
throw new ArgumentException("Start and end nodes are expected to have the same parent.");
StringBuilder builder = new StringBuilder();
for (Node child = startNode; !child.Equals(endNode); child = child.NextSibling)
builder.Append(child.GetText());
return builder.ToString();
}
/// <summary>
/// Removes nodes from start up to but not including the end node.
/// Start and end are assumed to have the same parent.
/// </summary>
private static void RemoveSameParent(Node startNode, Node endNode)
{
if ((endNode != null) && (startNode.ParentNode != endNode.ParentNode))
throw new ArgumentException("Start and end nodes are expected to have the same parent.");
Node curChild = startNode;
while ((curChild != null) && (curChild != endNode))
{
Node nextChild = curChild.NextSibling;
curChild.Remove();
curChild = nextChild;
}
}
private readonly Node mFieldStart;
private readonly Node mFieldSeparator;
private readonly Node mFieldEnd;
private static readonly Regex gRegex = new Regex(@"\s*(?<start>\S+)\s+(?<name>\S+)\s+(?<end>.+)");
}
}
[Visual Basic]
Imports Microsoft.VisualBasic
Imports System
Imports System.Text
Imports System.Text.RegularExpressions
Imports Aspose.Words
Imports Aspose.Words.Fields
Namespace Examples
''' <summary>
''' Shows how to rename merge fields in a Word document.
''' </summary>
<TestFixture> _
Public Class ExRenameMergeFields
Inherits ExBase
''' <summary>
''' Finds all merge fields in a Word document and changes their names.
''' </summary>
<Test> _
Public Sub RenameMergeFields()
' Specify your document name here.
Dim doc As Document = New Document(MyDir & "RenameMergeFields.doc")
' Select all field start nodes so we can find the merge fields.
Dim fieldStarts As NodeCollection = doc.GetChildNodes(NodeType.FieldStart, True, False)
For Each fieldStart As FieldStart In fieldStarts
If fieldStart.FieldType.Equals(FieldType.FieldMergeField) Then
Dim mergeField As MergeField = New MergeField(fieldStart)
mergeField.Name = mergeField.Name & "_Renamed"
End If
Next fieldStart
doc.Save(MyDir & "RenameMergeFields Out.doc")
End Sub
End Class
''' <summary>
''' Represents a facade object for a merge field in a Microsoft Word document.
''' </summary>
Friend Class MergeField
Friend Sub New(ByVal fieldStart As FieldStart)
If fieldStart.Equals(Nothing) Then
Throw New ArgumentNullException("fieldStart")
End If
If (Not fieldStart.FieldType.Equals(FieldType.FieldMergeField)) Then
Throw New ArgumentException("Field start type must be FieldMergeField.")
End If
mFieldStart = fieldStart
' Find the field separator node.
mFieldSeparator = FindNextSibling(mFieldStart, NodeType.FieldSeparator)
If mFieldSeparator Is Nothing Then
Throw New InvalidOperationException("Cannot find field separator.")
End If
' Find the field end node. Normally field end will always be found, but in the example document
' there happens to be a paragraph break included in the hyperlink and this puts the field end
' in the next paragraph. It will be much more complicated to handle fields which span several
' paragraphs correctly, but in this case allowing field end to be null is enough for our purposes.
mFieldEnd = FindNextSibling(mFieldSeparator, NodeType.FieldEnd)
End Sub
''' <summary>
''' Gets or sets the name of the merge field.
''' </summary>
Friend Property Name() As String
Get
Return GetTextSameParent(mFieldSeparator.NextSibling, mFieldEnd).Trim("�"c, "�"c)
End Get
Set
' Merge field name is stored in the field result which is a Run
' node between field separator and field end.
Dim fieldResult As Run = CType(mFieldSeparator.NextSibling, Run)
fieldResult.Text =