目 录:基于NPOI的报表引擎——ExcelReport
上一篇:使用ExcelReport导出Excel
下一篇:扩展元素格式化器
针对上一篇随笔收到的反馈,在展开对ExcelReport源码解析之前,我认为把编写该组件时的想法分享给大家是有必要的。
编写该组件时,思考如下:
为什么要将样式、格式与数据分离呢?恩,你不妨想一想在生成报表时,那些是变的而那些又是不变的。我的结论是:变的是数据。
有了这个想法,很自然的想到用模板去承载不变的部分(常量内容的样式、格式、数据及变量内容的样式、格式),在程序中控制变的部分(变量内容的数据)。
这里以上一篇中的例子标识:
变量内容已使用粉红色边框标出,其余为常量内容。好了,相信“内容的数据”大家都知道那个是那个的。下面截图,内容的样式和格式。
现在我们回到上篇中使用的模板,相信你应该知道它承载那些东西了。
啰嗦了这么多,总结一下样式、格式与数据分离的好处:它让我们编写程序时关注更少(只需关心“变量内容的数据”)。
为什么要抽象一个“元素格式化器”的概念呢?我们看数据源,我们有可能要将某个类型的数据填充到某个单元格、也可能将一个集合填充到多行、有可能将一张图片填充到某个位置、也有可能就将某个字符串合并到某个单元格的内容中......如此种种。那么它们有什么共同点呢?它们都是填充“变量内容的数据”到模板的。
有了上面的背景,这张UML想必不难理解了。
当然,如果你还是觉得复杂, 没关系。我会先介绍一下这里面几个重点关系。
这是一个静态类,非常简单。只有两个静态方法:ExportToLocal()、ExportToWeb()分别将生成的文件导出到本地和Web。这多半是废话了,下面是重点:
这便引出了SheetFormatterContainer类,SheetFormatterContainer类是何许也?
说到这,顺便说下:ElementFormatter类和SheetFormatterContext类。
回到Export:
public static byte[] ExportToBuffer(string templateFile, params SheetFormatterContainer[] containers)
{
var workbook = LoadTemplateWorkbook(templateFile);
foreach (var container in containers)
{
var sheet = workbook.GetSheet(container.SheetName);
var context = new SheetFormatterContext(sheet, container.Formatters);
context.Format();
}
return workbook.SaveToBuffer();
}
如上代码,在执行导出的过程中,将每一个SheetFormatterContainer对象转换成了SheetFormatterContext对象。然后SheetFormatterContext对象调用自身的Format()方法格式化Sheet。
public void Format()
{
if (null == Sheet || null == Formatters)
{
return;
}
foreach (var formatter in Formatters)
{
formatter.Format(this);
}
}
Formatters就是从SheetFormatterContainer传过来的“元素格式化器”集合。
抽象的“元素格式化器”:
至此,ExcelReport组件的核心部分已经介绍完成了,下面附上代码(如下代码仅供参考,了解ExcelReport组件最新动态,请到GitHub下载最新源码)。
SheetFormatterContainer.cs
/*
类:SheetFormatterContainer
描述:Sheet中元素的格式化器集合
编 码 人:韩兆新 日期:2015年01月17日
修改记录:
*/
using System.Collections.Generic;
namespace ExcelReport
{
public class SheetFormatterContainer
{
#region 成员字段及属性
PRivate string sheetName;
public string SheetName
{
get { return sheetName; }
}
private IEnumerable<ElementFormatter> formatters;
public IEnumerable<ElementFormatter> Formatters
{
get { return formatters; }
}
#endregion 成员字段及属性
#region 构造函数
public SheetFormatterContainer(string sheetName, IEnumerable<ElementFormatter> formatters)
{
this.sheetName = sheetName;
this.formatters = formatters;
}
#endregion 构造函数
}
}
SheetFormatterContext.cs
/*
类:SheetFormatterContext
描述:Sheet格式化的上下文
编 码 人:韩兆新 日期:2015年01月17日
修改记录:
*/
using System.Collections.Generic;
using NPOI.SS.UserModel;
namespace ExcelReport
{
public class SheetFormatterContext
{
#region 成员字段及属性
private int _increaseRowsCount = 0;
public ISheet Sheet { get; set; }
public IEnumerable<ElementFormatter> Formatters { get; set; }
#endregion 成员字段及属性
#region 构造函数
public SheetFormatterContext()
{
}
public SheetFormatterContext(ISheet sheet, IEnumerable<ElementFormatter> formatters)
{<
新闻热点
疑难解答