Mail Merge In Aspose C#.NET

What is Aspose?

Aspose, a file formats API provider, provides .NET, Java, Android, SharePoint, Reporting Services, and cloud-based APIs for document generation, conversion, and automation. Unlike any 3rd party DLL, you can use Aspose and play with your office documents along with PDF in a much simpler way.

The very best part of this I found is mail merge. To generate any PDF, you have to continue either item by item or you can create your HTML and then convert it into a PDF. Here, in Aspose, we have a method named Merge() through which we can use a Word template and from there, we can generate the PDF with our desired values. And twe can do this by writing only 3-4 lines. It’s that easy.

After using this, the only disappointing thing I found is, Aspose is not free :(

For more Aspose-related information, you can visit here.

So, let’s see how to integrate Aspose in our .NET application and use it to generate PDF from a template.

Integrate Aspose in your .NET application

Aspose is available in NuGet Package Manager library. So, you can install it either from the Package Manager console.

There is one DLL named Aspose.Total, which includes all packages but you can also get the license of individual items like (Aspose.Words, Aspose.PDF, Aspose.HTML etc.). Here, we will use Aspose.Words.

Go to your Package Manager window or search for “Aspose.Words”.

Mail Merge In Aspose C#.NET 

Or, if you want to install it from NuGet Package Manager console, then open the console and copy paste the below command.

PM> Install-Package Aspose.Words -Version 19.5.0

After successful integration, you will find a reference in your application.

Mail Merge In Aspose C#.NET 

Create Word Template

Now, coming to the template part, you have to create a Word document which will contain the mail merge fields. Please go through the provided link to create a Word document using mail merge. Mail Merge in Microsoft Word.

Using Code

Create a solution of any type in Visual Studio. I am taking VS 2017 and creating a console application. Make sure you have already installed the Aspose.Words in your application.

Now, create a Util namespace and add a new class named AsposeHelper and paste the below code snippet.

  1. using System;  
  2. using System.IO;  
  3. using WORDS = Aspose.Words;  
  4. using ASPOSE_Demo.Util.Handlers;  
  6. namespace ASPOSE_Demo.Util  
  7. {  
  8.     public class ASPOSEHelper  
  9.     {  
  10.         public static MemoryStream GenerateMemoryStreamFromWordTemplate(string templateLink,   
  11.             string[] placeholders,   
  12.             object[] values)  
  13.         {  
  14.             try  
  15.             {  
  16.                 MemoryStream dstStream = null;  
  17.                 // Create the document obejct of the template file  
  18.                 var doc = new Aspose.Words.Document(templateLink);  
  19.                 try  
  20.                 {  
  21.                     // Handling the HTML values, which will be replaced in the word template  
  22.                     doc.MailMerge.FieldMergingCallback = new HandleMergeFieldInsertHtml();  
  23.                     // Replace the placeholders of inputted word template  
  24.                     doc.MailMerge.Execute(placeholders, values);  
  25.                     // create Memory stream  
  26.                     dstStream = new MemoryStream();  
  27.                     // save the word file in desired format  
  28.                     doc.Save(dstStream, GetSaveFormat("Pdf"));  
  29.                 }  
  30.                 catch  
  31.                 {  
  32.                     // log  
  33.                     throw;  
  34.                 }  
  35.                 finally  
  36.                 {  
  37.                     doc = null;  
  38.                 }  
  39.                 return dstStream;  
  40.             }  
  41.             catch  
  42.             {  
  43.                 throw;  
  44.             }  
  45.         }  
  47.         private static WORDS.SaveFormat GetSaveFormat(string outputType)  
  48.         {  
  49.             return (WORDS.SaveFormat)Enum.Parse(typeof(WORDS.SaveFormat), outputType.ToString());  
  50.         }  
  51.     }  
  52. }  

This is our Aspose class which will create the PDF as a memory stream and will pass it to the calling method.

Now, you have to create a new Handler method to handle the HTML because if you put any HTML as a value in the mail merge, it will take that as a value only.

For that, create a new class named HandleMergeFieldInsertHtml and paste the below code snippet.

  1. using Aspose.Words;  
  2. using Aspose.Words.MailMerging;  
  4. namespace ASPOSE_Demo.Util.Handlers  
  5. {  
  6.     public class HandleMergeFieldInsertHtml : IFieldMergingCallback  
  7.     {  
  8.         ///  
  9.         /// This is called when merge field is actually merged with data in the document.  
  10.         ///  
  11.         void IFieldMergingCallback.FieldMerging(FieldMergingArgs e)  
  12.         {  
  13.             // All merge fields that expect HTML data should be marked with some prefix, e.g. 'html'.  
  14.             if (e.DocumentFieldName.EndsWith("HTML") || e.DocumentFieldName.StartsWith("HTML"))  
  15.             {  
  16.                 // Insert the text for this merge field as HTML data, using DocumentBuilder.  
  17.                 DocumentBuilder builder = new DocumentBuilder(e.Document);  
  18.                 builder.MoveToMergeField(e.DocumentFieldName);  
  19.                 builder.InsertHtml((string)e.FieldValue);  
  20.                 // The HTML text itself should not be inserted.  
  21.                 // We have already inserted it as an HTML.  
  22.                 e.Text = "";  
  23.             }  
  24.         }  
  26.         void IFieldMergingCallback.ImageFieldMerging(ImageFieldMergingArgs e)  
  27.         {  
  28.             // Do nothing.  
  29.         }  
  30.     }  
  31. }  

Now, please note, if you have to put any HTML data in PDF, then you have to name the Merge fields either starting with “HTML” or ending with “HTML”.

Now, it’s time to consume the Aspose helper class. In your mail method, create two arrays of type string/object. In one array, there will be a series of placeholders (merge fields name). Make sure it is a string array. In another array, there will be the desired values. This can be any type of array. If you have all values in one single type, you can create an array of that type, or you can create an array of type Object.

The count and place should be in same order for both the arrays, otherwise, you will get a runtime exception.

  1. // set the placeholders or create it from DB  
  2. // If any placeholder will be replaced by HTML generated in C# end, named it like Address_Line_1HTML  
  3. // HandleMergeFieldInsertHtml will take care of that  
  4. var placeHolders = new string[] { "Title""First_Name""Company_Name""Address_Line_1""City""ZIP_Code""Email_Address" };  
  6. // set the actual values  
  7. var actualValues = new string[] { "Mr.""Arkadeep""PwC""Dum Dum""Kolkata""700 050"""};  
  9. // set the template location. Use the base location instead of doing lie this.   
  10. // Note: This is only for demo purpose.  
  11. var templateLocation = @"C:\Users\arkadeepde\source\repos\ASPOSE_Demo\ASPOSE_Demo\Template\Template.docx";  
  13. // generating the memory stream   
  14. var memoryStream = ASPOSEHelper.GenerateMemoryStreamFromWordTemplate(templateLocation, placeHolders, actualValues);  
  15. // setting the position to begining of memory steam. [Important]  
  16. memoryStream.Position = 0;  

Now, you have your memory stream. Save it as PDF and enjoy.

  1. // creating the file and performing the write operation  
  2. using (FileStream file = new FileStream(@"C:\D\arka.pdf", FileMode.Create, System.IO.FileAccess.Write))  
  3. {  
  4.     byte[] bytes = new byte[memoryStream.Length];  
  5.     memoryStream.Read(bytes, 0, (int)memoryStream.Length);  
  6.     file.Write(bytes, 0, bytes.Length);  
  7.     memoryStream.Close();