How can one generate docx serial letter in ASP.NET MVC application? I can fill in a simple docx template with data from DB by using docx with Content Controls and OpenXML library - as suggested for example here.
However, when trying to use this for serial letter and merge generated documents into single output docx (hint here), resulting serial letter has data of the first entry - e.g. when I was generating letter for 10 employees and feed this data, resulting output generated 10 letters but all with the data of the first employee.
Edit: (sample code added)
internal static Stream CreateMultiPartDocument(IList<object> data, string templatePath)
{
Stream mainDocumentStream = CreateTempDocument(data[0], templatePath);
for(int i = 1; i < data.Count; i++)
{
object childDocumentData = data[i];
Stream childDocumentStream = CreateTempDocument(childDocumentData, templatePath);
AppendChildDocument(mainDocumentStream, childDocumentStream);
}
mainDocumentStream.Flush();
mainDocumentStream.Position = 0;
return mainDocumentStream;
}
internal static Stream CreateTempDocument(object data, string templatePath)
{
string fullTemplatePath = Path.Combine(TEMPLATE_BASE_PATH, templatePath);
FileStream templateFile = File.Open(fullTemplatePath, FileMode.Open);
if(null != templateFile)
{
MemoryStream fileInMemory = new MemoryStream();
templateFile.CopyTo(fileInMemory);
string customXML = data.SerializeToXml();
ReplaceCustomXmlInMemory(fileInMemory, customXML);
fileInMemory.Flush();
fileInMemory.Position = 0;
templateFile.Close();
return fileInMemory;
}
return null;
}
private static void ReplaceCustomXmlInMemory(MemoryStream fileInMemory, string customXML)
{
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(fileInMemory, true))
{
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
mainPart.DeleteParts(mainPart.CustomXmlParts);
CustomXmlPart customXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
using (StreamWriter streamWriter = new StreamWriter(customXmlPart.GetStream()))
{
streamWriter.Write(customXML);
}
wordDoc.Close();
}
}