Last active
April 17, 2020 14:33
-
-
Save pieterbeens/7008672 to your computer and use it in GitHub Desktop.
A modified version of DoddleReport iTextSharp PdfReportWriter that supports PDF files with multiple reports by implementing the AppendReport method. I've extracted out the logic that adds a report to the PDF document to a new method named AddReportToDocument and used method Document.NewPage to ensure that every report starts on a new page.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Drawing; | |
using System.IO; | |
using System.Linq; | |
using DoddleReport; | |
using iTextSharp.text; | |
using iTextSharp.text.pdf; | |
using Font = iTextSharp.text.Font; | |
using Rectangle = iTextSharp.text.Rectangle; | |
namespace DoddleReport.iTextSharp | |
{ | |
public class AppendablePdfReportWriter : IReportWriter | |
{ | |
public const string TitleStyle = "TitleStyle"; | |
public const string SubTitleStyle = "SubTitleStyle"; | |
public const string HeaderStyle = "HeaderStyle"; | |
public const string FooterStyle = "FooterStyle"; | |
public const string FontFamily = "FontFamily"; | |
internal IDictionary<Report, IList<Report>> ReportsToAppend { get; private set; } | |
public AppendablePdfReportWriter() | |
{ | |
ReportsToAppend = new Dictionary<Report, IList<Report>>(); | |
} | |
/// <summary> | |
/// Writes the report. | |
/// </summary> | |
/// <param name="report">The report.</param> | |
/// <param name="destination">The destination.</param> | |
public void WriteReport(Report report, Stream destination) | |
{ | |
var pageSize = new Rectangle(report.RenderHints.PageSize.Width, report.RenderHints.PageSize.Height); | |
if (report.RenderHints.Orientation == ReportOrientation.Landscape) | |
pageSize = pageSize.Rotate(); | |
var margins = report.RenderHints.Margins; | |
var doc = new Document(pageSize, margins.Width, margins.Width, margins.Height, margins.Height); | |
using (PdfWriter.GetInstance(doc, destination)) | |
{ | |
doc.Open(); | |
AddReportToDocument(report, doc); | |
// Add each report that has to be appended to the Pdf document | |
foreach (Report reportToAppend in ReportsToAppend[report]) | |
{ | |
AddReportToDocument(reportToAppend, doc); | |
} | |
doc.Close(); | |
} | |
} | |
private void AddReportToDocument(Report report, Document doc) | |
{ | |
// Start at a new page | |
doc.NewPage(); | |
var globalTable = new PdfPTable(1) | |
{ | |
HeaderRows = 1, | |
WidthPercentage = 100 | |
}; | |
// Render the header | |
RenderHeader(globalTable, report.TextFields, report.RenderHints); | |
// Render all the rows | |
int fieldsCount = report.DataFields.Count(f => !f.Hidden); | |
var table = new PdfPTable(fieldsCount) | |
{ | |
HeaderRows = 1, | |
WidthPercentage = 100 | |
}; | |
globalTable.AddCell(new PdfPCell(table) | |
{ | |
Border = 0 | |
}); | |
foreach (ReportRow row in report.GetRows()) | |
{ | |
foreach (RowField field in row.Fields.Where(f => !f.Hidden)) | |
{ | |
PdfPCell cell; | |
if (row.RowType == ReportRowType.HeaderRow) | |
{ | |
cell = CreateTextCell(field.HeaderStyle, report.RenderHints[FontFamily] as string, | |
field.HeaderText); | |
} | |
else | |
{ | |
var url = row.GetUrlString(field); | |
cell = url == null | |
? CreateTextCell(field.DataStyle, report.RenderHints[FontFamily] as string, row.GetFormattedValue(field)) | |
: CreateHyperLinkCell(url, row.GetFormattedValue(field)); | |
} | |
cell.Border = 0; | |
cell.Padding = 5; | |
table.AddCell(cell); | |
} | |
} | |
// Render the footer | |
RenderFooter(globalTable, report.TextFields, report.RenderHints); | |
doc.Add(globalTable); | |
} | |
/// <summary> | |
/// Appends the report. | |
/// </summary> | |
/// <param name="source">The source.</param> | |
/// <param name="destination">The destination.</param> | |
public void AppendReport(Report source, Report destination) | |
{ | |
if (source == null || destination == null) | |
throw new ArgumentNullException(source == null ? "source" : "destination"); | |
if (!(source.Writer is AppendablePdfReportWriter)) | |
throw new InvalidOperationException("Unable to append report, the source Writer is not a AppendablePdfReportWriter"); | |
if (!this.ReportsToAppend.ContainsKey(source)) | |
this.ReportsToAppend.Add(source, (IList<Report>)new List<Report>()); | |
this.ReportsToAppend[source].Add(destination); | |
} | |
/// <summary> | |
/// Renders the header. | |
/// </summary> | |
/// <param name="globalTable">The global table.</param> | |
/// <param name="textFields">The text fields.</param> | |
/// <param name="renderHints">The render hints.</param> | |
protected virtual void RenderHeader(PdfPTable globalTable, ReportTextFieldCollection textFields, | |
RenderHintsCollection renderHints) | |
{ | |
int rowCount = 0; | |
if (!string.IsNullOrEmpty(textFields.Title)) | |
{ | |
ReportStyle reportStyle = renderHints[TitleStyle] as ReportStyle ?? GetDefaultTitleStyle(); | |
globalTable.AddCell(CreateTextCell(reportStyle, renderHints[FontFamily] as string, textFields.Title)); | |
rowCount++; | |
} | |
if (!string.IsNullOrEmpty(textFields.SubTitle)) | |
{ | |
ReportStyle reportStyle = renderHints[SubTitleStyle] as ReportStyle ?? GetDefaultSubTitleStyle(); | |
globalTable.AddCell(CreateTextCell(reportStyle, renderHints[FontFamily] as string, textFields.SubTitle)); | |
rowCount++; | |
} | |
if (!string.IsNullOrEmpty(textFields.Header)) | |
{ | |
ReportStyle reportStyle = renderHints[HeaderStyle] as ReportStyle ?? GetDefaultHeaderStyle(); | |
globalTable.AddCell(CreateTextCell(reportStyle, renderHints[FontFamily] as string, textFields.Header)); | |
rowCount++; | |
} | |
if (rowCount > 0) | |
{ | |
PdfPCell cell = CreateTextCell(new ReportStyle(), renderHints[FontFamily] as string, string.Empty); | |
cell.PaddingBottom = 10; | |
globalTable.AddCell(cell); | |
rowCount++; | |
} | |
globalTable.HeaderRows = rowCount; | |
} | |
/// <summary> | |
/// Renders the footer. | |
/// </summary> | |
/// <param name="globalTable">The global table.</param> | |
/// <param name="textFields">The text fields.</param> | |
/// <param name="renderHints">The render hints.</param> | |
protected virtual void RenderFooter(PdfPTable globalTable, ReportTextFieldCollection textFields, | |
RenderHintsCollection renderHints) | |
{ | |
if (!string.IsNullOrEmpty(textFields.Footer)) | |
{ | |
ReportStyle reportStyle = renderHints[FooterStyle] as ReportStyle ?? GetDefaultFooterStyle(); | |
globalTable.AddCell(CreateTextCell(reportStyle, renderHints[FontFamily] as string, textFields.Footer)); | |
} | |
} | |
/// <summary> | |
/// Gets the default title style. | |
/// </summary> | |
/// <returns>The default title style.</returns> | |
private static ReportStyle GetDefaultTitleStyle() | |
{ | |
return new ReportStyle | |
{ | |
Bold = true, | |
FontSize = 18, | |
HorizontalAlignment = HorizontalAlignment.Center | |
}; | |
} | |
/// <summary> | |
/// Gets the default sub title style. | |
/// </summary> | |
/// <returns>The default sub title style.</returns> | |
private static ReportStyle GetDefaultSubTitleStyle() | |
{ | |
return new ReportStyle | |
{ | |
Bold = true, | |
FontSize = 14, | |
HorizontalAlignment = HorizontalAlignment.Center | |
}; | |
} | |
/// <summary> | |
/// Gets the default header style. | |
/// </summary> | |
/// <returns>The default header style.</returns> | |
private static ReportStyle GetDefaultHeaderStyle() | |
{ | |
return new ReportStyle | |
{ | |
Bold = true, | |
FontSize = 11, | |
HorizontalAlignment = HorizontalAlignment.Left | |
}; | |
} | |
/// <summary> | |
/// Gets the default footer style. | |
/// </summary> | |
/// <returns>The default footer style.</returns> | |
private static ReportStyle GetDefaultFooterStyle() | |
{ | |
return new ReportStyle | |
{ | |
HorizontalAlignment = HorizontalAlignment.Left | |
}; | |
} | |
/// <summary> | |
/// Creates the text cell. | |
/// </summary> | |
/// <param name="reportStyle">The report style.</param> | |
/// <param name="fontName">Name of the font.</param> | |
/// <param name="text">The text.</param> | |
/// <returns> | |
/// The newly created cell. | |
/// </returns> | |
private static PdfPCell CreateTextCell(ReportStyle reportStyle, string fontName, string text) | |
{ | |
var par = new Paragraph(text, ConvertStyleToFont(reportStyle, fontName)); | |
var cell = new PdfPCell(par) { Border = 0 }; | |
CopyStyleToCell(reportStyle, cell); | |
return cell; | |
} | |
private static PdfPCell CreateHyperLinkCell(string url, string text) | |
{ | |
Font linkFont = FontFactory.GetFont("Arial", 12, Font.UNDERLINE, new BaseColor(Color.Blue)); | |
Anchor anchor = new Anchor(text, linkFont); | |
anchor.Reference = url; | |
return new PdfPCell(anchor) { Border = 0 }; | |
} | |
/// <summary> | |
/// Converts a report style to a new font definition. | |
/// </summary> | |
/// <param name="reportStyle">The report style.</param> | |
/// <param name="fontFamily">Name of the font.</param> | |
/// <returns>The font.</returns> | |
public static Font ConvertStyleToFont(ReportStyle reportStyle, string fontFamily) | |
{ | |
var font = new Font(); | |
font.SetFamily(fontFamily); | |
if (reportStyle.Underline) | |
{ | |
font.SetStyle(Font.UNDERLINE); | |
} | |
else if (reportStyle.Bold || reportStyle.Italic) | |
{ | |
if (reportStyle.Bold && reportStyle.Italic) | |
{ | |
font.SetStyle(Font.BOLDITALIC); | |
} | |
else if (reportStyle.Bold) | |
{ | |
font.SetStyle(Font.BOLD); | |
} | |
else | |
{ | |
font.SetStyle(Font.ITALIC); | |
} | |
} | |
font.Size = reportStyle.FontSize; | |
font.SetColor(reportStyle.ForeColor.R, reportStyle.ForeColor.G, reportStyle.ForeColor.B); | |
return font; | |
} | |
/// <summary> | |
/// Copies the report style to the cell style. | |
/// </summary> | |
/// <param name="reportStyle">The report style.</param> | |
/// <param name="cell">The cell.</param> | |
public static void CopyStyleToCell(ReportStyle reportStyle, PdfPCell cell) | |
{ | |
cell.BackgroundColor = new BaseColor(reportStyle.BackColor); | |
//cell.Width = reportStyle.Width > 0 ? reportStyle.Width : cell.Width; | |
switch (reportStyle.HorizontalAlignment) | |
{ | |
case HorizontalAlignment.Center: | |
cell.HorizontalAlignment = Element.ALIGN_CENTER; | |
break; | |
case HorizontalAlignment.Left: | |
cell.HorizontalAlignment = Element.ALIGN_LEFT; | |
break; | |
case HorizontalAlignment.Right: | |
cell.HorizontalAlignment = Element.ALIGN_RIGHT; | |
break; | |
} | |
switch (reportStyle.VerticalAlignment) | |
{ | |
case VerticalAlignment.Bottom: | |
cell.VerticalAlignment = Element.ALIGN_BOTTOM; | |
break; | |
case VerticalAlignment.Middle: | |
cell.VerticalAlignment = Element.ALIGN_MIDDLE; | |
break; | |
case VerticalAlignment.Top: | |
cell.VerticalAlignment = Element.ALIGN_TOP; | |
break; | |
} | |
if (reportStyle.TextRotation % 90 == 0) | |
cell.Rotation = reportStyle.TextRotation; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment