عنوان:

‫تولید پویای ستون‌ها در PdfReport


نویسنده: وحید نصیری
تاریخ: ۱۳۹۱/۰۷/۱۵ ۰:۳۴
آدرس: www.dntips.ir
همانطور که در نکته انتهای قسمت قبل «کار با بانک‌های اطلاعاتی مختلف در PdfReport» عنوان شد، ذکر قسمت MainTableColumns و تمام تعاریف مرتبط با آن در PdfReports اختیاری است. برای تهیه یک گزارش توسط PdfReport فقط کافی است تا منبع داده را جهت تولید ستون‌های گزارش مشخص کنید.
این مورد انعطاف پذیری زیادی را به همراه خواهد داشت؛ اما ... پس از مدتی این سؤالات مطرح می‌شوند: آیا می‌شود در این ستون‌های خودکار، فیلدهای DateTime، با تاریخ شمسی نمایش داده شوند؟ آیا امکانپذیر است که ستونهای عددی، جمع پایین صفحه داشته باشند؟ و مواردی از این دست که در مورد نحوه مدیریت این نوع ستون‌های خودکار در ادامه بحث خواهد شد.

ابتدا سورس کامل مثال جاری را در ادامه ملاحظه خواهید کرد. تقریبا همان مثال قسمت قبل است که تعاریف ستون‌های آن حذف شده است:
using System;
using PdfRpt;
using PdfRpt.Core.Contracts;
using PdfRpt.Core.Helper;
using PdfRpt.FluentInterface;

namespace PdfReportSamples.AdHocColumns
{
    public class AdHocColumnsPdfReport
    {
        public IPdfReportData CreatePdfReport()
        {
            return new PdfReport().DocumentPreferences(doc =>
            {
                doc.RunDirection(PdfRunDirection.RightToLeft);
                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(AppPath.ApplicationPath + "\\fonts\\irsans.ttf",
                            Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf");
             })
             .PagesFooter(footer =>
             {
                 footer.DefaultFooter(printDate: DateTime.Now.ToString("MM/dd/yyyy"));
             })
             .PagesHeader(header =>
             {
                 header.DefaultHeader(defaultHeader =>
                 {
                     defaultHeader.ImagePath(AppPath.ApplicationPath + "\\Images\\01.png");
                     defaultHeader.Message("گزارش جدید ما");
                 });
             })
             .MainTableTemplate(template =>
             {
                 template.BasicTemplate(BasicTemplate.SilverTemplate);
             })
             .MainTablePreferences(table =>
             {
                 table.ColumnsWidthsType(TableColumnWidthType.Relative);
             })
             .MainTableDataSource(dataSource =>
             {
                 dataSource.GenericDataReader(
                    providerName: "System.Data.SQLite",
                    connectionString: "Data Source=" + AppPath.ApplicationPath + "\\data\\blogs.sqlite",
                    sql: @"SELECT [url] as 'آدرس', [name] as 'نام', [NumberOfPosts] as 'تعداد مطالب', [AddDate] as 'تاریخ ارسال'
                           FROM [tblBlogs]
                           WHERE [NumberOfPosts]>=@p1",
                    parametersValues: new object[] { 10 }
                );
             })
             .MainTableSummarySettings(summary =>
             {
                 summary.OverallSummarySettings("جمع کل");
                 summary.PreviousPageSummarySettings("نقل از صفحه قبل");
                 summary.PageSummarySettings("جمع صفحه");
             })
             .MainTableAdHocColumnsConventions(adHocColumns =>
             {
                 //We want sum of the int columns
                 adHocColumns.AddTypeAggregateFunction(
                     typeof(Int64),
                     new AggregateProvider(AggregateFunction.Sum)
                     {
                         DisplayFormatFormula = obj => obj == null ? string.Empty : string.Format("{0:n0}", obj)
                     });

                 //We want to dispaly all of the dateTimes as ShamsiDateTime
                 adHocColumns.AddTypeDisplayFormatFormula(
                     typeof(DateTime),
                     data => { return PersianDate.ToPersianDateTime((DateTime)data); }
                 );
                 adHocColumns.ShowRowNumberColumn(true);
                 adHocColumns.RowNumberColumnCaption("ردیف");
             })
             .MainTableEvents(events =>
             {
                 events.DataSourceIsEmpty(message: "There is no data available to display.");
             })
             .Export(export =>
             {
                 export.ToExcel();
                 export.ToXml();
             })
             .Generate(data => data.AsPdfFile(AppPath.ApplicationPath + "\\Pdf\\AdHocColumnsSampleRpt.pdf"));
        }
    }
}

توضیحات:

- با توجه به اینکه تعاریف ستون‌ها را حذف کرده‌ایم و به این ترتیب ستون‌ها به صورت خودکار بر اساس فیلدهای معرفی شده در منبع داده تشکیل می‌شوند، نیاز است سر ستون‌ها را بتوانیم فارسی نمایش دهیم. به همین جهت اینبار کوئری SQL ما با استفاده از aliasها، نامی فارسی را جهت فیلدها تدارک دیده است:
SELECT [url] as 'آدرس', [name] as 'نام', [NumberOfPosts] as 'تعداد مطالب', [AddDate] as 'تاریخ ارسال'
FROM [tblBlogs]
WHERE [NumberOfPosts]>=@p1
- در مرحله بعد توسط متد MainTableAdHocColumnsConventions، یک سری روال را جهت پردازش و نمایش این ستون‌های پویا مشخص می‌کنیم. برای مثال علاقمندیم در این نوع گزارشات هم ستون خودکار ردیف ظاهر شود:
adHocColumns.ShowRowNumberColumn(true);
adHocColumns.RowNumberColumnCaption("ردیف");
همچنین هر ستونی که نوع داده‌اش DateTime بود، از طریق فرمولی که مشخص می‌کنیم، به صورت شمسی نمایش داده شود:
adHocColumns.AddTypeDisplayFormatFormula(
                     typeof(DateTime),
                     data => { return PersianDate.ToPersianDateTime((DateTime)data); }
                 );
به علاوه می‌خواهیم تمام ستون‌هایی از نوع Int64، دارای جمع پایین صفحه هم باشند:
adHocColumns.AddTypeAggregateFunction(
                     typeof(Int64),
                     new AggregateProvider(AggregateFunction.Sum)
                     {
                         DisplayFormatFormula = obj => obj == null ? string.Empty : string.Format("{0:n0}", obj)
                     });
نوع int در بانک اطلاعاتی SQLite معادل نوع Int64 در دات نت است.

نظرات

  • Petek در ۱۳۹۱/۰۷/۱۵ ۲۱:۱۸
    با سلام
    مهندس اگه یکمی دیگه ادامه بدید دیگه خود من از استفاده از این گزارش سازها مثل StimulReport و ... بی خیال می‌شم و مثل همیشه کارهاتون عالیه . با تشکر
  • مهمان در ۱۳۹۱/۰۷/۲۹ ۰:۲۲
    سلام آقای نصیری ، با تشکر از این pdfReport بسیار عالی ، میخواستم یک راهنمایی در باره چگونگی استفاده از یک بانک اطلاعاتی sqlServer در این این سیستم گزارش گیری بفرمایید 
    با تشکر و سپاس فراوان .
    • وحید نصیری در ۱۳۹۱/۰۷/۲۹ ۰:۲۹
      مراجعه کنید به مطلب «کار با بانک‌های اطلاعاتی مختلف در PdfReport»
      تمام مباحث و مفاهیم آن یکی است. فقط قسمت منبع داده آن نیاز است تغییر کند:
       .MainTableDataSource(dataSource =>
                  {
                      dataSource.SqlDataReader(...


  • مهمان در ۱۳۹۱/۰۷/۲۹ ۱۶:۴۶
    سلام آقای نصیری 
    من تنطیمات اتصال بانک اطلاعاتی را انجام داده ام . اما باز با مشکل مواجه هستم .
    کد‌های خودم رو خدمت شما ارسال میکنم . منو راهنمایی بفرمایید.
    با تشکر

    ..MainTableDataSource(dataSource =>
                 {
                     dataSource.SqlDataReader(
                        providerName: "System.Data.SqlClient",
                        connectionString: "Data Source=.\SQLEXPRESS;Initial Catalog=EFDB;Integrated Security=True",
                        sql: @"SELECT [id] as 'شماره', [Title] as 'نام', [Content] as 'تعداد مطالب', [Date] as 'تاریخ ارسال'
                               FROM [posts]
                               WHERE [NumberOfPosts]>=@p1",
                        parametersValues: new object[] { 10 }
                    );
                 })
    • وحید نصیری در ۱۳۹۱/۰۷/۲۹ ۱۶:۵۲
      - لطفا جهت پرسش و پاسخ ویژه این پروژه، از قسمت مرتبط با آن در سایت استفاده کنید: (^)
      - امضای متد ویژه SqlDataReader به صورت زیر است:
      public void SqlDataReader(string connectionString, string sql, params object[] parametersValues)
      همانطور که مشاهده می‌کنید نیازی به ذکر providerName ندارد.
      - در دفعات بعد (چه در این سایت یا هر جای دیگری)، قسمت «با مشکل مواجه هستم» را بیشتر توضیح دهید. چون در این حالت کلی، اشخاص باید حدس بزنند که مشکل یاد شده چه چیزی بوده.
  • مهمان در ۱۳۹۱/۱۰/۲۲ ۱۸:۳۵
    آقای نصیری با سلام.
    آیا امکان دارد برخی از ستون‌ها را استاتیک و برخی دیگر را adhoc تعریف کنیم البته به غیر از rowNumber ؟
    با تشکر.
    • وحید نصیری در ۱۳۹۱/۱۰/۲۲ ۱۹:۳۹
      سلام؛ ستون‌های استاتیک را هم در دیتاسورس قرار بدید و در حالت adhoc استفاده کنید.
      • مهمان در ۱۳۹۱/۱۰/۲۲ ۱۹:۵۳
        سلام .
        منبع داده من Strongly type می‌باشد . چگونه می‌توانم برای آنها alias name بگذارم. با تشکر.
        • وحید نصیری در ۱۳۹۱/۱۰/۲۲ ۲۰:۴۳
          در این حالت می‌تونید از data annotations استفاده کنید. به صورت خودکار اعمال خواهند شد.
          • مهمان در ۱۳۹۱/۱۰/۲۲ ۲۳:۲۲
            سپاس مهندس. عالی .