We have an application where we use the region mail merge to create an invoice layout (header + detail lines). In the detail lines we also need to be able to inject subheaders.
The way we do this is to have a mergefield “subheader” which is added to the other fields like “description”, “quantity”, “unitprice”, … Either the “subheader” field has content, or all the other fields have content. Never both at the same time.
In a custom IFieldMergingCallback we check if the subheader field has content and give the row a gray background. We would also like to join all columns on the row, so the subheader field has the full width of the table. The hard part is that the “subheader” field can be in any of the columns as our client can adapt the template.
So the question is, how do we join all columns and display the content of the “subheader” field on the row?
@Jan_Gils Could you please attach your sample template, data, your current output and expected output here for our reference? We will check and provide you more information.
If the problem is in merging cells horizontally, please see our documentation to learn how to work with merged cells:
https://docs.aspose.com/words/net/working-with-merged-cells/
Have you considered using nested mail merge to generate a report with subheading:
https://docs.aspose.com/words/net/nested-mail-merge-with-regions/
@alexey.noskov I’ve included an example document :
invoice subheader.docx (20.5 KB)
Currently, we’re putting a background colour on the row, using the IFieldMergingCallback
void IFieldMergingCallback.FieldMerging(FieldMergingArgs args)
{
//Check if header field has content
if (args.FieldName == "Item.Header" && !string.IsNullOrEmpty(args.FieldValue.ToString()))
{
//get objects
var cell = (Aspose.Words.Tables.Cell)args.Field.Start.GetAncestor(NodeType.Cell);
var row = (Aspose.Words.Tables.Row)args.Field.Start.GetAncestor(NodeType.Row);
if (row != null && cell != null)
{
//Set background color
for (int i = 0; i < row.Cells.Count; i++)
{
row.Cells[i].CellFormat.Shading.BackgroundPatternColor = Color.FromArgb(238, 238, 238);
}
//merge all columns and set the content of the merged cell to the header field
//item.header mergefield can be in any column of the table, but will only occur once
//if it has a value, all other mergefields will be empty
//TODO
}
}
}
@Jan_Gils Please try using the following code:
// Create dummy data source
DataTable items = new DataTable("Items");
items.Columns.Add("Item.AnimalName");
items.Columns.Add("Item.Description");
items.Columns.Add("Item.Header");
items.Columns.Add("Item.Quantity");
items.Columns.Add("Item.UnitPriceExcl");
items.Columns.Add("Item.TotalExcl");
items.Columns.Add("Item.VatPercentage");
for (int i = 0; i < 5; i++)
{
DataRow header = items.NewRow();
header["Item.Header"] = $"Header {i}";
items.Rows.Add(header);
for (int j = 0; j < 5; j++)
items.Rows.Add($"test {i}-{j}", "test", "", "test", "test", "test", "test");
}
Document doc = new Document(@"C:\Temp\in.docx");
doc.MailMerge.FieldMergingCallback = new MyCallback();
doc.MailMerge.MergeDuplicateRegions = true;
doc.MailMerge.ExecuteWithRegions(items);
doc.Save(@"C:\Temp\out.docx");
private class MyCallback : IFieldMergingCallback
{
public void FieldMerging(FieldMergingArgs args)
{
//Check if header field has content
if (args.FieldName == "Item.Header" && !string.IsNullOrEmpty(args.FieldValue.ToString()))
{
//get objects
var cell = (Aspose.Words.Tables.Cell)args.Field.Start.GetAncestor(NodeType.Cell);
var row = (Aspose.Words.Tables.Row)args.Field.Start.GetAncestor(NodeType.Row);
if (row != null && cell != null)
{
//Set background color
for (int i = 0; i < row.Cells.Count; i++)
{
row.Cells[i].CellFormat.Shading.BackgroundPatternColor = Color.FromArgb(238, 238, 238);
}
//merge all columns and set the content of the merged cell to the header field
//item.header mergefield can be in any column of the table, but will only occur once
//if it has a value, all other mergefields will be empty
// Move all contnet into the first cell and merge cells horizontally.
Cell firstCell = row.FirstCell;
firstCell.CellFormat.HorizontalMerge = CellMerge.First;
for (int i = 1; i < row.Cells.Count; i++)
{
Cell c = row.Cells[i];
c.CellFormat.HorizontalMerge = CellMerge.Previous;
while(c.FirstParagraph.HasChildNodes)
firstCell.LastParagraph.AppendChild(c.FirstParagraph.FirstChild);
}
}
}
}
public void ImageFieldMerging(ImageFieldMergingArgs args)
{
// Do nothing
}
}
out.docx (17.5 KB)
@alexey.noskov Thanks for the code example. This works perfect!
1 Like