分享一个简单一用的 Excel 导出的类库
特性如下:
-
可支持复杂的多级表头的导出,表头采用树结构的数据,最终取所有的叶子节点作为数据列。
-
支持 DataTable、DataSet、IEnumerable、IEnumerable<>、IEnumerable<IDictianry>、IEnumerable<IDictianry<,>>、Lazy<>、Func<> 等类型作为数据源。
-
每个 WorkBook 可导出多个 Sheet,可自动实现分页导出到不同的 Sheet。
-
可对列中连续的重复值做合并单元格操作。
-
可对单元格的值格式化、设置行列的颜色、宽度等。
大概说一下,整个设计吧,
1、首先有一个 IExcelExporter 的接口,第一如下:
1 public interface IExcelExporter 2 { 3 Task BuildSheetsAsync( 4 Stream stream, IEnumerable<Settings> settings_list, bool useOldVersion = false, 5 object hostContext = null); 6 }
2、然后有一个抽象类, ExcelExporterBase<TWorkBook, TWorkSheet, TCellStyle> 实现 IExcelExporter 接口。
抽象类里面封装了创建表头、创建表格主题的、合并列中连续重复值 等的算法。然后定义了一些需要在子类是实现的抽象方法。如下:
1 #region [ protected ] 2 3 protected abstract TWorkBook CreateWorkBook(bool useOldVersion); 4 5 protected abstract TWorkSheet CreateWorkSheet(TWorkBook workbook, string name, Settings settings); 6 7 protected abstract TCellStyle CreateCellStyle(TWorkBook workbook, TCellStyle style, CellStyle cellStyle); 8 9 protected abstract TCellStyle GetCellStyle(TWorkBook workbook, TWorkSheet sheet, int row, int col); 10 11 protected abstract void SetCell(TWorkBook workbook, TWorkSheet sheet, int row, int col, Settings settings, ColNode node, object value, TCellStyle style, bool setValue = true, bool setStyle = true); 12 13 protected abstract void MergeCells(TWorkBook workbook, TWorkSheet sheet, int startRow, int endRow, int startCol, int endCol, Settings settings); 14 15 protected abstract void FreezePane(TWorkBook workbook, TWorkSheet sheet, int rowSplit, int colSplit); 16 17 protected abstract void SetColumnsWidth(TWorkBook workbook, TWorkSheet sheet, Settings settings, uint[] widthArray, int startCol); 18 19 protected abstract void AutoFillColumns(TWorkBook workbook, TWorkSheet sheet, Settings settings, int startCol); 20 21 protected abstract void Save(TWorkBook workbook, bool useOldVersion, Stream stream); 22 23 #endregion
几个抽象方法,都很好理解,根据方法名很容易知道要实现的功能。
3、在具体的实现中我用 Aspose.Cells 和 NPOI 分别实现了一套。
Aspose_Cells_ExcelExporter、 NPOI_ExcelExporter 这两个类。
4、使用示例。
DataTable dt = MAIN.Get_Users(); Settings set = new Settings() { PageSize = 100, Name = "", ColumnsAutoWidth = true, StartColIndex = 1, StartRowIndex = 1, DataSource = new Lazy<System.Collections.Generic.IEnumerable<SysUser>>(() => { string str = ConfigurationManager.ConnectionStrings["mysql_demo"].ConnectionString; return MAIN.helper.ToEnumerable2<SysUser>("SELECT * FROM SysUser"); //MAIN.Get_Users(); }), FreezeHeader = true, //RowStyleGetter = (i, row) => i % 2 == 0 ? CellStyle.Body : new CellStyle() { BgColor = Color.White, FgColor = RandColor() }, RootNodes = new[]{ new ColNode(){ Title = "用户列表", ChildColNodes = dt.Columns.Cast< DataColumn>().Select(col => new ColNode { Title = col.ColumnName, Field = col.ColumnName, MergeField = col.ColumnName }).ToArray() } } }; IExcelExporter ep = new NPOI_ExcelExporter(); Task task = ep.BuildSheetsAsync( new FileStream("./test.xlsx", FileMode.Create, FileAccess.Write), new[] { set }, false); task.Wait();
这里导出时,我将表头作为了一个父列,DataTable 的所有列作为子列。
比如 SysUser 表结构如下 : ID、UserName、Sex
那么导出的 Excel 格式如下
用户列表 | ||
ID | UserName | Sex |
已在开源中国开源,有需要的朋友,可以下载,欢迎拍砖。