بر این اساس قصد داریم رابطه یک به چند فوق را گروه بندی شده نمایش دهیم:
(البته این اعداد و اطلاعات، به صورت اتفاقی تولید شدهاند و الزامی ندارد که والد متولد 2002 هنوز والد شده باشد؛ یا اینکه فرزندی متولد 2003 داشته باشد!)
بنابراین صورت مساله ما به این ترتیب خواهد بود:
بر اساس اطلاعات دو جدول والدین و فرزندان فوق، اطلاعات نهایی را در جداول مجزایی بر اساس والدین و فرزندان آنها گروه بندی نمائید.
سورس کامل این مثال را در ادامه مشاهده میکنید:
using System; using PdfRpt.Core.Contracts; using PdfRpt.FluentInterface; namespace PdfReportSamples.MasterDetails { public class MasterDetailsPdfReport { public IPdfReportData CreatePdfReport() { return new PdfReport().DocumentPreferences(doc => { doc.RunDirection(PdfRunDirection.LeftToRight); doc.Orientation(PageOrientation.Portrait); doc.PageSize(PdfPageSize.A4); doc.DocumentMetadata(new DocumentMetadata { Author = "Vahid", Application = "PdfRpt", Keywords = "Test", Subject = "Test Rpt", Title = "Test" }); }) .DefaultFonts(fonts => { fonts.Path(Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\arial.ttf", Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf"); }) .PagesHeader(header => { header.CustomHeader(new MasterDetailsHeaders { PdfRptFont = header.PdfFont }); }) .PagesFooter(footer => { footer.DefaultFooter(DateTime.Now.ToString("MM/dd/yyyy")); }) .MainTableTemplate(t => t.BasicTemplate(BasicTemplate.SilverTemplate)) .MainTablePreferences(table => { table.ColumnsWidthsType(TableColumnWidthType.Relative); table.GroupsPreferences(new GroupsPreferences { GroupType = GroupType.HideGroupingColumns, RepeatHeaderRowPerGroup = true, ShowOneGroupPerPage = false, SpacingBeforeAllGroupsSummary = 5f, NewGroupAvailableSpacingThreshold = 170 }); }) .MainTableDataSource(dataSource => { dataSource.GenericDataReader( providerName: "System.Data.SQLite", connectionString: "Data Source=" + AppPath.ApplicationPath + "\\data\\blogs.sqlite", sql: @"select tblParents.BirthDate as ParentBirthDate, tblParents.Name as ParentName, tblParents.LastName as ParentLastName, tblKids.Name as KidName, tblKids.BirthDate as KidBirthDate from tblParents left outer join tblKids on tblKids.ParentId = tblParents.Id order by tblParents.Name, tblParents.LastName, tblKids.Name" ); }) .MainTableColumns(columns => { columns.AddColumn(column => { column.PropertyName("rowNo"); column.IsRowNumber(true); column.CellsHorizontalAlignment(HorizontalAlignment.Left); column.IsVisible(true); column.Order(0); column.Width(1); column.HeaderCell("#"); }); columns.AddColumn(column => { column.PropertyName("ParentBirthDate"); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.Order(1); column.Width(2); column.HeaderCell("ParentBirthDate"); column.Group(true, (val1, val2) => { var date1 = (DateTime)val1; var date2 = (DateTime)val2; return date1.Year == date2.Year && date1.Month == date2.Month && date1.Day == date2.Day; }); }); columns.AddColumn(column => { column.PropertyName("ParentName"); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.Order(2); column.Width(2); column.HeaderCell("ParentName"); column.Group(true, (val1, val2) => { return val1.ToString() == val2.ToString(); }); }); columns.AddColumn(column => { column.PropertyName("ParentLastName"); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.Order(3); column.Width(2); column.HeaderCell("ParentLastName"); column.Group(true, (val1, val2) => { return val1.ToString() == val2.ToString(); }); }); columns.AddColumn(column => { column.PropertyName("KidName"); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.Order(4); column.Width(2); column.HeaderCell("Child Name"); column.IsVisible(true); }); columns.AddColumn(column => { column.PropertyName("KidBirthDate"); column.CellsHorizontalAlignment(HorizontalAlignment.Center); column.Order(5); column.Width(2); column.HeaderCell("BirthDate"); column.IsVisible(true); }); }) .MainTableEvents(events => { events.DataSourceIsEmpty(message: "There is no data available to display."); }) .Export(e => e.ToExcel()) .Generate(data => data.AsPdfFile(AppPath.ApplicationPath + "\\Pdf\\RptMasterDetailsSample.pdf")); } } }
using System.Collections.Generic; using iTextSharp.text; using iTextSharp.text.pdf; using PdfRpt.ColumnsItemsTemplates; using PdfRpt.Core.Contracts; using PdfRpt.Core.Helper; namespace PdfReportSamples.MasterDetails { public class MasterDetailsHeaders : IPageHeader { public IPdfFont PdfRptFont { set; get; } public PdfPTable RenderingGroupHeader(Document pdfDoc, PdfWriter pdfWriter, IList<CellData> newGroupInfo, IList<SummaryCellData> summaryData) { var parentName = newGroupInfo.GetSafeStringValueOf("ParentName"); var parentLastName = newGroupInfo.GetSafeStringValueOf("ParentLastName"); var parentBirthDate = newGroupInfo.GetSafeStringValueOf("ParentBirthDate"); var table = new PdfPTable(relativeWidths: new[] { 1f, 5f }) { WidthPercentage = 100 }; table.AddSimpleRow( (cellData, cellProperties) => { cellData.Value = "Name:"; cellProperties.PdfFont = PdfRptFont; cellProperties.PdfFontStyle = DocumentFontStyle.Bold; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (cellData, cellProperties) => { cellData.Value = parentName; cellProperties.PdfFont = PdfRptFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }); table.AddSimpleRow( (cellData, cellProperties) => { cellData.Value = "Last Name:"; cellProperties.PdfFont = PdfRptFont; cellProperties.PdfFontStyle = DocumentFontStyle.Bold; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (cellData, cellProperties) => { cellData.Value = parentLastName; cellProperties.PdfFont = PdfRptFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }); table.AddSimpleRow( (cellData, cellProperties) => { cellData.Value = "Birth Date:"; cellProperties.PdfFont = PdfRptFont; cellProperties.PdfFontStyle = DocumentFontStyle.Bold; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (cellData, cellProperties) => { cellData.Value = parentBirthDate; cellProperties.PdfFont = PdfRptFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }); return table.AddBorderToTable(borderColor: BaseColor.LIGHT_GRAY, spacingBefore: 5f); } public PdfPTable RenderingReportHeader(Document pdfDoc, PdfWriter pdfWriter, IList<SummaryCellData> summaryData) { var table = new PdfPTable(numColumns: 1) { WidthPercentage = 100 }; table.AddSimpleRow( (cellData, cellProperties) => { cellData.CellTemplate = new ImageFilePathField(); cellData.Value = AppPath.ApplicationPath + "\\Images\\01.png"; cellProperties.HorizontalAlignment = HorizontalAlignment.Center; }); table.AddSimpleRow( (cellData, cellProperties) => { cellData.Value = "Family rpt"; cellProperties.PdfFont = PdfRptFont; cellProperties.PdfFontStyle = DocumentFontStyle.Bold; cellProperties.HorizontalAlignment = HorizontalAlignment.Center; }); return table.AddBorderToTable(); } } }
- منبع داده مورد استفاده در اینجا از نوع GenericDataReader است؛ جهت خواندن رکوردهای بانک اطلاعاتی SQLite ذکر شده در ابتدای بحث. (دو مثال دیگر هم به پوشه مثالهای سورسهای PdfReport اضافه شدهاند به نامهای Grouping و WrapGroupsInColumns که به همین موضوع گروه بندی میپردازند؛ البته با استفاده از StronglyTypedListها. ولی درکل مفاهیم و اصول آنها یکی است.)
select tblParents.BirthDate as ParentBirthDate, tblParents.Name as ParentName, tblParents.LastName as ParentLastName, tblKids.Name as KidName, tblKids.BirthDate as KidBirthDate from tblParents left outer join tblKids on tblKids.ParentId = tblParents.Id order by tblParents.Name, tblParents.LastName, tblKids.Name
الف) چون قرار است اطلاعات بر اساس مشخصات والدین و فرزندان آنها گروه بندی شود، نیاز است حتما order by و مرتب سازی رکوردها قید گردد.
ب) در PdfReport نمیتوانید در خواص معرفی شده جهت تعریف ستونها، از نامهای تکراری استفاده کنید. برای رفع این مشکل استفاده از Alias پیشنهاد میشود؛ مانند:
tblParents.Name as ParentName, tblKids.Name as KidName,
column.Group(true, (val1, val2) => { return val1.ToString() == val2.ToString(); });
- تنظیم دیگری را که در اینجا میتوان ذکر کرد، مورد ذیل است:
table.GroupsPreferences(new GroupsPreferences { GroupType = GroupType.HideGroupingColumns, RepeatHeaderRowPerGroup = true, ShowOneGroupPerPage = false, SpacingBeforeAllGroupsSummary = 5f, NewGroupAvailableSpacingThreshold = 170 });
- اگر به تصویر ابتدای مطلب دقت کرده باشید، علاوه بر هدر صفحه، هر گروه نیز یک هدر مجزا دارد. برای طراحی آن باید اینترفیس IPageHeader را پیاده سازی کرد که نمونهای از آنرا در کلاس MasterDetailsHeaders فوق مشاهده میکنید.
public PdfPTable RenderingGroupHeader(Document pdfDoc, PdfWriter pdfWriter, IList<CellData> newGroupInfo, IList<SummaryCellData> summaryData) { var parentName = newGroupInfo.GetSafeStringValueOf("ParentName"); var parentLastName = newGroupInfo.GetSafeStringValueOf("ParentLastName"); var parentBirthDate = newGroupInfo.GetSafeStringValueOf("ParentBirthDate"); var table = new PdfPTable(relativeWidths: new[] { 1f, 5f }) { WidthPercentage = 100 }; table.AddSimpleRow( (cellData, cellProperties) => { cellData.Value = "Name:"; cellProperties.PdfFont = PdfRptFont; cellProperties.PdfFontStyle = DocumentFontStyle.Bold; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; }, (cellData, cellProperties) => { cellData.Value = parentName; cellProperties.PdfFont = PdfRptFont; cellProperties.HorizontalAlignment = HorizontalAlignment.Left; });