How to Find all Merge Fields in Cell

Hi,
I have previously posted questions asking how to loop through all the cells in a table (and many thanks for your previous help, which has been excellent). I have now almost completed my application, but I am really struggling with one last issue. I need to be able to loop through all of the Mail Merge fields within a cell, and determine what the merge field name is. I have written some code using the NextSibling and FieldMergeField properties, but I can’t seem to reliably loop through each mail merge field within the cell. Would you be able to provide a simple example in VB.Net?
Thanks again for your continued help

Hi
Thanks for your inquiry. I think that you can try to use the MoveToMergeField method to achieve this. For example see the following code.

Dim doc As Document = New Document("in_102196.doc")
Dim builder As DocumentBuilder = New DocumentBuilder(doc)
'Get mergeFields names
Dim fieldNamesArr As String() = doc.MailMerge.GetFieldNames()
'loop through mergfields
Dim i As Integer
For i = 0 To fieldNamesArr.Length - 1
builder.MoveToMergeField(fieldNamesArr(i))
builder.Write(String.Format("Here is Field {0}", fieldNamesArr(i)))
Next
doc.Save("out_102196.doc")

I hope that this will help you.
Best regards.

Hi,
Thanks very much for your rapid response (as always). This code allows me to retrieve all the merge fields in the whole document, but I really need a way to determine which merge fields exist within a word table cell. I am converting an existing application, and have now completed the code that loops through all of the tables, and then loops through all of the cells, but I need to check for the existence of merge fields in each cell.
Thanks again

Hi
Thanks you for additional information. I think that you can try to use the following code.

Dim doc As Document = New Document("in.doc")
Dim builder As DocumentBuilder = New DocumentBuilder(doc)
Dim tab As Table = doc.FirstSection.Body.Tables(0)
Dim row As Row = Nothing
For Each row In tab.Rows
Dim cel As Cell = Nothing
For Each cel In row.Cells
Dim names As String = ""
Dim collection As NodeCollection = cel.GetChildNodes(NodeType.FieldStart, True)
Dim start As FieldStart = Nothing
For Each start In collection
If start.FieldType = FieldType.FieldMergeField Then
'get mergefields name
Dim name As String = CType(start.NextSibling, Run).Text.Replace("MERGEFIELD", "")
name = name.Substring(0, name.IndexOf("\")).Trim()
names &= name & " "
End If
Next
If Not String.IsNullOrEmpty(names) Then
builder.MoveToCell(0, tab.IndexOf(row), row.IndexOf(cel), 0)
builder.Write("This cell contains the following mergefields: " & names)
End If
Next
Next
doc.Save("out.doc")

I hope that this will help you.
Best regards.

Hi Alexey,
Thanks again. This looks promising, but doesn’t seem to work quite right. The line “CType(start.NextSibling, Run).Text” returns a value of " MERGEFIELD " - but the actual name of the merge field is not returned.
Laurie

Hi
Thanks for your remark. Field code has the following structure by default:
FieldStart | Run | FieldSeparator | Run | FieldEnd
But the field can contain several runs between FieldStart and FieldSeparator or between FieldSeparator and FieldEnd. That’s why you get this result. You can try to open your file using DocumentExplorer then you will see structure of your document.
Best regards.

Hi Alexey,
OK, we’re really getting somewhere now!
I now understand that there are multiple runs between fields, so the field name may be contained within Start.NextSibling.Range.Text or Start.NextSibling.NextSibling.Range.Text or Start.NextSibling.NextSibling.NextSibling.Range.Text, etc. If I could determine a way to loop through each of these I think I would have my solution. Is there a way to do this?

Hi
Thanks for your inquiry. Try to use the following code snippet to solve your problem

string names = string.Empty;
NodeCollection collection = cell.GetChildNodes(NodeType.FieldStart, true);
foreach (FieldStart start in collection)
{
    if (start.FieldType == FieldType.FieldMergeField)
    {
        Node currentNode = start;
        string name = string.Empty;
        while (currentNode.NodeType != NodeType.FieldSeparator)
        {
            currentNode = currentNode.NextSibling;
            if (currentNode.NodeType == NodeType.Run)
            {
                name += (currentNode as Run).Text;
            }
        }
        name = name.Replace("MERGEFIELD", "");
        name = name.Substring(0, name.IndexOf("\\")).Trim();
        names += name + " ";
    }
}

I hope that this will help you.
Let me know if you would like to know something else.
Best regards.

Hi Alexey,
Thanks again for your help. I have now got the application to correctly recognise all the fields in the table cells. This is a MAJOR step forwards!! The very final piece I now need to complete, is to replace the field with some basic text (the code effectively loops through the fields and if certain conditions are met it changes some of the fields into text). This code was very simple within the Word macro, as I could simple select the field, and then perform a replace operation. In Aspose.Words though, I am looping through many “run” items within the field. I have been able to change a single instance, but can you tell me how (using your code example above) I could replace the whole field with a string of text?
Thanks again

Hi
Thanks for your inquiry. I think that you can try to use MailMerge.Execute method. See the following link for more information.
https://reference.aspose.com/words/net/aspose.words.mailmerging/mailmerge/execute/
Names array you can get using the above code.
I hope that this will help you.
Best regards.

Sorry, I should have been clearer. The process works as follows:

  1. Check through the Word document for specific mail merge fields that need to be replaced with static text (there is a good reason why some fields need to be replaced with static text, but I won’t bother explaining it here as it is irrelevant to the Aspose sample code)
  2. Run the mail merge (this is coded, and is working perfectly)

I’m pretty sure the rest of the application has now been ported to use Aspose.Words, and is ready for testing. The final piece is to replace the affected merge fields with static text. The code to identify the fields and check them is finished, but I am not sure how to replace the field with static text. Once that’s done, I think we are finished and ready for testing
Many thanks for your continued help

Hi
Thanks for your inquiry. You can try using the following code.

builder.MoveToMergeField(name);
builder.Write("some text intead field ");

Or you can try using the following code.

Document doc = new Document(@"352_102196_workaholicme\in.doc");
DocumentBuilder builder = new DocumentBuilder(doc);
Table table = doc.FirstSection.Body.Tables[0];
foreach (Row row in table.Rows)
{
    foreach (Cell cell in row.Cells)
    {
        string names = string.Empty;
        NodeCollection collection = cell.GetChildNodes(NodeType.FieldStart, true);
        foreach (FieldStart start in collection)
        {
            if (start.FieldType == FieldType.FieldMergeField)
            {
                while (start.NextSibling.NodeType != NodeType.FieldEnd)
                {
                    start.NextSibling.Remove();
                }
                start.NextSibling.Remove();
                Run run = new Run(doc, "some text instead field");
                start.ParentParagraph.InsertAfter(run, start);
                start.Remove();
            }
        }
    }
}
doc.Save(@"352_102196_workaholicme\out.doc");

I hope that this will help you.
Please let me know if you would like to know something else.
Best regards.