代码改变世界

扩展NPOI,一行代码导出二进制Excel(下)

2009-12-30 13:52  Zork  阅读(887)  评论(0编辑  收藏  举报

话接上一回。扩展NPOI,一行代码导出二进制Excel

 在上一篇Blog中,我们已经讲解了生成Excel所需要的接口和类库。然而真正实现生成Excel代码的逻辑还没有给出,这也是本文的目的。

 回顾上一篇文章,生成Excel的方法的实现代码如下:

 

ReportExcel
 1         /// <summary>
 2         /// 导出Excel
 3         /// </summary>
 4         /// <typeparam name="T"></typeparam>
 5         /// <param name="dataSource"></param>
 6         /// <param name="sheetName"></param>
 7         /// <param name="writer"></param>
 8         /// <param name="columns"></param>
 9         public static void ReportExcel<T>(IEnumerable<T> dataSource, String sheetName, Stream writer, Action<IRootExcelColumnBuilder<T>> columns)
10             where T : class
11         {
12             ReportExcel(dataSource, sheetName, writer, columns, nullnullnullnull);
13         }
14 
15         /// <summary>
16         /// 导出Excel
17         /// </summary>
18         /// <typeparam name="T"></typeparam>
19         /// <param name="dataSource"></param>
20         /// <param name="sheetName"></param>
21         /// <param name="writer"></param>
22         /// <param name="columns"></param>
23         /// <param name="documentProperty"></param>
24         /// <param name="workbookProperty"></param>
25         public static void ReportExcel<T>(IEnumerable<T> dataSource, String sheetName, Stream writer, Action<IRootExcelColumnBuilder<T>> columns,
26             Action<DocumentSummaryInformation> documentProperty, Action<SummaryInformation> summaryProperty,
27             Action<HSSFCellStyle> defaultHeaderStyle, Action<HSSFCellStyle> defaultBodyStyle)
28             where T : class
29         {
30             var exporter = new ExcelExporter(writer);
31             exporter.DocumentProperty = documentProperty;
32             exporter.SummaryProperty = summaryProperty;
33             exporter.DefaultHeaderStyle = defaultHeaderStyle;
34             exporter.DefaultBodyStyle = defaultBodyStyle;
35 
36             var columnBuilder = CreateColumnBuilder(columns);
37             //生成Excel
38             exporter.GenerateSheet(sheetName, dataSource, columnBuilder);
39 
40             exporter.Save();
41         }

 

抛开其它杂项,请看方法exporter.GenerateSheet(sheetName, dataSource, columnBuilder);的实现:

 

 

GenerateSheet
       /// <summary>
        
/// 生成工作表
        
/// </summary>
        
/// <typeparam name="T"></typeparam>
        
/// <param name="sheetName">工作表名称</param>
        
/// <param name="items">数据源</param>
        
/// <param name="columns">数据列构建器</param>
        public void GenerateSheet<T>(String sheetName, IEnumerable<T> items, ExcelColumnBuilder<T> columns)
            
where T : class
        {
            
//设置Table样式
            HSSFSheet sheet = String.IsNullOrEmpty(sheetName) ? this.Workbook.CreateSheet() : this.Workbook.CreateSheet(sheetName);
            
this.CurrentSheet = sheet;
            
//生成样式
            this.GenerateHeader(columns, sheet);
            
//生成Body
            this.GenerateItems(items, columns, sheet);
        }

 

从该段代码中可以看出生成Excel的顺序是:

1. 生成工作表Sheet;

2. 生成数据列头样式;

3. 生成Excel数据单元格。

 

GenerateItems
 1         /// <summary>
 2         /// 生成数据行
 3         /// </summary>

 4         protected virtual void GenerateItems<T>(IEnumerable<T> dataSource, ExcelColumnBuilder<T> columns, HSSFSheet sheet)
 5             where T : class

 6         {           
 7             if (!
dataSource.Any())
 8 
            {
 9                 return
;
10 
            }
11 

12             //保存单元格样式信息
13             List<HSSFCellStyle> bodyStyles = new List<HSSFCellStyle>(columns.ColumnCount);
14             //生成样式信息

15             foreach (var column in columns)
16 
            {
17                 #region 设置样式

18                 HSSFCellStyle bodyStyle = this.Workbook.CreateCellStyle();
19                 this
.SetDefaultBodyStyle(bodyStyle);
20                 if (column.BodyStyle != null
)
21 
                {
22 
                    column.BodyStyle(bodyStyle);
23 
                }              
24 
                bodyStyles.Add(bodyStyle);
25                 #endregion

26             }
27 
           
28             //第一行用户数据列头

29             Int32 rowIndex = 1;
30             foreach (var item in
 dataSource)
31 
            {
32                 HSSFRow row =
 sheet.CreateRow(rowIndex);
33                 Int32 columnIndex = 0
;
34                 rowIndex++
;
35 

36                 foreach (var column in columns)
37 
                {                   
38                     HSSFCell cell =
 row.CreateCell(columnIndex);
39                     cell.CellStyle =
 bodyStyles[columnIndex];                    
40                     if (column.CustomRenderer == null
)
41 
                    {
42                         #region 获取数据 并 格式化单元格数据

43                         Object value = null;
44                         if (column.ColumnDelegate != null
)
45 
                        {
46                             value =
 column.ColumnDelegate(item);
47 
                        }
48                         else

49                         {
50                             var property =
 item.GetType().GetProperty(column.Name);
51                             if (property != null
)
52 
                            {
53                                 value = property.GetValue(item, null
);
54 
                            }
55 
                        }
56 

57                         String formattedValue = null;
58                         if (value != null
)
59 
                        {
60                             if (column.Format != null
)
61 
                            {
62                                 formattedValue =
 String.Format(column.Format, value);
63 
                            }
64                             else

65                             {
66                                 formattedValue =
 value.ToString();
67 
                            }
68 
                        }
69                         #endregion

70 
71                         cell.SetCellValue(formattedValue);
72 
                    }
73                     else

74                     {
75                         //自定义呈现单元格 

76                         column.CustomRenderer(item, cell);                        
77 
                    }
78 

79                     #region 设置链接
80                     if (null != column.HrefDelegate)
81 
                    {
82                         var href =
 column.HrefDelegate(item);
83                         if (null !=
 href)
84 
                        {
85                             var link = new
 HSSFHyperlink(HSSFHyperlink.LINK_URL)
86 
                            {
87                                 Address =
 href.ToString()
88 
                            };
89                             cell.Hyperlink =
 link;
90 
                        }
91 
                    }
92                     #endregion

93 
94                     columnIndex++;
95 
                }
96 
            }
97         }

 

首先,创建单元格样式,如果有自定义样式委托,则调用委托方法,生成单元格样式。否者使用默认样式。然后, 迭代数据源,生成Excel工作表的数据行。

在创建单元格的过程中,

  1. 首先查看单元格是否为自定义创建NPOI单元格。

  2. 查看单元格是否有获取数据的委托Func<T, Object> ColumnDelegate,如果存在,从该委托获取值.如果不存在,从数据实体T的属性中获取值。然后提供格式化功能,格式化数据输出。

     3. 如果单元格需要超链接,则设置单元格的超链接。

 

到此,用一行代码导出Excel的目标就实现了。

以下是相关类库和实例下载:

SmartExcel