Need help with MergeFieldEvent

Can someone please provide detailed information on how to use the MergeFieldEvent handler? I have read every post in this forum and simply do not understand it. I guess the main point I don’t get is how to reference the DocumentBuilder back in the source document from the event handler routine.

I would like to do the following:

When I come across the mergefield named “ReserveData” in my Word doc template, I want to insert the contents of a DataTable that I have available. After that, I want the document to continue processing the rest of the merge fields as normal. This is really a workaround to embed a nested table into a document since nested tables are not yet supported. If anyone has a complete and detailed explanation of how to accomplish this, I would greatly appreciate it.

R. Clift

When inside the event handler, you can use MergeFieldEvent.Document to obtain the document and then create a DocumentBuilder for it.

Alternatively, create the DocumentBuilder before the mail merge operation and store it in a private member of your class that runs the mail merge operation and provides the event handler.

private void HandleMergeFieldEvent(object sender, MergeFieldEventArgs e)
{
    //This creates a new document builder for every event.
    //Although DocumentBuilder is a lightweight object, it still
    //might be better to cache it in a field of this class.
    DocumentBuilder builder = new DocumentBuilder(e.Document);

    if (e.FieldName == "Description")
    {
        builder.MoveToMergeField(e.FieldName);
        string fieldValue = e.FieldValue.ToString();

        if (fieldValue.IndexOf("Blue") != -1)
            builder.Font.Color = System.Drawing.Color.Blue;
        else
            builder.Font.Color = System.Drawing.Color.Red;

        //Write the text using the builder, don’t let the mail merge engine to insert text too.
        builder.Write(fieldValue);
        e.Text = "";
    }
}

Thanks for your help… that clears things up a bit. Now that I have that working, how would I insert a table into the document within the mergefield event handler?

Essentially I would like to take what you have here:

if (e.FieldName == "Description")
{
    builder.MoveToMergeField(e.FieldName);
    string fieldValue = e.FieldValue.ToString();

    if (fieldValue.IndexOf("Blue") != -1)
        builder.Font.Color = System.Drawing.Color.Blue;
    else
        builder.Font.Color = System.Drawing.Color.Red;

    //Write the text using the builder, don’t let the mail merge engine to insert text too.
    builder.Write(fieldValue);
    e.Text = "";
}

And change it to something like:

if (e.FieldName == "Description")
{
    builder.MoveToMergeField(e.FieldName);

    // 1. Create a new table in the word doc with 2 columns

    foreach (DataRow myDR in thisDS.Tables["ClaimReserves"].Rows)

    {

        // 2. Create a new table row in word doc
        // 3. Insert something into the left cell
        // 4. Insert something into the right cell, right-aligned.

    }
    e.Text = "";
}

Is this easy to do? I really just don’t know about inserting the table object I guess…

Thanks again,

R. Clift

There is an example how to create a table in the C# demo project. Here is similar code:

public void TestChess()
{
    builder.Font.Size = 8;
    builder.Font.Name = "Tahoma";
    builder.ParagraphFormat.Alignment = ParagraphAlignment.Center;
    builder.RowFormat.Height = 0.75 * 72;//0.5
    builder.RowFormat.HeightRule = RowHeightRule.Exactly;
    builder.CellFormat.Width = 0.75 * 72;//0.5
    builder.CellFormat.VerticalAlignment = CellVerticalAlignment.Center;

    foreach (Border border in builder.CellFormat.Borders)
    {
        border.LineStyle = LineStyle.Single;
        border.LineWidth = 2;
        border.Color = System.Drawing.Color.Blue;
    }

    for (int y = 0; y < 8; y++)
    {
        for (int x = 0; x < 8; x++)
        {
            builder.InsertCell();
            builder.Write(string.Format("X{ 0}, Y{ 1}", x, y));
            bool isBlack = (((x + y) & 0x01) != 0);
            builder.CellFormat.Shading.BackgroundPatternColor =
            (isBlack) ? System.Drawing.Color.LightGreen : System.Drawing.Color.LightYellow;
        }
        builder.EndRow();
    }
    builder.EndTable();

    builder.ParagraphFormat.ClearFormatting();
    builder.ParagraphFormat.KeepWithNext = true;
    builder.ParagraphFormat.SpaceAfter = 12;
    builder.ParagraphFormat.SpaceBefore = 11;
    builder.Font.Name = "Arial";
    builder.Font.Bold = true;
    builder.Font.Underline = Underline.Thick;
    builder.Font.Size = 12;
    builder.Writeln("blah blah");

    SaveOpen();
}

Thanks for your reply. I figured out how to do what I needed. I have included a code snippet below in case anyone else needs help with a similar issue.

private void EmbedDataTable(object sender, MergeFieldEventArgs e)
{
    DataSet thisDS = (DataSet)Session[“DocDS”];
    DataTable myDT = thisDS.Tables[0];

    DocumentBuilder myBuilder = new DocumentBuilder(e.Document);

    if (e.FieldName == "ReserveData")
    {
        myBuilder.MoveToMergeField(e.FieldName);
        foreach (DataRow myDR in myDT.Rows)
        {
            if (Field.GetBool(myDR, "Approved"))
            {
                myBuilder.InsertCell();
                myBuilder.ParagraphFormat.Alignment = ParagraphAlignment.Left;
                myBuilder.Write(Field.GetDateString(myDR, "ReserveDate"));
                myBuilder.InsertCell();
                myBuilder.ParagraphFormat.Alignment = ParagraphAlignment.Right;
                myBuilder.Write(Field.GetCurrencyString(Field.GetDecimal(myDR, "AmountUS")));
                myBuilder.EndRow();
            }
        }

        e.Text = "";
    }
}

Hi SpotVader / Roman,

I have been trying to use the MailMerge feature of ASPOSE Word and while searching for some shortcuts, I came across the alternative you’ve suggested (using the EmbedDataTable event). I guess I can use the same logic in my code to merge data in my Word table (the structure is the same as the one you had in your document - Master / Detail relationship)

I would like to know whether the EmbedDataTable thing that you have used in your code snippet, is a Method or an Event. If it is an event, 1) how and 2) where does it get triggerred off, and if it is a method, 1) when is it called, and 2) how do I get the parameters that are passed to this method (input parameters).

In my case, I have a Word tale with 3 sections:
The first section uses data from, say, DataTable_1 (single record). The second section uses data from DataTable_2, and the 3rd section contains just one field from DataTable_1. In the above structure, Section 1 & Section 3 use data from the Master Datatable (DataTable_1 - Single row) and section 2 uses data from the Detail DataTable (DataTable_2 - Multiple rows)

Also, I was not very clear with the “Field.GetBool(myDR, “Approved”)” statement that you have used in your code snippet. Is it a system defined function, or is it a function built-in the ASPOSE class library.

Thanks in anti***tion.

Regards,
Parry

EmbedDataTable is an event handler for the MergeFieldEvent event.

//You attach it like this:
doc.MailMerge.MergeField += new MergeFieldEventHandler(EmbedDataTable);

//Then you can do mail merge
doc.MailMerge.Execute(…

MergeFieldEventArgs is the arguments passed into the event handler, please see the API documentation for this.

Field.GetBool and others seem to be spotvader's code because
it's not part of Aspose.Word and not in the MSDN library.
I think he is just using those methods to retrieve field value from
a data row while checking for nulls or something like that.

Yes, Roman you are correct… Field.GetBool() is one of my own methods that gets a boolean value from a datatable while checking for nulls, etc. Sorry if that confused anyone…

Aspose.Word 2.1.3 is released with new demos, for more info see File Format APIs for .NET Core, Java, Python, C++, Android | products.aspose.com