From 11237972b0f8c306cc35bb4ca4abc6f1c7008238 Mon Sep 17 00:00:00 2001 From: Cobus Smit Date: Tue, 21 Feb 2017 11:14:12 +0200 Subject: [PATCH 1/4] feature: ITextSharp report writer can now accept an image file (jpg,png,gif) to be displayed in the Title section via ReportTitleStyle class. User supplies details using TitleStyle render hint --- .../DoddleReport.Sample.WinForms.csproj | 9 +++ .../Form1.Designer.cs | 27 +++---- src/DoddleReport.Sample.WinForms/Form1.cs | 66 +++++++++++++++++ .../Properties/Resources.Designer.cs | 2 +- .../Properties/Resources.resx | 13 ++-- .../Resources/Logomakr.png | Bin 0 -> 3069 bytes .../PdfReportWriter.cs | 70 +++++++++++++++--- src/DoddleReport/DoddleReport.csproj | 2 + src/DoddleReport/ReportImage.cs | 9 +++ src/DoddleReport/ReportTitleStyle.cs | 8 ++ 10 files changed, 178 insertions(+), 28 deletions(-) create mode 100644 src/DoddleReport.Sample.WinForms/Resources/Logomakr.png create mode 100644 src/DoddleReport/ReportImage.cs create mode 100644 src/DoddleReport/ReportTitleStyle.cs diff --git a/src/DoddleReport.Sample.WinForms/DoddleReport.Sample.WinForms.csproj b/src/DoddleReport.Sample.WinForms/DoddleReport.Sample.WinForms.csproj index 842d735..a2cddd4 100644 --- a/src/DoddleReport.Sample.WinForms/DoddleReport.Sample.WinForms.csproj +++ b/src/DoddleReport.Sample.WinForms/DoddleReport.Sample.WinForms.csproj @@ -85,6 +85,10 @@ {355CAFF3-F806-4194-BE54-2F7640463CED} DoddleReport.AbcPdf + + {347d0716-0297-4866-9fd5-5e019b51c408} + DoddleReport.iTextSharp + {0646C575-0EA6-4331-809C-10DC000929F3} DoddleReport.OpenXml @@ -94,6 +98,11 @@ DoddleReport + + + Always + + + @@ -68,9 +69,10 @@ - + + @@ -85,9 +87,10 @@ - + + @@ -109,9 +112,9 @@ 2.0 - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 \ No newline at end of file diff --git a/src/DoddleReport.Sample.WinForms/Resources/Logomakr.png b/src/DoddleReport.Sample.WinForms/Resources/Logomakr.png new file mode 100644 index 0000000000000000000000000000000000000000..0c602d413b88b7dddba6832f84d9d4c05a2cf6e7 GIT binary patch literal 3069 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 + /// Creates a new Title cell + /// + /// Title text. + /// The render hints. + /// The newly created Title cell + private static PdfPCell CreateTitleCell(string titleText, RenderHintsCollection renderHints) + { + var reportStyle = renderHints[TitleStyle] as ReportTitleStyle ?? GetDefaultTitleStyle(); + + var table = new PdfPTable(2); + table.SetWidths(new[] {reportStyle.ImageWidthPercentage, (100 - reportStyle.ImageWidthPercentage)}); + + if (reportStyle.Image != null) + { + table.AddCell(CreateImageCell(reportStyle.Image)); + } + else + { + table.AddCell(CreateEmptyCell()); + } + + table.AddCell(CreateTextCell(reportStyle, renderHints[FontFamily] as string, titleText)); + + + var headerTableCell = new PdfPCell(table) {Border = 0}; + return headerTableCell; + } + + /// + /// Creates a new Image cell + /// + /// The image details + /// The newly created Image cell + private static PdfPCell CreateImageCell(ReportImage imageDetails) + { + var headerImage = Image.GetInstance(imageDetails.ImageData); + headerImage.ScaleToFit(imageDetails.Width, imageDetails.Height); + return new PdfPCell(headerImage) {Border = 0}; + } + + /// + /// Creates an Empty cell + /// + /// The empty cell + private static PdfPCell CreateEmptyCell() + { + return new PdfPCell() { Border = 0 }; + } + /// /// Renders the footer. /// @@ -161,14 +212,15 @@ protected virtual void RenderFooter(PdfPTable globalTable, ReportTextFieldCollec /// Gets the default title style. /// /// The default title style. - private static ReportStyle GetDefaultTitleStyle() + private static ReportTitleStyle GetDefaultTitleStyle() { - return new ReportStyle - { - Bold = true, - FontSize = 18, - HorizontalAlignment = HorizontalAlignment.Center - }; + return new ReportTitleStyle + { + Bold = true, + FontSize = 18, + HorizontalAlignment = HorizontalAlignment.Center, + ImageWidthPercentage = 0 + }; } /// diff --git a/src/DoddleReport/DoddleReport.csproj b/src/DoddleReport/DoddleReport.csproj index a4b111e..a920f8c 100644 --- a/src/DoddleReport/DoddleReport.csproj +++ b/src/DoddleReport/DoddleReport.csproj @@ -89,8 +89,10 @@ + + diff --git a/src/DoddleReport/ReportImage.cs b/src/DoddleReport/ReportImage.cs new file mode 100644 index 0000000..9c5bfb0 --- /dev/null +++ b/src/DoddleReport/ReportImage.cs @@ -0,0 +1,9 @@ +namespace DoddleReport +{ + public class ReportImage + { + public byte[] ImageData { get; set; } + public int Width { get; set; } + public int Height { get; set; } + } +} \ No newline at end of file diff --git a/src/DoddleReport/ReportTitleStyle.cs b/src/DoddleReport/ReportTitleStyle.cs new file mode 100644 index 0000000..06f71e7 --- /dev/null +++ b/src/DoddleReport/ReportTitleStyle.cs @@ -0,0 +1,8 @@ +namespace DoddleReport +{ + public class ReportTitleStyle : ReportStyle + { + public ReportImage Image { get; set; } + public int ImageWidthPercentage { get; set; } + } +} \ No newline at end of file From 6060969f2776dfe608b247782be9f781e65e30f6 Mon Sep 17 00:00:00 2001 From: Cobus Smit Date: Tue, 21 Feb 2017 13:25:04 +0200 Subject: [PATCH 2/4] bugfix: ensure backwards compatibility for existing code using ReportStyle class to set Title style. --- src/DoddleReport.iTextSharp/PdfReportWriter.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/DoddleReport.iTextSharp/PdfReportWriter.cs b/src/DoddleReport.iTextSharp/PdfReportWriter.cs index 54bbf25..62610f3 100644 --- a/src/DoddleReport.iTextSharp/PdfReportWriter.cs +++ b/src/DoddleReport.iTextSharp/PdfReportWriter.cs @@ -149,14 +149,15 @@ protected virtual void RenderHeader(PdfPTable globalTable, ReportTextFieldCollec /// The newly created Title cell private static PdfPCell CreateTitleCell(string titleText, RenderHintsCollection renderHints) { - var reportStyle = renderHints[TitleStyle] as ReportTitleStyle ?? GetDefaultTitleStyle(); + var reportTitleStyle = renderHints[TitleStyle] as ReportTitleStyle ?? GetDefaultTitleStyle(); + var reportStyle = renderHints[TitleStyle] as ReportStyle ?? GetDefaultTitleStyle(); var table = new PdfPTable(2); - table.SetWidths(new[] {reportStyle.ImageWidthPercentage, (100 - reportStyle.ImageWidthPercentage)}); + table.SetWidths(new[] { reportTitleStyle.ImageWidthPercentage, (100 - reportTitleStyle.ImageWidthPercentage)}); - if (reportStyle.Image != null) + if (reportTitleStyle.Image != null) { - table.AddCell(CreateImageCell(reportStyle.Image)); + table.AddCell(CreateImageCell(reportTitleStyle.Image)); } else { From 920f1753b83cac79efe906a5588664e95f5a5202 Mon Sep 17 00:00:00 2001 From: Cobus Smit Date: Wed, 22 Feb 2017 08:25:10 +0200 Subject: [PATCH 3/4] feature: Added TitleStyle, SubTitleStyle and HeaderStyle render hints to HtmlReportWriter. User can also specify logo image when passing in a ReportTitleStyle object to TitleStyle. --- .../Form1.Designer.cs | 3 +- src/DoddleReport.Sample.WinForms/Form1.cs | 72 +++++++++++++++++++ src/DoddleReport/Writers/HtmlReportWriter.cs | 67 +++++++++++++---- 3 files changed, 128 insertions(+), 14 deletions(-) diff --git a/src/DoddleReport.Sample.WinForms/Form1.Designer.cs b/src/DoddleReport.Sample.WinForms/Form1.Designer.cs index 7b7477c..0c68c66 100644 --- a/src/DoddleReport.Sample.WinForms/Form1.Designer.cs +++ b/src/DoddleReport.Sample.WinForms/Form1.Designer.cs @@ -38,7 +38,8 @@ private void InitializeComponent() this.cmbReportType.FormattingEnabled = true; this.cmbReportType.Items.AddRange(new object[] { "Excel (Open XML)", - "PDF with title image (ITextSharp)"}); + "PDF with title image (ITextSharp)", + "HTML with custom title style & image"}); this.cmbReportType.Location = new System.Drawing.Point(98, 31); this.cmbReportType.Name = "cmbReportType"; this.cmbReportType.Size = new System.Drawing.Size(218, 21); diff --git a/src/DoddleReport.Sample.WinForms/Form1.cs b/src/DoddleReport.Sample.WinForms/Form1.cs index 4284517..20b4f2f 100644 --- a/src/DoddleReport.Sample.WinForms/Form1.cs +++ b/src/DoddleReport.Sample.WinForms/Form1.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Drawing; using DoddleReport.Sample.WinForms.Properties; +using DoddleReport.Writers; namespace DoddleReport.Sample.WinForms { @@ -31,6 +32,10 @@ private void button1_Click(object sender, System.EventArgs e) { RenderPdfWithImage(); } + else if (cmbReportType.Text == "HTML with custom title style & image") + { + RenderHtmlWithImage(); + } } private static void RenderExcel() @@ -119,5 +124,72 @@ private static void RenderPdfWithImage() Process.Start("Report.pdf"); } + + + private static void RenderHtmlWithImage() + { + var query = DoddleProductRepository.GetAll(); + var totalProducts = query.Count; + var totalOrders = query.Sum(p => p.OrderCount); + + // Create the report and turn our query into a ReportSource + var report = new Report(query.ToReportSource(), new HtmlReportWriter()); + + // Customize the Text Fields + report.TextFields.Title = "Products Report"; + report.TextFields.SubTitle = "This is a sample report showing how Doddle Report works"; + report.TextFields.Footer = "Copyright 2011 © The Doddle Project"; + report.TextFields.Header = string.Format(@" + Report Generated: {0} + Total Products: {1} + Total Orders: {2} + Total Sales: {3:c}", DateTime.Now, totalProducts, totalOrders, totalProducts * totalOrders); + + // Render hints allow you to pass additional hints to the reports as they are being rendered + report.RenderHints.BooleanCheckboxes = true; + + report.RenderHints["TitleStyle"] = new ReportTitleStyle + { + Bold = true, + Underline = true, + FontSize = 18, + HorizontalAlignment = HorizontalAlignment.Left, + ForeColor = Color.SteelBlue, + Image = new ReportImage + { + ImageData = File.ReadAllBytes(@"./Resources/Logomakr.png"), + Width = 150, + Height = 100 + } + }; + + report.RenderHints["SubTitleStyle"] = new ReportStyle + { + Bold = true, + FontSize = 12, + HorizontalAlignment = HorizontalAlignment.Left, + ForeColor = Color.SteelBlue + }; + + report.RenderHints["HeaderStyle"] = new ReportStyle + { + Italic = true, + FontSize = 10, + HorizontalAlignment = HorizontalAlignment.Left, + ForeColor = Color.Salmon + }; + + // Customize the data fields + report.DataFields["Id"].Hidden = true; + report.DataFields["Price"].DataFormatString = "{0:c}"; + report.DataFields["LastPurchase"].DataFormatString = "{0:d}"; + + using (var stream = File.Create("Report.html")) + { + report.WriteReport(stream); + } + + Process.Start("Report.html"); + } } } diff --git a/src/DoddleReport/Writers/HtmlReportWriter.cs b/src/DoddleReport/Writers/HtmlReportWriter.cs index 67387a5..6fe1420 100644 --- a/src/DoddleReport/Writers/HtmlReportWriter.cs +++ b/src/DoddleReport/Writers/HtmlReportWriter.cs @@ -6,6 +6,9 @@ namespace DoddleReport.Writers { public class HtmlReportWriter : IReportWriter { + public const string TitleStyle = "TitleStyle"; + public const string SubTitleStyle = "SubTitleStyle"; + public const string HeaderStyle = "HeaderStyle"; public const string HtmlStyle = "HtmlStyle"; public const string HtmlLogo = "HtmlLogo"; @@ -32,22 +35,48 @@ protected virtual string InternalStyling() /// /// This CSS style will be applied to the top of every report. You may override this property to customize the default CSS that gets rendered on all HTML reports /// - public static string DefaultStyle + public static string GetDefaultStyle() { - get - { - var style = @" + + var style = @" .htmlReport { font: 12px Verdana; } .htmlReport h1 { font-size: 12pt; margin-bottom: 10px; } - .htmlReport .title { margin-bottom: 1px; } + .htmlReport .titleImage { vertical-align:middle; } + .htmlReport .title { margin-bottom: 1px; vertical-align:middle; } .htmlReport .subTitle { margin-bottom: 3px; margin-top: 1px; } .htmlReport .header { padding-bottom: 8px; border-bottom: solid 1px #ccc; } \r\n"; + + style += ".htmlReport td { " + ReportStyle.HeaderRowStyle.ToCss() + "}\r\n"; + style += ".htmlReport th { " + ReportStyle.DataRowStyle.ToCss() + "}\r\n"; + + return style; + } + + /// + /// Generates the custom CSS styles passed in via the render hints + /// + public static string GetCustomStyle(RenderHintsCollection hints) + { - style += ".htmlReport td { " + ReportStyle.HeaderRowStyle.ToCss() + "}\r\n"; - style += ".htmlReport th { " + ReportStyle.DataRowStyle.ToCss() + "}\r\n"; + var style = string.Empty; - return style; + var titleStyle = hints[TitleStyle] as ReportStyle; + if (titleStyle != null) + { + style += ".htmlReport .titleHint { " + titleStyle.ToCss() + "}\r\n"; + } + var subTitleStyle = hints[SubTitleStyle] as ReportStyle; + if (subTitleStyle != null) + { + style += ".htmlReport .subTitleHint { " + subTitleStyle.ToCss() + "}\r\n"; } + var headerStyle = hints[HeaderStyle] as ReportStyle; + if (headerStyle != null) + { + style += ".htmlReport .headerHint { " + headerStyle.ToCss() + "}\r\n"; + } + + return style; } protected void AppendStyling(RenderHintsCollection hints) @@ -56,9 +85,12 @@ protected void AppendStyling(RenderHintsCollection hints) Html.AppendLine(@"