首页 > 学院 > 开发设计 > 正文

基于NPOI导出Excel

2019-11-17 02:52:23
字体:
来源:转载
供稿:网友

基于NPOI导出Excel

2014-09-22 16:56 by 谢中涞, ... 阅读, ... 评论, 收藏, 编辑

在上一篇文章[关于大数据的查询与导出]中,提到了使用NPOI组件导出Excel,本想上次一起分享给大家,无奈最近比较忙,今天抽空整理了下,分享出来.

  1. 预置填充模板,并且需要支持公式计算;
  2. 可导入图片;
  3. 可以追加数据形式填充表格.
  1. 简单分一下这个功能.
    1. 需要处理模板的读取,并根据模板中指定特定适配符替换模板中的数据,需要处理三种类型的单元格的格式化:散列单元格,图片单元格,数据明细区单元格;
    2. 散列单元格: 需要定义具体的模板字符串,及期望格式化后的数据,姑且将这里处理散列单元格的对象 命名为 DispersedCellFormater;
    3. 图片的导出,需要指定需要导出Excel 中的具体位置及期望填充的图片资源,姑且将这里才处理图片单元格的对象命名为 ImageCellFormater;
    4. 明细区单元格格式化,需要制定当前的列索引及每个列的这个取值函数.姑且这里将处理对象命名为DetailCellValueFormater<T>,因为了便于使用,我们引入了泛型类型;
    5. 外部调用,统一从一个入口处理,这里暂且命名为 ExportFormater;
    6. 至于散列单元格的位置,我们采用系统内置的 Point 类型来描述,明细区的取值函数使用系统定义的Func<T,object> 来描述,这里的输入类型T即为当前行数据对象;
  2. 根据以上分析,我们简单画一下这个功能的UML图,以方便理解. image
  3. 有了以上分析,实现似乎就是水到渠成的事情了.
    1. 我们拟定一个接口,用于约束导出操作.
      /// <summary>/// 导出接口/// </summary>public interface IExport{    /// <summary>    /// 导出数据,基于模板文件处理替换后,保存为一个新文件    /// </summary>    /// <param name="templateFile">模板文件</param>    /// <param name="targetFile">目标文件</param>    /// <param name="fromater">模板格式化处理规则</param>    void Export(string templateFile, string targetFile, ExportFormater fromater);    /// <summary>    /// 导出数据,基于模板文件处理替换后,保存为一个新文件    /// </summary>    /// <typeparam name="T">数据源类型</typeparam>    /// <param name="templateFile">模板文件</param>    /// <param name="targetFile">目标文件</param>    /// <param name="formater">模板格式化处理规则</param>    /// <param name="source">数据源</param>    void Export<T>(string templateFile, string targetFile,        ExportFormater<T> formater, IList<T> source) where T : class;    /// <summary>    /// 以追加的形式,将数据添加到已存在的文件中    /// </summary>    /// <typeparam name="T">数据源类型</typeparam>    /// <param name="targetFile">目标文件</param>    /// <param name="formater">模板格式化处理规则</param>    /// <param name="source">数据源</param>    void ExportByAppend<T>(string targetFile, ExportFormater<T> formater,        IList<T> source) where T : class;}
    2. 散列单元格格式处理器
      /// <summary> /// 散列单元格数据格式器 /// </summary> public class DispersedCellFormater {     /// <summary>     /// 单元格坐标     /// </summary>     public Point CellPoint { get; set; }     /// <summary>     /// 格式化字符串     /// </summary>     public string FormaterString { get; set; }     /// <summary>     /// 格式化数据     /// </summary>     public object CellValue { get; set; }     /// <summary>     /// 实例化     /// </summary>     public DispersedCellFormater()     {     }     /// <summary>     /// 实例化     /// </summary>     /// <param name="x">cell 横坐标</param>     /// <param name="y">cell 纵坐标</param>     /// <param name="formatStr">格式化字符串</param>     /// <param name="val">替换值</param>     public DispersedCellFormater(int x, int y, string formatStr, object val)        {            this.CellPoint = new Point(x, y);            this.FormaterString = formatStr;            this.CellValue = val;        } }
    3. 图片单元格格式处理器
      /// <summary> /// 图片Cell格式化器 /// </summary> public class ImageCellFormater {     /// <summary>     /// 单元格位置     /// </summary>     public Point CellPoint { get; set; }     /// <summary>     /// 显示图片     /// </summary>     public Image Img { get; set; }     /// <summary>     /// 实例化     /// </summary>     public ImageCellFormater()        {        }     /// <summary>     /// 实例化     /// </summary>     /// <param name="x">cell横坐标</param>     /// <param name="y">cell纵坐标</param>     /// <param name="img">图片</param>     public ImageCellFormater(int x, int y, Image img)     {         this.CellPoint = new Point(x, y);         this.Img = img;     } }
    4. 明细区单元格格式处理器
      /// <summary>/// 明细单元格取值规则/// <typeparam name="T">数据类型</typeparam>/// </summary>public class DetailCellValueFormater<T> where T : class{    /// <summary>    /// 列索引    /// </summary>    public int Index { get; set; }    /// <summary>    /// 取值函数    /// </summary>    public Func<T, object> Value { get; set; }    /// <summary>    /// 实例化    /// </summary>    public DetailCellValueFormater()    {    }    /// <summary>    /// 实例化    /// </summary>    /// <param name="index">列索引</param>    /// <param name="val">数据</param>    public DetailCellValueFormater(int index, Func<T, object> val)    {        this.Index = index;        this.Value = val;    }}
    5. 接下来一起看下导出格式处理集合的定义.
      /// <summary>/// 用于描述导出格式化数据/// </summary>public class ExportFormater{    /// <summary>    /// 散列单元格替换规格    /// </summary>    public List<DispersedCellFormater> DispersedCellFormaters { get; PRivate set; }    /// <summary>    /// 图片单元格格式化规则    /// </summary>    public List<ImageCellFormater> ImageCellFormaters { get; private set; }    /// <summary>    /// 明细数据起始行索引    /// </summary>    public int DetailRowBeginIndex { get; set; }    /// <summary>    /// 实例化    /// </summary>    public ExportFormater()    {        DispersedCellFormaters = new List<DispersedCellFormater>();        ImageCellFormaters = new List<ImageCellFormater>();    }}/// <summary>/// 用于描述导出格式化数据,带有明细区数据取值规则/// </summary>public class ExportFormater<T> : ExportFormater where T : class{    /// <summary>    /// 明细区取值函数    /// </summary>    public List<DetailCellValueFormater<T>> DetailCellValueFormaters { get; private set; }    /// <summary>    /// 实例化    /// </summary>    public ExportFormater()    {        DetailCellValueFormaters = new List<DetailCellValueFormater<T>>();    }}
    6. 接下来我们简单看下导出的具体实现.
      1. 散列单元格的处理
        /// <summary>/// 应用散列单元格格式/// </summary>/// <param name="formater">格式化规则</param>/// <param name="sheet">当前sheet</param>private static void ApplyDispersedCell(ExportFormater formater, HSSFSheet sheet){    if (formater.DispersedCellFormaters != null && formater.DispersedCellFormaters.Count > 0)    {        formater.DispersedCellFormaters.ForEach(r =>        {            var tempRow = sheet.GetRow(r.CellPoint.X);            var tempCell = tempRow.GetCell(r.CellPoint.Y);            var txt = tempCell.StringCellValue;            if (string.IsNullOrWhiteSpace(txt))            {                tempCell.SetCellValue(Convert.ToString(r.CellValue));            }            else            {                //替换模板                tempCell.SetCellValue(txt.Replace(r.FormaterString, Convert.ToString(r.CellValue)));            }        });    }}
      2. 图片单元格的处理
        /// <summary> /// 应用图片单元格 /// </summary> /// <param name="formater">格式化处理器</param> /// <param name="workbook"></param> /// <param name="sheet"></param> private static void ApplyImgCell(ExportFormater formater,     HSSFWorkbook workbook, HSSFSheet sheet) {     if (formater.ImageCellFormaters.Count <= 0)     {         return;     }     var patriarch = sheet.CreateDrawingPatriarch();     formater.ImageCellFormaters.ForEach(t =>     {         if (t.Img != null)         {             var imgData = t.Img.ToByte();             //- 图片输出的位置这么计算的:             //- 假设我们要将图片放置于第 5(E) 列的第 2 行              //- 对应索引为是 4 : 1 (默认位置)             //- 放置的位置就等于(默认位置)到(默认位置各自加上一行、一列)             var imgPath = new HSSFClientAnchor(                1, 1,              //- 上左 到 上右 的位置,是基于下面的行列位置
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表