65.9K
CodeProject 正在变化。 阅读更多。
Home

隆重推出 PdfRport

starIconstarIconstarIconstarIconstarIcon

5.00/5 (28投票s)

2013 年 1 月 18 日

CPOL

9分钟阅读

viewsIcon

102185

downloadIcon

3504

PdfReport 是一个基于 iTextSharp 和 EPPlus 库构建的代码优先报告引擎。

引言

PdfReport 是一个代码优先报告引擎,它构建在 iTextSharpEPPlus 库之上。它兼容 .NET 3.5+ 的 Web 和 Windows 应用程序。PdfReport 支持从数据表到内存中强类型列表的广泛数据源,而无需数据库。它为您节省了搜索和学习 iTextSharp 和 EPPlus 库的大量技巧和窍门的时间。它设计用于兼容 RTL 语言。

如何开始使用 PdfRport 

创建您的第一个 PdfReport

  1. 在 Visual Studio 中创建一个新的类库项目。我们将将其用作 Windows 和 Web 应用程序的基础报表类容器。
  2. 然后添加对以下程序集的引用:PdfReport、iTextSharp 和 EPPlus。您可以从 http://pdfreport.codeplex.com/releases/ 下载它们

    或者直接使用 NuGet PowerShell 控制台自动添加这些引用

    PM> Install-Package PdfReport

    https://nuget.net.cn/packages/PdfReport/

  3. 将以下类添加到类库项目中
  4. using System.Web;
    using System.Windows.Forms;
     
    namespace PdfReportSamples
    {
        public static class AppPath
        {
            public static string ApplicationPath
            {
                get
                {
                    if (isInWeb)
                        return HttpRuntime.AppDomainAppPath;
     
                    return Application.StartupPath;
                }
            }
     
            private static bool isInWeb
            {
                get
                {
                    return HttpContext.Current != null;
                }
            }
        }
    }

我们将使用这个类来指定生成的 PDF 文件的位置。它还需要以下引用

  • System.Windows.Forms.dll
  • System.Web.dll
using System;
 
namespace PdfReportSamples.IList
{
    public class User
    {
        public int Id { set; get; }
        public string Name { set; get; }
        public string LastName { set; get; }
        public long Balance { set; get; }
        public DateTime RegisterDate { set; get; }
    }
}
 
//"User" class will be used for creating an in-memory generic list data source.
//And now add the main report class:

using System;
using System.Collections.Generic;
using PdfReportSamples.Models;
using PdfRpt.Core.Contracts;
using PdfRpt.FluentInterface;
 
namespace PdfReportSamples.IList
{
    public class IListPdfReport
    {
        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 = "IList Rpt.", 
                  Subject = "Test Rpt", Title = "Test" });
            })
            .DefaultFonts(fonts =>
            {
                fonts.Path(Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\arial.ttf",
                                  Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\verdana.ttf");
            })
            .PagesFooter(footer =>
            {
                footer.DefaultFooter(DateTime.Now.ToString("MM/dd/yyyy"));
            })
            .PagesHeader(header =>
            {
                header.DefaultHeader(defaultHeader =>
                {
                    defaultHeader.RunDirection(PdfRunDirection.LeftToRight);
                    defaultHeader.ImagePath(AppPath.ApplicationPath + "\\Images\\01.png");
                    defaultHeader.Message("Our new rpt.");
                });
            })
            .MainTableTemplate(template =>
            {
                template.BasicTemplate(BasicTemplate.ClassicTemplate);
            })
            .MainTablePreferences(table =>
            {
                table.ColumnsWidthsType(TableColumnWidthType.Relative);
                table.NumberOfDataRowsPerPage(5);
            })
            .MainTableDataSource(dataSource =>
            {
                var listOfRows = new List<User>();
                for (int i = 0; i < 200; i++)
                {
                    listOfRows.Add(new User { Id = i, LastName = "LastName " + i, 
                       Name = "Name " + i, Balance = i + 1000 });
                }
                dataSource.StronglyTypedList(listOfRows);
            })
            .MainTableSummarySettings(summarySettings =>
            {
                summarySettings.OverallSummarySettings("Summary");
                summarySettings.PreviousPageSummarySettings("Previous Page Summary");
                summarySettings.PageSummarySettings("Page Summary");
            })
            .MainTableColumns(columns =>
            {
                columns.AddColumn(column =>
                {
                    column.PropertyName("rowNo");
                    column.IsRowNumber(true);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(0);
                    column.Width(1);
                    column.HeaderCell("#");
                });
 
                columns.AddColumn(column =>
                {
                    column.PropertyName<User>(x => x.Id);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(1);
                    column.Width(2);
                    column.HeaderCell("Id");
                });
 
                columns.AddColumn(column =>
                {
                    column.PropertyName<User>(x => x.Name);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(2);
                    column.Width(3);
                    column.HeaderCell("Name");
                });
 
                columns.AddColumn(column =>
                {
                    column.PropertyName<User>(x => x.LastName);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(3);
                    column.Width(3);
                    column.HeaderCell("Last Name");
                });
 
                columns.AddColumn(column =>
                {
                    column.PropertyName<User>(x => x.Balance);
                    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
                    column.IsVisible(true);
                    column.Order(4);
                    column.Width(2);
                    column.HeaderCell("Balance");
                    column.ColumnItemsTemplate(template =>
                    {
                        template.TextBlock();
                        template.DisplayFormatFormula(obj => obj == null ? string.Empty : string.Format("{0:n0}", obj));
                    });
                    column.AggregateFunction(aggregateFunction =>
                    {
                        aggregateFunction.NumericAggregateFunction(AggregateFunction.Sum);
                        aggregateFunction.DisplayFormatFormula(obj => obj == null ? string.Empty : string.Format("{0:n0}", obj));
                    });
                });
 
                })
            .MainTableEvents(events =>
            {
                events.DataSourceIsEmpty(message: "There is no data available to display.");
            })
            .Export(export =>
            {
                export.ToExcel();
                export.ToCsv();
                export.ToXml();
            })
            .Generate(data => data.AsPdfFile(AppPath.ApplicationPath + "\\Pdf\\RptIListSample.pdf"));
        }
    }
}

您可以在此处找到它的最新版本 here

要使用这个类并创建一个新的 PDF 报表文件,我们可以这样做

var rpt = new IListPdfReport().CreatePdfReport();
// rpt.FileName
  • 在 DocumentPreferences 方法中,我们可以指定报表的方向(PdfRunDirection:RTL 或 LTR)、页面大小(PdfPageSize)、方向(PageOrientation)等。
  • 然后,有必要在 DefaultFonts 方法中确定默认报表字体文件。第一个字体将是主字体,第二个字体将用作回退字体。
  • PdfReport 提供了内置的页脚和页眉示例。通过实现 IPageFooterIPageHeader 接口,可以自定义这些元素。我们将在其他操作指南中讨论这一点。
  • 通过使用 MainTableTemplate,我们可以定义主网格的模板。PdfReport 库中提供了一些预定义模板。也可以通过实现 ITableTemplate 接口来创建新模板。
  • MainTablePreferences 方法将用于指定主报表网格的设置,例如每页应有多少行(如果未指定,行数将根据页面大小自动计算)。
  • ColumnsWidthsType 方法接受四种不同的值

    1. Relative:每列的相对宽度等于 1。示例:相对值 = 2, 1, 1。这意味着您想将表的宽度分成四部分(2 + 1 + 1):第一列两部分,第二列和第三列各一部分。
    2. Absolute:以用户空间单位表示的绝对宽度。
    3. EquallySized:等宽列。在这种情况下,指定的所有宽度都将被忽略。
    4. FitToContent:尝试自动调整列的大小。在这种情况下,指定的所有宽度都将被忽略。
  • MainTableDataSource 方法设置主网格的数据源。例如,在上面的示例中,StronglyTypedList 方法将处理用户列表。PdfReport 库中还有其他内置的数据源方法。例如,如果您想使用原始 SQL 并直接处理数据库,请尝试以下方法
//SQL server data source
public void SqlDataReader(string connectionString, string sql, params object[] parametersValues)
 
//.mdb or .accdb files
public void AccessDataReader(string filePath, string password, string sql, params object[] parametersValues)
 
//Odbc data source
public void OdbcDataReader(string connectionString, string sql, params object[] parametersValues)
 
// A generic data reader data source
public void GenericDataReader(string providerName, string connectionString, string sql, params object[] parametersValues)

可以在上述所有方法中编写参数化查询。这些参数应以 @ 符号开头。以下是一个快速示例,演示了如何在 PdfReport 中使用 SQLite 数据库

dataSource.GenericDataReader(
    providerName: "System.Data.SQLite",
    connectionString: "Data Source=" + AppPath.ApplicationPath + "\\data\\blogs.sqlite",
    sql: @"SELECT [url], [name], [NumberOfPosts], [AddDate]
               FROM [tblBlogs]
               WHERE [NumberOfPosts]>=@p1",
    parametersValues: new object[] { 10 }
);

添加对  System.Data.SQLite 程序集的引用,然后使用上述通用数据读取器。MySQL 等数据库也适用相同的规则。

  • MainTableSummarySettings 方法确定自动生成的摘要/总计标签及其显示位置。它是可选的。
  • 通过使用可选的 MainTableColumns 方法,可以确定报表网格的精确列。每列都应存在于数据源中。还可以定义计算字段。这将在以后的操作指南中讨论。在 MainTableColumns 方法中,您可以指定列的相关属性、宽度、可见性、顺序等。在此处使用 ColumnItemsTemplate 方法,我们可以确定当前字段的类型以及如何显示它。如果它应显示为文本,请使用 template.TextBlock() 方法(这是默认方法)。还有其他内置单元格模板,如图像、超链接等。也可以通过实现 IColumnItemsTemplate 接口来使用自定义列模板。
    如果您想在渲染之前格式化单元格的值,请使用 template.DisplayFormatFormula 方法。这是一个回调方法,它为您提供单元格的实际值,然后您可以对其进行格式化并返回最终结果以显示在报表中。
  • 通过使用 column.AggregateFunction 方法,我们可以确定当前列的相关聚合方法。PdfReport 库提供了一些预定义的数字聚合函数。也可以通过实现 IAggregateFunc 接口来编写自定义函数。
  • MainTableEvents 方法提供了对主网格内部事件的访问。例如,如果数据源为空,将引发 DataSourceIsEmpty 事件。
  • 还可以将主表的*数据*导出为 Excel、CSV、XML 等文件。所有这些导出的文件将自动嵌入到最终的 PDF 文件中。

如何创建自动生成/动态列

在 PdfReport 中,指定 MainTableColumns 方法及其所有定义是任意的。只需省略这部分,最终的报表将根据提供的数据源中的可用列动态创建。此功能为我们提供了极大的灵活性,但经过一段时间后,我们需要自定义这类报表:如何格式化 DateTime、如何添加数字字段的总数等。

以下是一些关于自定义自动生成列的提示

a) 使用别名指定标题单元格

如果您使用的是 SQL 数据源,如 GenericDataReader,要自定义标题单元格,只需在最终 SQL 中定义列别名即可。

SELECT [NumberOfPosts] as 'Number of posts'
FROM [tblBlogs]
WHERE [NumberOfPosts]>=@p1

b) 根据列的数据类型指定渲染约定

通过使用 MainTableAdHocColumnsConventions 方法,可以修改动态列的渲染条件。在 MainTableAdHocColumnsConventions 方法中,我们可以将自动生成的行*列*包含在最终报表中。

adHocColumns.ShowRowNumberColumn(true);
adHocColumns.RowNumberColumnCaption("#");
Or it's possible to format a cell's value based on its type:
adHocColumns.AddTypeDisplayFormatFormula(
                     typeof(DateTime),
                     data => { return PersianDate.ToPersianDateTime((DateTime)data); }
                 );

在这里,我们正在修改所有 DateTime 列的渲染值。

adHocColumns.AddTypeAggregateFunction(
                     typeof(Int64),
                     new AggregateProvider(AggregateFunction.Sum)
                     {
                         DisplayFormatFormula = obj => obj == null ? string.Empty : string.Format("{0:n0}", obj)
                     });

或者我们可以确定给定数据类型的特定 AggregateFunction

c) 使用数据注释定义列属性

如果您使用的是通用列表数据源,则可以通过用数据注释替换 MainTableColumns 方法及其所有定义来省略它们。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using PdfReportSamples.Models;
using PdfRpt.Aggregates.Numbers;
using PdfRpt.ColumnsItemsTemplates;
using PdfRpt.Core.Contracts;
using PdfRpt.Core.Helper;
using PdfRpt.DataAnnotations;
 
namespace PdfReportSamples.DataAnnotations
{
    public class Person
    {
        [IsVisible(false)]
        public int Id { get; set; }
 
        [DisplayName("User name")]
        //Note: If you don't specify the ColumnItemsTemplate, a new TextBlockField() will be used automatically.
        [ColumnItemsTemplate(typeof(TextBlockField))]
        public string Name { get; set; }
 
        [DisplayName("Job title")]
        public JobTitle JobTitle { set; get; }
 
        [DisplayName("Date of birth")]
        [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
        public DateTime DateOfBirth { get; set; }
 
        [DisplayName("Date of death")]
        [DisplayFormat(NullDisplayText = "-", DataFormatString = "{0:MM/dd/yyyy}")]
        public DateTime? DateOfDeath { get; set; }
 
        [DisplayFormat(DataFormatString = "{0:n0}")]
        [CustomAggregateFunction(typeof(Sum))]
        public int Salary { get; set; }
 
        [IsCalculatedField(true)]
        [DisplayName("Calculated Field")]
        [DisplayFormat(DataFormatString = "{0:n0}")]
        [AggregateFunction(AggregateFunction.Sum)]
        public string CalculatedField { get; set; }
 
        [CalculatedFieldFormula("CalculatedField")]
        public static Func<IList<CellData>, object> CalculatedFieldFormula =
                                                    list =>
                                                    {
                                                        if (list == null) return string.Empty;
                                                        var salary = (int)list.GetValueOf<Person>(x => x.Salary);
                                                        return salary * 0.8;
                                                    };//Note: It's a static field, not a property.
    }
}
  • 如果您不想在最终报表中显示某个属性,请使用 [IsVisible(false)] 属性。
  • DisplayName 属性将用于定义报表的标题单元格。
  • 指定 ColumnItemsTemplate 属性是可选的,如果未定义,则会自动使用 TextBlockField

其他预定义列单元格模板定义在 PdfRpt.ColumnsItemsTemplates 命名空间中。

  • 要格式化显示的日期或数字,请使用 DisplayFormat 属性。
  • 要添加总计行,请指定 CustomAggregateFunction 属性。PdfRpt.Aggregates.Numbers 命名空间中提供了一些内置的聚合函数。
  • 要定义计算字段/列,请指定 [IsCalculatedField(true)] 属性。然后添加一个新*静态*字段(不是属性)来定义相关的公式。这个新字段应该用 CalculatedFieldFormula 属性进行修饰,以确定计算字段的属性名称。

以下是一些关于自动生成列的完整示例

如何定义计算列

有时我们需要创建一个新的列,该列不在数据源中,而是基于其他列的值。PdfReport 中有两种类型的计算列

a) 行号列

只需设置 column.IsRowNumber(true);。然后,一个未包含在数据源中的新行号列将在最终报表中可用。

b) 要定义自定义计算列,我们需要通过设置 column.CalculatedField 方法来指定其计算公式

columns.AddColumn(column =>
{
 column.PropertyName("CF1");
 column.CalculatedField(
     list =>
     {
         if (list == null) return string.Empty;
         var name = list.GetSafeStringValueOf<User>(x => x.Name);
         var lastName = list.GetSafeStringValueOf<User>(x => x.LastName);
         return name + " - " + lastName;
     });
 column.HeaderCell("Full name");
 column.Width(3);
 column.CellsHorizontalAlignment(HorizontalAlignment.Center);
 column.IsVisible(true);
 column.Order(4);
});

column.CalculatedField 方法的参数为我们提供了当前行值的列表。

public void CalculatedField(bool isCalculatedField, Func<IList<CellData>, object> calculatedFieldFormula)

现在我们可以根据其他列值构建当前单元格的值。PdfRpt.Core.Helper 命名空间中定义了一些辅助方法,例如 GetSafeStringValueOf,以帮助更轻松地处理 IList<CellData> 数据。定义 PropertyName 是强制性的,但在本例中,它可以是任意文本。

以下是演示如何定义计算列的完整示例:CalculatedFields

如何在 PdfReport 中显示*图像*

通常,报表中*图像*有两种类型

a) 从文件系统加载的*图像*

要显示此类*图像*,我们需要将默认的 ColumnItemsTemplate(即 TextBlock)更改为 ImageFilePath

columns.AddColumn(column =>
{
    column.PropertyName<ImageRecord>(x => x.ImagePath);
    column.CellsHorizontalAlignment(HorizontalAlignment.Center);
    column.IsVisible(true);
    column.Order(2);
    column.Width(3);
    column.HeaderCell("Image");
    column.ColumnItemsTemplate(t => t.ImageFilePath(defaultImageFilePath: string.Empty, fitImages: false));
});

在这里,defaultImageFilePath 是在*图像*丢失时默认的*图像*路径。

b) 存储在数据库中的*图像*

显示存储在数据库中的二进制*图像*与 (a) 类似。我们只需使用合适的 ColumnItemsTemplate,即 ByteArrayImage 模板。

columns.AddColumn(column =>
{
 column.PropertyName("thumbnail");
 column.CellsHorizontalAlignment(HorizontalAlignment.Center);
 column.IsVisible(true);
 column.Order(5);
 column.HeaderCell("Image");
 column.ColumnItemsTemplate(t => t.ByteArrayImage(defaultImageFilePath: string.Empty, fitImages: false));
});

您可以在此处找到 (a) 和 (b) 的完整示例

PdfReport 中的条件格式设置

假设我们想显示一年中人员列表。在此报表中,月份为 7 的每个月单元格都应以不同的颜色显示。为了实现此目标,我们可以使用 template.ConditionalFormatFormula 方法。

columns.AddColumn(column =>
{
 column.PropertyName("Month");
 column.CellsHorizontalAlignment(HorizontalAlignment.Center);
 column.IsVisible(true);
 column.Order(2);
 column.Width(2);
 column.HeaderCell("Month");
 column.ColumnItemsTemplate(template =>
 {
     template.TextBlock();
     template.ConditionalFormatFormula(list =>
     {
         var cellValue = int.Parse(list.GetSafeStringValueOf("Month", nullValue: "0"));
         if (cellValue == 7)
         {
             return new CellBasicProperties
             {
                 PdfFontStyle = DocumentFontStyle.Bold | DocumentFontStyle.Underline,
                 FontColor = new BaseColor(System.Drawing.Color.Brown),
                 BackgroundColor = new BaseColor(System.Drawing.Color.Yellow)
             };
         }
         return new CellBasicProperties { PdfFontStyle = DocumentFontStyle.Normal };
     });
 });
});

template.ConditionalFormatFormula 是一个回调方法,它为我们提供当前行的数据列表。现在,根据月份(或其他属性)的值,我们可以返回具有不同字体颜色、样式等的“new CellBasicProperties”。您可以在此处找到相关示例:here

如何创建自定义主表*模板*

PdfReport 库中提供了一些内置的报表*模板*,例如 BasicTemplate.RainyDayTemplateBasicTemplate.SilverTemplate 等。也可以通过实现 ITableTemplate 接口来创建新的主表*模板*。例如

using System.Collections.Generic;
using System.Drawing;
using iTextSharp.text;
using PdfRpt.Core.Contracts;
 
namespace PdfReportSamples.HexDump
{
    public class GrayTemplate : ITableTemplate
    {
        public HorizontalAlignment HeaderHorizontalAlignment
        {
            get { return HorizontalAlignment.Center; }
        }
 
        public BaseColor AlternatingRowBackgroundColor
        {
            get { return new BaseColor(Color.WhiteSmoke); }
        }
 
        public BaseColor CellBorderColor
        {
            get { return new BaseColor(Color.LightGray); }
        }
 
        public IList<BaseColor> HeaderBackgroundColor
        {
            get { return new List<BaseColor> { new BaseColor(
              ColorTranslator.FromHtml("#990000")), 
              new BaseColor(ColorTranslator.FromHtml("#e80000")) }; }
        }
 
        public BaseColor RowBackgroundColor
        {
            get { return null; }
        }
 
        public IList<BaseColor> PreviousPageSummaryRowBackgroundColor
        {
            get { return new List<BaseColor> { new BaseColor(Color.LightSkyBlue) }; }
        }
 
        public IList<BaseColor> SummaryRowBackgroundColor
        {
            get { return new List<BaseColor> { new BaseColor(Color.LightSteelBlue) }; }
        }
 
        public IList<BaseColor> PageSummaryRowBackgroundColor
        {
            get { return new List<BaseColor> { new BaseColor(Color.Yellow) }; }
        }
 
        public BaseColor AlternatingRowFontColor
        {
            get { return new BaseColor(ColorTranslator.FromHtml("#333333")); }
        }
 
        public BaseColor HeaderFontColor
        {
            get { return new BaseColor(Color.White); }
        }
 
        public BaseColor RowFontColor
        {
            get { return new BaseColor(ColorTranslator.FromHtml("#333333")); }
        }
 
        public BaseColor PreviousPageSummaryRowFontColor
        {
            get { return new BaseColor(Color.Black); }
        }
 
        public BaseColor SummaryRowFontColor
        {
            get { return new BaseColor(Color.Black); }
        }
 
        public BaseColor PageSummaryRowFontColor
        {
            get { return new BaseColor(Color.Black); }
        }
 
        public bool ShowGridLines
        {
            get { return true; }
        }
    }
}

要使用这个新*模板*,我们可以这样做

.MainTableTemplate(template =>
{
      template.CustomTemplate(new GrayTemplate());
})

一些技巧和窍门

  • iTextSharp 库中的颜色由 BaseColor 类定义。如果您想将 System.Drawing 的颜色转换为 BaseColor,只需将其传递给 BaseColor 的构造函数即可。
  • var blackColor = new BaseColor(Color.Black);
  • ColorTranslator.FromHtml 等 .NET 类中有一些有用的辅助方法,用于转换和使用 HTML 颜色。
  • 如果您想在此处定义透明颜色,只需返回 null 即可。
  • ITableTemplate 接口中,一些颜色被定义为列表。这些属性可以接受一种或最多两种颜色。如果指定了两种颜色,则报表中将显示这些颜色的自动渐变。

如何使用 HTML 创建自定义单元格*模板*

假设我们有一个用户列表,包含他们的姓名和照片。我们想在*一个*单元格中显示每个用户的姓名和照片,而不是*两个*单独的单元格。PdfReport 的内置单元格*模板*仅适用于在*一个*单元格中显示*一个*对象。要定义自定义单元格*模板*,我们需要实现 IColumnItemsTemplate 接口或使用快捷方式。
columns.AddColumn(column =>
{
 column.PropertyName("User");
 column.CellsHorizontalAlignment(HorizontalAlignment.Center);
 column.IsVisible(true);
 column.Order(1);
 column.Width(3);
 column.HeaderCell("User");
 column.CalculatedField(list =>
     {
         var user = list.GetSafeStringValueOf("User");
         var photo = new Uri(list.GetSafeStringValueOf("Photo"));
         var image = string.Format("<img src='{0}' />", photo);
         return
                @"<table style='width: 100%; font-size:9pt;'>
                            <tr>
                                <td>" + user + @"</td>
                            </tr>
                            <tr>
                                <td>" + image + @"</td>
                            </tr>
                   </table>
                 ";
     });
 column.ColumnItemsTemplate(template =>
     {
         template.Html(); // Using iTextSharp's limited HTML to PDF capabilities (HTMLWorker class).
     });
});

这里在后台使用了 iTextSharp 的 HTMLWorker 类。通过使用 CalculatedField,我们可以注入单元格的新值,然后由所选的 ColumnItemsTemplate 进行处理。注意:iTextSharp 的 HTMLWorker 类的 HTML 到 PDF 功能非常有限,不要对此抱太大期望。您可以在此处找到此示例:here

更多指南和示例

PdfReport 提供了 40 多个示例。请从 CodePlex 下载其源代码,并查看其示例文件夹。
© . All rights reserved.