Mail Merge with Custom Object

Hello there,

I am working on a reporting service in which mail merge with Aspose is a major functionality.
Because I have a no. of custom objects against which mail merge(Execute(), ExecuteWithRegions()) is run, IMailMergeDataSource needs to be implemented for each custom object that I have.

In future, more custom objects will be added to the list.o, I was wondering if there is a generic way of getting MailMergeDataSource for my custom objects so that I don’t need to implement IMailMergeDataSource for each custom object?

Thank you!

Hi Nutan,

Thanks for yu rreqeust. Sure, you can use reflection to achieve this. Please see the following code for example:

///
/// A custom mail merge data source that you implement to allow Aspose.Words
/// to mail merge data from LINQ query results into Microsoft Word documents.
///
public class MailMergeDataSource: IMailMergeDataSource
{
    ///
    /// Creates new instance of a custom mail merge data source
    ///
    /// Data returned from a LINQ query
    public MailMergeDataSource(IEnumerable data)
    {
        mEnumerator = data.GetEnumerator();
    }
    ///
    /// Creates new instance of a custom mail merge data source
    ///
    /// Data returned from a LINQ query
    /// Name of the data source is only used when you perform mail merge with regions.
    /// If you would like to use simple mail merge then use constructor with one parameter.
    public MailMergeDataSource(IEnumerable data, string tableName)
    {
        mEnumerator = data.GetEnumerator();
        // Name of the data source is needed when you perform mail merge with regions
        mTableName = tableName;
    }
    ///
    /// Aspose.Words call this to get a value for every data field.
    ///
    public bool GetValue(string fieldName, out object fieldValue)
    {
        // Get type of current record
        Type curentRecordType = mCurrentObject.GetType();
        // Use reflection to get property by name and its value
        PropertyInfo property = curentRecordType.GetProperty(fieldName);
        if (property != null)
        {
            fieldValue = property.GetValue(mCurrentObject, null).ToString();
            return true;
        }
        else
        {
            // A field with this name was not found,
            // return false to the Aspose.Words mail merge engine.
            fieldValue = null;
            return false;
        }
    }
    ///
    /// Moves to the next record in the collection.
    ///
    public bool MoveNext()
    {
        // Move enumerator to next record
        bool hasNexeRecord = mEnumerator.MoveNext();
        if (hasNexeRecord)
        {
            mCurrentObject = mEnumerator.Current;
        }
        return hasNexeRecord;
    }
    ///
    /// The name of the data source. Used by Aspose.Words only when executing mail merge with repeatable regions.
    ///
    public string TableName
    {
        get
        {
            return mTableName;
        }
    }
    private IEnumerator mEnumerator;
    private object mCurrentObject;
    private string mTableName = string.Empty;
}

Hope this helps.
Best regards,

Thanks for your reply.

One more query, to get it to work do you think mail merge fields in my source document should exactly match with object property names?

Hi

Thanks for your inquiry. Yes, merge field names in your source document should exactly match with object property names. If not, you can use MappedDataFields to map between merge field names in the template and names in your datasource:
https://reference.aspose.com/words/net/aspose.words.mailmerging/mappeddatafieldcollection/
Best regards,

Thanks for your help Alexey!

One more query in addition to above -
The object i use for Mail Merge has further child objects, I need to map merge fields for these child object properties as well.
For exp. ‘Client’ object has child object ‘Address’.
If I want to access StreetNumber/PostCode or any other address related info., I need to access it through objClient.Address.PostCode and so on.
FYI, In source document, I have merge fields like ‘APostCode’, ‘AStreetNumber’ etc.

Could you please guide how can I map fields for such properties?

Thank you!

Hi Nutan,

Thanks for your inquiry. I think, in this case, you should have set of rules where engine should look for the appropriate property. But the main idea is the same is I described.
As I already mentioned above, you should use MappedDataFields to map between merge field names in the template and names in your datasource.
Best regards,