From 5ecaa601518b83d308e30b82c8f6c29868a807ec Mon Sep 17 00:00:00 2001 From: Peter Gill Date: Sat, 8 Feb 2025 18:46:28 -0330 Subject: [PATCH] Add fluent API methods and new tests for PDF export Introduced new test class `ManualFluentChainedReportDefinitionTest` with methods for PDF export verification. Enhanced `Body`, `Report`, `ReportItemsBody`, and `Table` classes with fluent methods for better report definition. Added `GenerateTestData` method for sample report creation. --- ...ManualFluentChainedReportDefinitionTest.cs | 324 ++++++++++++++++++ RdlCreator/Body.cs | 15 + RdlCreator/Report.cs | 86 ++++- RdlCreator/ReportItemsBody.cs | 7 +- RdlCreator/Table.cs | 36 ++ 5 files changed, 466 insertions(+), 2 deletions(-) create mode 100644 RdlCreator.Tests/ManualFluentChainedReportDefinitionTest.cs diff --git a/RdlCreator.Tests/ManualFluentChainedReportDefinitionTest.cs b/RdlCreator.Tests/ManualFluentChainedReportDefinitionTest.cs new file mode 100644 index 00000000..782141d3 --- /dev/null +++ b/RdlCreator.Tests/ManualFluentChainedReportDefinitionTest.cs @@ -0,0 +1,324 @@ +using System.Collections.Generic; +using System.IO; +using System.Xml.Serialization; +using System; +using Majorsilence.Reporting.RdlCreator; +using NUnit.Framework; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UglyToad.PdfPig; +using System.Linq; + +namespace Majorsilence.Reporting.RdlCreator.Tests +{ + [TestFixture] + public class ManualFluentChainedReportDefinitionTest + { + string connectionString = "Data Source=sqlitetestdb2.db;"; + string dataProvider = "Microsoft.Data.Sqlite"; + + [Test] + public async Task PdfStreamExport() + { + var create = new RdlCreator.Create(); + var report = GenerateTestData(); + var fyiReport = await create.GenerateRdl(report); + using var ms = new Majorsilence.Reporting.Rdl.MemoryStreamGen(); + await fyiReport.RunGetData(null); + await fyiReport.RunRender(ms, Majorsilence.Reporting.Rdl.OutputPresentationType.PDF); + var pdfStream = ms.GetStream(); + + pdfStream.Position = 0; + using var pdfDocument = PdfDocument.Open(pdfStream); + var text = string.Join(" ", pdfDocument.GetPages().SelectMany(page => page.GetWords()).Select(word => word.Text)); + + Assert.That(text, Is.Not.Null); + Assert.That(text, Is.EqualTo("Test Data Set Report CategoryID CategoryName Description Beverages Soft drinks, coffees, teas, beers, and ales Condiments Sweet and savory sauces, relishes, spreads, and seasonings Confections Desserts, candies, and sweet breads Dairy Products Cheeses Grains/Cereals Breads, crackers, pasta, and cereal Meat/Poultry Prepared meats Produce Dried fruit and bean curd Seafood Seaweed and fish 1 of 1")); + } + + [Test] + public async Task PdfDiskExport() + { + var create = new RdlCreator.Create(); + var report = GenerateTestData(); + var fyiReport = await create.GenerateRdl(report); + using var ms = new Majorsilence.Reporting.Rdl.MemoryStreamGen(); + await fyiReport.RunGetData(null); + await fyiReport.RunRender(ms, Majorsilence.Reporting.Rdl.OutputPresentationType.PDF); + var pdfStream = ms.GetStream(); + pdfStream.Position = 0; + + using var fileStream = new FileStream("PdfChainedDiskExport.pdf", FileMode.Create, FileAccess.Write); + pdfStream.CopyTo(fileStream); + await fileStream.DisposeAsync(); + + using var pdfDocument = PdfDocument.Open("PdfChainedDiskExport.pdf"); + var text = string.Join(" ", pdfDocument.GetPages().SelectMany(page => page.GetWords()).Select(word => word.Text)); + + Assert.That(text, Is.Not.Null); + Assert.That(text, Is.EqualTo("Test Data Set Report CategoryID CategoryName Description Beverages Soft drinks, coffees, teas, beers, and ales Condiments Sweet and savory sauces, relishes, spreads, and seasonings Confections Desserts, candies, and sweet breads Dairy Products Cheeses Grains/Cereals Breads, crackers, pasta, and cereal Meat/Poultry Prepared meats Produce Dried fruit and bean curd Seafood Seaweed and fish 1 of 1")); + } + + + private RdlCreator.Report GenerateTestData() + { + + var report = new Report + { + Description = "Sample report", + Author = "John Doe", + PageHeight = "11in", + PageWidth = "8.5in", + Width = "7.5in", + TopMargin = ".25in", + LeftMargin = ".25in", + RightMargin = ".25in", + BottomMargin = ".25in" + } + .WithDataSources( + new DataSources + { + DataSource = new DataSource + { + Name = "DS1", + ConnectionProperties = new ConnectionProperties + { + DataProvider = dataProvider, + ConnectString = connectionString + } + } + } + ) + .WithDataSets( + new DataSets + { + DataSet = new DataSet + { + Name = "Data", + Query = new Query + { + DataSourceName = "DS1", + CommandText = "SELECT CategoryID, CategoryName, Description FROM Categories" + }, + Fields = new Fields + { + Field = new List + { + new Field { Name = "CategoryID", DataField = "CategoryID", TypeName = "System.Int64" }, + new Field { Name = "CategoryName", DataField = "CategoryName", TypeName = "System.String" }, + new Field { Name = "Description", DataField = "Description", TypeName = "System.String" } + } + } + } + } + ) + .WithPageHeader( + new PageHeader + { + Height = ".5in", + ReportItems = new ReportItemsHeader + { + Textbox = new Textbox + { + Name = "Textbox1", + Top = ".1in", + Left = ".1in", + Width = "6in", + Height = ".25in", + Value = new Value { Text = "Test Data Set Report" }, + Style = new Style { FontSize = "15pt", FontWeight = "Bold" } + } + }, + PrintOnFirstPage = "true", + PrintOnLastPage = "true" + }) + .WithPageFooter(new PageFooter + { + Height = "14pt", + ReportItems = new ReportItemsFooter + { + Textbox = new Textbox + { + Name = "Textbox5", + Top = "1pt", + Left = "10pt", + Height = "12pt", + Width = "3in", + Value = new Value { Text = "=Globals!PageNumber + ' of ' + Globals!TotalPages" }, + Style = new Style { FontSize = "10pt", FontWeight = "Normal" } + } + }, + PrintOnFirstPage = "true", + PrintOnLastPage = "true" + }); + + // Add a body to the report + + report + .WithBody() + .WithHeight("36pt") + .WithReportItems() + .WithTableName("Table1") + .WithDataSetName("Data") + .WithNoRows("Query returned no rows!") + .WithHeader(new Header + { + TableRows = new TableRows + { + TableRow = new TableRow + { + Height = "12pt", + TableCells = new TableCells() + { + TableCell = new List + { + new TableCell { ReportItems= new TableCellReportItems(){ ReportItem = new Textbox { Name = "Textbox2", + Value = new Value { Text = "CategoryID" }, + Style = new Style { TextAlign = "Center", FontWeight = "Bold" } } } }, + new TableCell { ReportItems= new TableCellReportItems(){ReportItem = new Textbox { Name = "Textbox3", + Value = new Value { Text = "CategoryName" }, + Style = new Style { TextAlign = "Center", FontWeight = "Bold" } } } }, + new TableCell { ReportItems= new TableCellReportItems(){ReportItem = new Textbox { Name = "Textbox4", + Value = new Value { Text = "Description" }, + Style = new Style { TextAlign = "Center", FontWeight = "Bold" } } } } + } + } + } + }, + RepeatOnNewPage = "true" + }) + .WithTableColumns(new TableColumns + { + TableColumn = new List + { + new TableColumn { Width = "1.25in" }, + new TableColumn { Width = "1.5in" }, + new TableColumn { Width = "1.375in" } + } + }) + .WithDetails(new Details + { + TableRows = new TableRows + { + TableRow = new TableRow + { + Height = "12pt", + TableCells = new TableCells() + { + TableCell = new List + { + new TableCell { + ReportItems= new TableCellReportItems() + { + ReportItem = new CustomReportItems() + { + Name = "QrCode", + Type = "QR Code", + Width = "35.91mm", + Height = "35.91mm", + CustomProperties = new CustomProperties + { + CustomProperty = new CustomProperty() + { + Name = "QrCode", + Value = "=Fields!CategoryID.Value" + } + }, + CanGrow="true", + Style = new Style + { + BorderStyle= new BorderStyle + { + Default="None", + Bottom="Solid" + }, + BorderColor=new BorderColor + { + Bottom = "Gray" + }, + BorderWidth= new BorderWidth + { + Bottom="1pt" + } + + } + } + } + }, + new TableCell + { + ReportItems = new TableCellReportItems() + { + ReportItem = new Textbox { + Name = "CategoryName", + Value = new Value + { + Text = "=Fields!CategoryName.Value" + }, + CanGrow = "true", + Style = new Style + { + BorderStyle= new BorderStyle + { + Default="None", + Bottom="Solid" + }, + BorderColor=new BorderColor + { + Bottom = "Gray" + }, + BorderWidth= new BorderWidth + { + Bottom="1pt" + } + + } + } + } + }, + new TableCell + { + ReportItems= new TableCellReportItems() + { + ReportItem = new Textbox + { + Name = "Description", + Value = new Value + { + Text = "=Fields!Description.Value" + }, + CanGrow = "true", + Style = new Style + { + BorderStyle= new BorderStyle + { + Default="None", + Bottom="Solid" + }, + BorderColor=new BorderColor + { + Bottom = "Gray" + }, + BorderWidth= new BorderWidth + { + Bottom="1pt" + } + + } + } + } + } + } + } + } + } + }) + + ; + + + + return report; + } + } +} diff --git a/RdlCreator/Body.cs b/RdlCreator/Body.cs index f2e726d1..2b9967b5 100644 --- a/RdlCreator/Body.cs +++ b/RdlCreator/Body.cs @@ -13,5 +13,20 @@ public class Body [XmlElement(ElementName = "Height")] public string Height { get; set; } + + public Table WithReportItems() + { + this.ReportItems = new ReportItemsBody() + { + Table = new Table() + }; + return ReportItems.Table; + } + + public Body WithHeight(string height) + { + this.Height = height; + return this; + } } } \ No newline at end of file diff --git a/RdlCreator/Report.cs b/RdlCreator/Report.cs index 37fd3149..bb6c7cfc 100644 --- a/RdlCreator/Report.cs +++ b/RdlCreator/Report.cs @@ -1,6 +1,5 @@ using System.Xml.Serialization; - namespace Majorsilence.Reporting.RdlCreator { // Report class representing the root element @@ -48,5 +47,90 @@ public class Report [XmlElement(ElementName = "PageFooter")] public PageFooter PageFooter { get; set; } + + // Fluid style methods + public Report WithDescription(string description) + { + Description = description; + return this; + } + + public Report WithAuthor(string author) + { + Author = author; + return this; + } + + public Report WithPageHeight(string pageHeight) + { + PageHeight = pageHeight; + return this; + } + + public Report WithPageWidth(string pageWidth) + { + PageWidth = pageWidth; + return this; + } + + public Report WithDataSources(DataSources dataSources) + { + DataSources = dataSources; + return this; + } + + public Report WithWidth(string width) + { + Width = width; + return this; + } + + public Report WithTopMargin(string topMargin) + { + TopMargin = topMargin; + return this; + } + + public Report WithLeftMargin(string leftMargin) + { + LeftMargin = leftMargin; + return this; + } + + public Report WithRightMargin(string rightMargin) + { + RightMargin = rightMargin; + return this; + } + + public Report WithBottomMargin(string bottomMargin) + { + BottomMargin = bottomMargin; + return this; + } + + public Report WithDataSets(DataSets dataSets) + { + DataSets = dataSets; + return this; + } + + public Report WithPageHeader(PageHeader pageHeader) + { + PageHeader = pageHeader; + return this; + } + + public Body WithBody() + { + Body = new Body(); + return Body; + } + + public Report WithPageFooter(PageFooter pageFooter) + { + PageFooter = pageFooter; + return this; + } } } \ No newline at end of file diff --git a/RdlCreator/ReportItemsBody.cs b/RdlCreator/ReportItemsBody.cs index c46b976c..a11b4f5a 100644 --- a/RdlCreator/ReportItemsBody.cs +++ b/RdlCreator/ReportItemsBody.cs @@ -5,8 +5,13 @@ namespace Majorsilence.Reporting.RdlCreator { public class ReportItemsBody { - [XmlElement(ElementName = "Table")] public Table Table { get; set; } + + public ReportItemsBody WithTable(Table table) + { + this.Table = table; + return this; + } } } \ No newline at end of file diff --git a/RdlCreator/Table.cs b/RdlCreator/Table.cs index 258c98a4..b86531a9 100644 --- a/RdlCreator/Table.cs +++ b/RdlCreator/Table.cs @@ -22,5 +22,41 @@ public class Table [XmlAttribute(AttributeName = "Name")] public string TableName { get; set; } + + public Table WithTableColumns(TableColumns tableColumns) + { + this.TableColumns = tableColumns; + return this; + } + + public Table WithHeader(Header header) + { + this.Header = header; + return this; + } + + public Table WithDetails(Details details) + { + this.Details = details; + return this; + } + + public Table WithDataSetName(string dataSetName) + { + this.DataSetName = dataSetName; + return this; + } + + public Table WithNoRows(string noRows) + { + this.NoRows = noRows; + return this; + } + + public Table WithTableName(string tableName) + { + this.TableName = tableName; + return this; + } } } \ No newline at end of file