As mentioned in MS Documenation:
Word does not repeat header rows on page two and greater, although you set the RepeatOnNewPage property of the static header row in a tablix (table, matrix, or list) to True. You can define explicit page breaks in your report to force header rows to appear on new pages. However, because Word applies its own pagination to the rendered report exported to Word, results might vary and the header row might not repeat predictably. The static header row is the row that contains the column headings.
So how to repeat group headers on every page when outputting RDLC report to Word documents?
This solution is using OpenXML as document processing.
Who may also find this helpful
Limitations:
Assumptions:
Summary of the Solution:
Key Steps
Put and align you group header and table header in the Header Section (not inside Tablix)
[GroupHeaderText1] is the header text you want to repeat and different for every group.
It will appears on every page in the Word document.
Depends on your report and data structure, prepare your data accordingly.
Example
public class SampleData
{
public string GroupHeaderField { get; set; }
public string Data1 { get; set; }
public string Data2 { get; set; }
public string Data3 { get; set; }
}
Part of function for report generation
ReportViewer rv = new ReportViewer();
ReportDataSource reportDataSource = new ReportDataSource();
reportDataSource.Name = "SampleData";
List<SampleData> dataForReport = GetData();
reportDataSource.Value = dataForReport;
rv.LocalReport.DataSources.Add(reportDataSource);
List<string> lstReplace = new List<string>();
//Prepare the data
foreach (SampleData sa in dataForReport)
{
if (!lstReplace.Contains(sa.GroupHeaderField))
{
lstReplace.Add(sa.GroupHeaderField);
}
}
lstReplace now contains the value for dynamic group headers.
Get the header we prepared at Step 1 as template, we are using it for Section Header
WordprocessingDocument wordDoc = WordprocessingDocument.Open(docPath, true);
MainDocumentPart mainDocPart = wordDoc.MainDocumentPart;
HeaderPart defaultHeaderPart = mainDocPart.HeaderParts.FirstOrDefault();
Now we create header part for each section (group)
List<string> newSectionHeaderIds = new List<string>();
foreach (string groupHeaderText in lstReplace)
{
HeaderPart newGroupHeaderPart = mainDocPart.AddNewPart<HeaderPart>();
string sId = mainDocPart.GetIdOfPart(newGroupHeaderPart);
Header newHeader = (Header)defaultHeaderPart.Header.Clone();
foreach (Paragraph p in newHeader.Descendants<Paragraph>())
{
foreach (Run r in p.Descendants<Run>())
{
foreach (Text t in r.Descendants<Text>())
{
t.Text = t.Text.Replace("[GroupHeaderText1]", groupHeaderText);
}
}
}
newHeader.Save(newGroupHeaderPart);
newSectionHeaderIds.Add(sId);
}
This code basically
To understand better, you should use Open XML SDK 2.5 for Microsoft Office and study a DOCX document structure.
Section Headers are ready. Now create some sections.
By default, report generated by SSRS has Page Break between groups.
We just need to replace them.
Create a SectionProperties template to create sections in Word Document, such that we can have different headers between groups. (You can change PageSize and etc. using this property)
SectionProperties defaultProperties = mainDocumentPart.Document.Body.Descendants<SectionProperties>().FirstOrDefault();
defaultProperties.AppendChild(new SectionType { Val = SectionMarkValues.NextPage });
Now find and replace page break
foreach (Paragraph p in document.Body.Descendants<Paragraph>())
{
foreach (Run r in p.Elements<Run>())
{
foreach (Break b in r.Descendants<Break>())
{
if (b.Type != null)
{
if (b.Type.Value == BreakValues.Page)
{
b.Remove(); //Remove the page break
p.Descendants<ParagraphProperties>().FirstOrDefault().AppendChild(defaultProperties.CloneNode(true)); //Replace by a cloned section break
}
}
}
}
}
Note that properties like page size, width and height is independent for each section, you should set it in Step 5
Remember the newSectionHeaderIds List we created in Step 5? Now we bind them.
int i = 0;
foreach (SectionProperties sp in document.Body.Descendants<SectionProperties>())
{
//Replace them
sp.RemoveAllChildren<HeaderReference>();
sp.PrependChild(new HeaderReference() { Id = newSectionHeaderIds[i], Type = HeaderFooterValues.Default });
i++;
}
The most important Step of all... Save it.
wordDoc.Save();
You should be good to go, let me know it you have questions.