分享我基于NPOI+ExcelReport实现的导入与导出EXCEL类库:ExcelUtility

1. ExcelUtility功能:
   1.将数据导出到EXCEL(支持XLS,XLSX,支持多种类型模板,支持列宽自适应)
     类名:ExcelUtility. Export


   2.将EXCEL数据导入到数据对象中(DataTable、Dataset,支持XLS,XLSX)
     类名:ExcelUtility. Import

  类库项目文件结构如下图示:

  


 2. ExcelUtility依赖组件:
   1.NPOI 操作EXCEL核心类库
   2.NPOI.Extend NPOI扩展功能
   3. ExcelReport 基于NPOI的二次扩展,实现模板化导出功能
   4. System.Windows.Forms 导出或导入时,弹出文件选择对话框(如果用在WEB中可以不需要,但我这里以CS端为主)

3.使用环境准备:

  1.通过NUGet引用NPOI包、ExcelReport 包;(ExcelReport 存在BUG,可能需要用我项目中修复过后的DLL)

  2.引用ExcelUtility类库;

4.具体使用方法介绍(示例代码,全部为测试方法):

导出方法测试:

1
2
3
4
5
6
7
8
9
10
/// <summary>
         /// 测试方法:测试将DataTable导出到EXCEL,无模板
         /// </summary>
         [TestMethod]
         public  void  TestExportToExcelByDataTable()
         {
             DataTable dt = GetDataTable();
             string  excelPath = ExcelUtility.Export.ToExcel(dt,  "导出结果" );
             Assert.IsTrue(File.Exists(excelPath));
         }

结果如下图示:

 

1
2
3
4
5
6
7
8
9
10
11
/// <summary>
/// 测试方法:测试将DataTable导出到EXCEL,无模板,且指定导出的列名
/// </summary>
[TestMethod]
public  void  TestExportToExcelByDataTable2()
{
     DataTable dt = GetDataTable();
     string [] expColNames = {  "Col1" "Col2" "Col3" "Col4" "Col5"  };
     string  excelPath = ExcelUtility.Export.ToExcel(dt,  "导出结果" null , expColNames);
     Assert.IsTrue(File.Exists(excelPath));
}

结果如下图示:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/// <summary>
       /// 测试方法:测试将DataTable导出到EXCEL,无模板,且指定导出的列名,以及导出列名的重命名
       /// </summary>
       [TestMethod]
       public  void  TestExportToExcelByDataTable3()
       {
           DataTable dt = GetDataTable();
           string [] expColNames = {  "Col1" "Col2" "Col3" "Col4" "Col5"  };
           Dictionary< string string > expColAsNames =  new  Dictionary< string string >() {
               { "Col1" , "列一" },
               { "Col2" , "列二" },
               { "Col3" , "列三" },
               { "Col4" , "列四" },
               { "Col5" , "列五" }
           };
           string  excelPath = ExcelUtility.Export.ToExcel(dt,  "导出结果" null , expColNames,expColAsNames);
           Assert.IsTrue(File.Exists(excelPath));
       }

结果如下图示:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// <summary>
       /// 测试方法:测试将DataTable导出到EXCEL,无模板,且指定导出列名的重命名
       /// </summary>
       [TestMethod]
       public  void  TestExportToExcelByDataTable4()
       {
           DataTable dt = GetDataTable();
           Dictionary< string string > expColAsNames =  new  Dictionary< string string >() {
               { "Col1" , "列一" },
               { "Col5" , "列五" }
           };
           string  excelPath = ExcelUtility.Export.ToExcel(dt,  "导出结果" null null , expColAsNames);
           Assert.IsTrue(File.Exists(excelPath));
       }

结果如下图示:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/// <summary>
/// 测试方法:测试依据模板+DataTable来生成EXCEL
/// </summary>
[TestMethod]
public  void  TestExportToExcelWithTemplateByDataTable()
{
     DataTable dt = GetDataTable(); //获取数据
     string  templateFilePath = AppDomain.CurrentDomain.BaseDirectory +  "/excel.xlsx" //获得EXCEL模板路径
     SheetFormatterContainer<DataRow> formatterContainers =  new  SheetFormatterContainer<DataRow>();  //实例化一个模板数据格式化容器
 
     PartFormatterBuilder partFormatterBuilder =  new  PartFormatterBuilder(); //实例化一个局部元素格式化器
     partFormatterBuilder.AddFormatter( "Title" "IT学员" ); //将模板表格中Title的值设置为跨越IT学员
     formatterContainers.AppendFormatterBuilder(partFormatterBuilder); //添加到工作薄格式容器中,注意只有添加进去了才会生效
 
     CellFormatterBuilder cellFormatterBuilder =  new  CellFormatterBuilder(); //实例化一个单元格格式化器
     cellFormatterBuilder.AddFormatter( "rptdate" , DateTime.Today.ToString( "yyyy-MM-dd HH:mm" )); //将模板表格中rptdate的值设置为当前日期
     formatterContainers.AppendFormatterBuilder(cellFormatterBuilder); //添加到工作薄格式容器中,注意只有添加进去了才会生效
 
     //实例化一个表格格式化器,dt.Select()是将DataTable转换成DataRow[],name表示的模板表格中第一行第一个单元格要填充的数据参数名
     TableFormatterBuilder<DataRow> tableFormatterBuilder =  new  TableFormatterBuilder<DataRow>(dt.Select(),  "name" );
     tableFormatterBuilder.AddFormatters( new  Dictionary< string , Func<DataRow,  object >>{
         { "name" ,r=>r[ "Col1" ]}, //将模板表格中name对应DataTable中的列Col1
         { "sex" ,r=>r[ "Col2" ]}, //将模板表格中sex对应DataTable中的列Col2
         { "km" ,r=>r[ "Col3" ]}, //将模板表格中km对应DataTable中的列Col3
         { "score" ,r=>r[ "Col4" ]}, //将模板表格中score对应DataTable中的列Col
         { "result" ,r=>r[ "Col5" ]} //将模板表格中result对应DataTable中的列Co5
     });
     formatterContainers.AppendFormatterBuilder(tableFormatterBuilder); //添加到工作薄格式容器中,注意只有添加进去了才会生效
 
     string  excelPath = ExcelUtility.Export.ToExcelWithTemplate<DataRow>(templateFilePath,  "table" , formatterContainers);
     Assert.IsTrue(File.Exists(excelPath));
}

模板如下图示:

结果如下图示:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/// <summary>
/// 测试方法:测试依据模板+List来生成EXCEL
/// </summary>
[TestMethod]
public  void  TestExportToExcelWithTemplateByList()
{
     List<Student> studentList = GetStudentList(); //获取数据
     string  templateFilePath = AppDomain.CurrentDomain.BaseDirectory +  "/excel.xlsx" //获得EXCEL模板路径
     SheetFormatterContainer<Student> formatterContainers =  new  SheetFormatterContainer<Student>();  //实例化一个模板数据格式化容器
 
     PartFormatterBuilder partFormatterBuilder =  new  PartFormatterBuilder(); //实例化一个局部元素格式化器
     partFormatterBuilder.AddFormatter( "Title" "IT学员" ); //将模板表格中Title的值设置为跨越IT学员
     formatterContainers.AppendFormatterBuilder(partFormatterBuilder); //添加到工作薄格式容器中,注意只有添加进去了才会生效
 
     CellFormatterBuilder cellFormatterBuilder =  new  CellFormatterBuilder(); //实例化一个单元格格式化器
     cellFormatterBuilder.AddFormatter( "rptdate" , DateTime.Today.ToString( "yyyy-MM-dd HH:mm" )); //将模板表格中rptdate的值设置为当前日期
     formatterContainers.AppendFormatterBuilder(cellFormatterBuilder); //添加到工作薄格式容器中,注意只有添加进去了才会生效
 
     //实例化一个表格格式化器,studentList本身就是可枚举的无需转换,name表示的模板表格中第一行第一个单元格要填充的数据参数名
     TableFormatterBuilder<Student> tableFormatterBuilder =  new  TableFormatterBuilder<Student>(studentList,  "name" );
     tableFormatterBuilder.AddFormatters( new  Dictionary< string , Func<Student,  object >>{
         { "name" ,r=>r.Name}, //将模板表格中name对应Student对象中的属性Name
         { "sex" ,r=>r.Sex}, //将模板表格中sex对应Student对象中的属性Sex
         { "km" ,r=>r.KM}, //将模板表格中km对应Student对象中的属性KM
         { "score" ,r=>r.Score}, //将模板表格中score对应Student对象中的属性Score
         { "result" ,r=>r.Result} //将模板表格中result对应Student对象中的属性Result
     });
     formatterContainers.AppendFormatterBuilder(tableFormatterBuilder);
 
     string  excelPath = ExcelUtility.Export.ToExcelWithTemplate<Student>(templateFilePath,  "table" , formatterContainers);
     Assert.IsTrue(File.Exists(excelPath));
 
}

结果如下图示:(模板与上面相同)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/// <summary>
/// 测试方法:测试依据模板+DataTable来生成多表格EXCEL(注意:由于NPOI框架限制,目前仅支持模板文件格式为:xls)
/// </summary>
[TestMethod]
public  void  TestExportToRepeaterExcelWithTemplateByDataTable()
{
     DataTable dt = GetDataTable(); //获取数据
     string  templateFilePath = AppDomain.CurrentDomain.BaseDirectory +  "/excel2.xls" //获得EXCEL模板路径
     SheetFormatterContainer<DataRow> formatterContainers =  new  SheetFormatterContainer<DataRow>();  //实例化一个模板数据格式化容器
 
     //实例化一个可重复表格格式化器,dt.Select()是将DataTable转换成DataRow[],rpt_begin表示的模板表格开始位置参数名,rpt_end表示的模板表格结束位置参数名
     RepeaterFormatterBuilder<DataRow> tableFormatterBuilder =  new  RepeaterFormatterBuilder<DataRow>(dt.Select(),  "rpt_begin" "rpt_end" );
     tableFormatterBuilder.AddFormatters( new  Dictionary< string , Func<DataRow,  object >>{
         { "sex" ,r=>r[ "Col2" ]}, //将模板表格中sex对应DataTable中的列Col2
         { "km" ,r=>r[ "Col3" ]}, //将模板表格中km对应DataTable中的列Col3
         { "score" ,r=>r[ "Col4" ]}, //将模板表格中score对应DataTable中的列Col
         { "result" ,r=>r[ "Col5" ]} //将模板表格中result对应DataTable中的列Co5
     });
 
     PartFormatterBuilder<DataRow> partFormatterBuilder2 =  new  PartFormatterBuilder<DataRow>(); //实例化一个可嵌套的局部元素格式化器
     partFormatterBuilder2.AddFormatter( "name" , r => r[ "Col1" ]); //将模板表格中name对应DataTable中的列Col1
     tableFormatterBuilder.AppendFormatterBuilder(partFormatterBuilder2); //添加到可重复表格格式化器中,作为其子格式化器
 
 
     CellFormatterBuilder<DataRow> cellFormatterBuilder =  new  CellFormatterBuilder<DataRow>(); //实例化一个可嵌套的单元格格式化器
     cellFormatterBuilder.AddFormatter( "rptdate" , r => DateTime.Today.ToString( "yyyy-MM-dd HH:mm" )); //将模板表格中rptdate的值设置为当前日期
     tableFormatterBuilder.AppendFormatterBuilder(cellFormatterBuilder); //添加到可重复表格格式化器中,作为其子格式化器
 
     formatterContainers.AppendFormatterBuilder(tableFormatterBuilder); //添加到工作薄格式容器中,注意只有添加进去了才会生效
 
     string  excelPath = ExcelUtility.Export.ToExcelWithTemplate<DataRow>(templateFilePath,  "multtable" , formatterContainers);
     Assert.IsTrue(File.Exists(excelPath));
}

模板如下图示:(注意:该模板仅支持XLS格式文件,XLSX下存在问题)

结果如下图示:

以下是模拟数据来源所定义的方法(配合测试):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
private  DataTable GetDataTable()
{
     DataTable dt =  new  DataTable();
     for  ( int  i = 1; i <= 6; i++)
     {
         if  (i == 4)
         {
             dt.Columns.Add( "Col"  + i.ToString(),  typeof ( double ));
         }
         else
         {
             dt.Columns.Add( "Col"  + i.ToString(),  typeof ( string ));
         }
     }
 
     for  ( int  i = 1; i <= 10; i++)
     {
         dt.Rows.Add( "Name"  + i.ToString(), (i % 2) > 0 ?  "男"  "女" "科目"  + i.ToString(), i *  new  Random().Next(1, 5),  "待定" , Guid.NewGuid().ToString( "N" ));
     }
 
     return  dt;
}
 
private  List<Student> GetStudentList()
{
     List<Student> studentList =  new  List<Student>();
     for  ( int  i = 1; i <= 10; i++)
     {
         studentList.Add( new  Student
         {
             Name =  "Name"  + i.ToString(),
             Sex = (i % 2) > 0 ?  "男"  "女" ,
             KM =  "科目"  + i.ToString(),
             Score = i *  new  Random().Next(1, 5),
             Result =  "待定"
         });
     }
     return  studentList;
}
 
class  Student
{
     public  string  Name {  get set ; }
 
     public  string  Sex {  get set ; }
 
     public  string  KM {  get set ; }
 
     public  double  Score {  get set ; }
 
     public  string  Result {  get set ; }
}

导入方法测试:

1
2
3
4
5
6
7
8
9
10
/// <summary>
    /// 测试方法:测试将指定的EXCEL数据导入到DataTable
    /// </summary>
    [TestMethod]
    public  void  TestImportToDataTableFromExcel()
    {
       //null表示由用户选择EXCEL文件路径,data表示要导入的sheet名,0表示数据标题行
       DataTable dt=  ExcelUtility.Import.ToDataTable( null "data" , 0);
       Assert.AreNotEqual(0, dt.Rows.Count);
    }

数据源文件内容如下图示:

 

下面贴出该类库主要源代码:

ExcelUtility.Export类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
using  ExcelReport;
using  ExcelUtility.Base;
using  NPOI.SS.UserModel;
using  System;
using  System.Collections.Generic;
using  System.Data;
using  System.IO;
using  System.Linq;
using  System.Text;
using  System.Windows.Forms;
 
namespace  ExcelUtility
{
     public  sealed  class  Export
     {
         /// <summary>
         /// 由DataSet导出Excel
         /// </summary>
         /// <param name="sourceTable">要导出数据的DataTable</param>
         /// <param name="filePath">导出路径,可选</param>
         /// <returns></returns>
         public  static  string  ToExcel(DataSet sourceDs,  string  filePath =  null )
         {
 
             if  ( string .IsNullOrEmpty(filePath))
             {
                 filePath = Common.GetSaveFilePath();
             }
 
             if  ( string .IsNullOrEmpty(filePath))  return  null ;
 
             bool  isCompatible = Common.GetIsCompatible(filePath);
 
             IWorkbook workbook = Common.CreateWorkbook(isCompatible);
             ICellStyle headerCellStyle = Common.GetCellStyle(workbook, true );
             ICellStyle cellStyle = Common.GetCellStyle(workbook);
 
             for  ( int  i = 0; i < sourceDs.Tables.Count; i++)
             {
                 DataTable table = sourceDs.Tables[i];
                 string  sheetName =  string .IsNullOrEmpty(table.TableName) ?  "result"  + i.ToString() : table.TableName;
                 ISheet sheet = workbook.CreateSheet(sheetName);
                 IRow headerRow = sheet.CreateRow(0);
                 // handling header.
                 foreach  (DataColumn column  in  table.Columns)
                 {
                     ICell headerCell = headerRow.CreateCell(column.Ordinal);
                     headerCell.SetCellValue(column.ColumnName);
                     headerCell.CellStyle = headerCellStyle;
                     sheet.AutoSizeColumn(headerCell.ColumnIndex);
                 }
 
                 // handling value.
                 int  rowIndex = 1;
                 
                 foreach  (DataRow row  in  table.Rows)
                 {
                     IRow dataRow = sheet.CreateRow(rowIndex);
 
                     foreach  (DataColumn column  in  table.Columns)
                     {
                         ICell cell = dataRow.CreateCell(column.Ordinal);
                         cell.SetCellValue((row[column] ??  "" ).ToString());
                         cell.CellStyle = cellStyle;
                         Common.ReSizeColumnWidth(sheet, cell);
                     }
 
                     rowIndex++;
                 }
             }
 
             FileStream fs =  new  FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
             workbook.Write(fs);
             fs.Dispose();
             workbook =  null ;
 
             return  filePath;
 
         }
 
         /// <summary>
         /// 由DataTable导出Excel
         /// </summary>
         /// <param name="sourceTable">要导出数据的DataTable</param>
         /// <param name="colAliasNames">导出的列名重命名数组</param>
         /// <param name="sheetName">工作薄名称,可选</param>
         /// <param name="filePath">导出路径,可选</param>
         /// <returns></returns>
         public  static  string  ToExcel(DataTable sourceTable,  string [] colAliasNames,  string  sheetName =  "result" string  filePath =  null )
         {
             if  (sourceTable.Rows.Count <= 0)  return  null ;
 
             if  ( string .IsNullOrEmpty(filePath))
             {
                 filePath = Common.GetSaveFilePath();
             }
 
             if  ( string .IsNullOrEmpty(filePath))  return  null ;
 
             if  (colAliasNames ==  null  || sourceTable.Columns.Count != colAliasNames.Length)
             {
                 throw  new  ArgumentException( "列名重命名数组与DataTable列集合不匹配。" "colAliasNames" );
             }
 
             bool  isCompatible = Common.GetIsCompatible(filePath);
 
             IWorkbook workbook = Common.CreateWorkbook(isCompatible);
             ICellStyle headerCellStyle = Common.GetCellStyle(workbook,  true );
             ICellStyle cellStyle = Common.GetCellStyle(workbook);
 
             ISheet sheet = workbook.CreateSheet(sheetName);
             IRow headerRow = sheet.CreateRow(0);
             // handling header.
             foreach  (DataColumn column  in  sourceTable.Columns)
             {
                 ICell headerCell = headerRow.CreateCell(column.Ordinal);
                 headerCell.SetCellValue(colAliasNames[column.Ordinal]);
                 headerCell.CellStyle = headerCellStyle;
                 sheet.AutoSizeColumn(headerCell.ColumnIndex);
             }
 
             // handling value.
             int  rowIndex = 1;
 
             foreach  (DataRow row  in  sourceTable.Rows)
             {
                 IRow dataRow = sheet.CreateRow(rowIndex);
 
                 foreach  (DataColumn column  in  sourceTable.Columns)
                 {
                     ICell cell = dataRow.CreateCell(column.Ordinal);
                     cell.SetCellValue((row[column] ??  "" ).ToString());
                     cell.CellStyle = cellStyle;
                     Common.ReSizeColumnWidth(sheet, cell);
                 }
 
                 rowIndex++;
             }
             FileStream fs =  new  FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
             workbook.Write(fs);
             fs.Dispose();
 
             sheet =  null ;
             headerRow =  null ;
             workbook =  null ;
 
             return  filePath;
         }
 
         /// <summary>
         /// 由DataGridView导出
         /// </summary>
         /// <param name="grid">要导出的DataGridView对象</param>
         /// <param name="sheetName">工作薄名称,可选</param>
         /// <param name="filePath">导出路径,可选</param>
         /// <returns></returns>
         public  static  string  ToExcel(DataGridView grid,  string  sheetName =  "result" string  filePath =  null )
         {
             if  (grid.Rows.Count <= 0)  return  null ;
 
             if  ( string .IsNullOrEmpty(filePath))
             {
                 filePath = Common.GetSaveFilePath();
             }
 
             if  ( string .IsNullOrEmpty(filePath))  return  null ;
 
             bool  isCompatible = Common.GetIsCompatible(filePath);
 
             IWorkbook workbook = Common.CreateWorkbook(isCompatible);
             ICellStyle headerCellStyle = Common.GetCellStyle(workbook,  true );
             ICellStyle cellStyle = Common.GetCellStyle(workbook);
             ISheet sheet = workbook.CreateSheet(sheetName);
 
             IRow headerRow = sheet.CreateRow(0);
 
             for  ( int  i = 0; i < grid.Columns.Count; i++)
             {
                 ICell headerCell = headerRow.CreateCell(i);
                 headerCell.SetCellValue(grid.Columns[i].HeaderText);
                 headerCell.CellStyle = headerCellStyle;
                 sheet.AutoSizeColumn(headerCell.ColumnIndex);
             }
 
             int  rowIndex = 1;
             foreach  (DataGridViewRow row  in  grid.Rows)
             {
                 IRow dataRow = sheet.CreateRow(rowIndex);
                 for  ( int  n = 0; n < grid.Columns.Count; n++)
                 {
                     ICell cell = dataRow.CreateCell(n);
                     cell.SetCellValue((row.Cells[n].Value ??  "" ).ToString());
                     cell.CellStyle = cellStyle;
                     Common.ReSizeColumnWidth(sheet, cell);
                 }
                 rowIndex++;
             }
 
             FileStream fs =  new  FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
             workbook.Write(fs);
             fs.Dispose();
 
             sheet =  null ;
             headerRow =  null ;
             workbook =  null ;
 
             return  filePath;
         }
 
         /// <summary>
         /// 由DataTable导出Excel
         /// </summary>
         /// <param name="sourceTable">要导出数据的DataTable</param>
         /// <param name="sheetName">工作薄名称,可选</param>
         /// <param name="filePath">导出路径,可选</param>
         /// <param name="colNames">需要导出的列名,可选</param>
         /// <param name="colAliasNames">导出的列名重命名,可选</param>
         /// <returns></returns>
         public  static  string  ToExcel(DataTable sourceTable,  string  sheetName =  "result" string  filePath =  null string [] colNames =  null , IDictionary< string string > colAliasNames =  null )
         {
             if  (sourceTable.Rows.Count <= 0)  return  null ;
 
             if  ( string .IsNullOrEmpty(filePath))
             {
                 filePath = Common.GetSaveFilePath();
             }
 
             if  ( string .IsNullOrEmpty(filePath))  return  null ;
 
             bool  isCompatible = Common.GetIsCompatible(filePath);
 
             IWorkbook workbook = Common.CreateWorkbook(isCompatible);
             ICellStyle headerCellStyle = Common.GetCellStyle(workbook,  true );
             ICellStyle cellStyle = Common.GetCellStyle(workbook);
 
             ISheet sheet = workbook.CreateSheet(sheetName);
             IRow headerRow = sheet.CreateRow(0);
 
             if  (colNames ==  null  || colNames.Length <= 0)
             {
                 colNames = sourceTable.Columns.Cast<DataColumn>().OrderBy(c => c.Ordinal).Select(c => c.ColumnName).ToArray();
             }
 
             // handling header.
             for  ( int  i = 0; i < colNames.Length; i++)
             {
                 ICell headerCell = headerRow.CreateCell(i);
                 if  (colAliasNames !=  null  && colAliasNames.ContainsKey(colNames[i]))
                 {
                     headerCell.SetCellValue(colAliasNames[colNames[i]]);
                 }
                 else
                 {
                     headerCell.SetCellValue(colNames[i]);
                 }
                 headerCell.CellStyle = headerCellStyle;
                 sheet.AutoSizeColumn(headerCell.ColumnIndex);
             }
 
             // handling value.
             int  rowIndex = 1;
 
             foreach  (DataRow row  in  sourceTable.Rows)
             {
                 IRow dataRow = sheet.CreateRow(rowIndex);
 
                 for  ( int  i = 0; i < colNames.Length; i++)
                 {
                     ICell cell = dataRow.CreateCell(i);
                     cell.SetCellValue((row[colNames[i]] ??  "" ).ToString());
                     cell.CellStyle = cellStyle;
                     Common.ReSizeColumnWidth(sheet, cell);
                 }
 
                 rowIndex++;
             }
             FileStream fs =  new  FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
             workbook.Write(fs);
             fs.Dispose();
 
             sheet =  null ;
             headerRow =  null ;
             workbook =  null ;
 
             return  filePath;
         }
 
 
         /// <summary>
         ///由SheetFormatterContainer导出基于EXCEL模板的文件
         /// </summary>
         /// <param name="templatePath">模板路径</param>
         /// <param name="sheetName">模板中使用的工作薄名称</param>
         /// <param name="formatterContainer">模板数据格式化容器</param>
         /// <param name="filePath">导出路径,可选</param>
         /// <returns></returns>
 
         public  static  string  ToExcelWithTemplate<T>( string  templatePath,  string  sheetName, SheetFormatterContainer<T> formatterContainer,  string  filePath =  null )
         {
 
             if  (!File.Exists(templatePath))
             {
                 throw  new  FileNotFoundException(templatePath +  "文件不存在!" );
             }
 
             if  ( string .IsNullOrEmpty(filePath))
             {
                 filePath = Common.GetSaveFilePath();
             }
 
             if  ( string .IsNullOrEmpty(filePath))  return  null ;
 
             string  templateConfigFilePath = Common.GetTemplateConfigFilePath(templatePath,  false );
 
             var  workbookParameterContainer =  new  WorkbookParameterContainer();
             workbookParameterContainer.Load(templateConfigFilePath);
             SheetParameterContainer sheetParameterContainer = workbookParameterContainer[sheetName];
             ExportHelper.ExportToLocal(templatePath, filePath,  new  SheetFormatter(sheetName, formatterContainer.GetFormatters(sheetParameterContainer)));
 
             return  filePath;
         }
 
 
     }
}

  

ExcelUtility.Import类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using  NPOI.SS.UserModel;
using  System;
using  System.Collections.Generic;
using  System.Data;
using  System.IO;
using  System.Linq;
using  System.Text;
using  ExcelUtility.Base;
 
namespace  ExcelUtility
{
     public  sealed  class  Import
     {
         /// <summary>
         /// 由Excel导入DataTable
         /// </summary>
         /// <param name="excelFileStream">Excel文件流</param>
         /// <param name="sheetName">Excel工作表名称</param>
         /// <param name="headerRowIndex">Excel表头行索引</param>
         /// <param name="isCompatible">是否为兼容模式</param>
         /// <returns>DataTable</returns>
         public  static  DataTable ToDataTable(Stream excelFileStream,  string  sheetName,  int  headerRowIndex,  bool  isCompatible)
         {
             IWorkbook workbook = Common.CreateWorkbook(isCompatible, excelFileStream);
             ISheet sheet =  null ;
             int  sheetIndex = -1;
             if  ( int .TryParse(sheetName,  out  sheetIndex))
             {
                 sheet = workbook.GetSheetAt(sheetIndex);
             }
             else
             {
                 sheet = workbook.GetSheet(sheetName);
             }
 
             DataTable table = Common.GetDataTableFromSheet(sheet, headerRowIndex);
 
             excelFileStream.Close();
             workbook =  null ;
             sheet =  null ;
             return  table;
         }
 
         /// <summary>
         /// 由Excel导入DataTable
         /// </summary>
         /// <param name="excelFilePath">Excel文件路径,为物理路径,可传空值</param>
         /// <param name="sheetName">Excel工作表名称</param>
         /// <param name="headerRowIndex">Excel表头行索引</param>
         /// <returns>DataTable</returns>
         public  static  DataTable ToDataTable( string  excelFilePath,  string  sheetName,  int  headerRowIndex)
         {
             if  ( string .IsNullOrEmpty(excelFilePath))
             {
                 excelFilePath = Common.GetOpenFilePath();
             }
 
             if  ( string .IsNullOrEmpty(excelFilePath))
             {
                 return  null ;
             }
 
             using  (FileStream stream = System.IO.File.OpenRead(excelFilePath))
             {
                 bool  isCompatible = Common.GetIsCompatible(excelFilePath);
                 return  ToDataTable(stream, sheetName, headerRowIndex, isCompatible);
             }
         }
 
         /// <summary>
         /// 由Excel导入DataSet,如果有多个工作表,则导入多个DataTable
         /// </summary>
         /// <param name="excelFileStream">Excel文件流</param>
         /// <param name="headerRowIndex">Excel表头行索引</param>
         /// <param name="isCompatible">是否为兼容模式</param>
         /// <returns>DataSet</returns>
         public  static  DataSet ToDataSet(Stream excelFileStream,  int  headerRowIndex,  bool  isCompatible)
         {
             DataSet ds =  new  DataSet();
             IWorkbook workbook = Common.CreateWorkbook(isCompatible, excelFileStream);
             for  ( int  i = 0; i < workbook.NumberOfSheets; i++)
             {
                 ISheet sheet = workbook.GetSheetAt(i);
                 DataTable table = Common.GetDataTableFromSheet(sheet, headerRowIndex);
                 ds.Tables.Add(table);
             }
 
             excelFileStream.Close();
             workbook =  null ;
 
             return  ds;
         }
 
         /// <summary>
         /// 由Excel导入DataSet,如果有多个工作表,则导入多个DataTable
         /// </summary>
         /// <param name="excelFilePath">Excel文件路径,为物理路径。可传空值</param>
         /// <param name="headerRowIndex">Excel表头行索引</param>
         /// <returns>DataSet</returns>
         public  static  DataSet ToDataSet( string  excelFilePath,  int  headerRowIndex)
         {
             if  ( string .IsNullOrEmpty(excelFilePath))
             {
                 excelFilePath = Common.GetOpenFilePath();
             }
 
             if  ( string .IsNullOrEmpty(excelFilePath))
             {
                 return  null ;
             }
 
             using  (FileStream stream = System.IO.File.OpenRead(excelFilePath))
             {
                 bool  isCompatible = Common.GetIsCompatible(excelFilePath);
                 return  ToDataSet(stream, headerRowIndex, isCompatible);
             }
         }
 
     }
}

Common类根据单元格内容重新设置列宽ReSizeColumnWidth

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/// <summary>
/// 根据单元格内容重新设置列宽
/// </summary>
/// <param name="sheet"></param>
/// <param name="cell"></param>
public  static  void  ReSizeColumnWidth(ISheet sheet, ICell cell)
{
     int  cellLength = (Encoding.Default.GetBytes(cell.ToString()).Length + 5) * 256;
     const  int  maxLength = 255 * 256;
     if  (cellLength > maxLength)
     {
         cellLength = maxLength;
     }
     int  colWidth = sheet.GetColumnWidth(cell.ColumnIndex);
     if  (colWidth < cellLength)
     {
         sheet.SetColumnWidth(cell.ColumnIndex, cellLength);
     }
}

注意这个方法中,列宽自动设置最大宽度为255个字符宽度。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/// <summary>
/// 创建表格样式
/// </summary>
/// <param name="sheet"></param>
/// <returns></returns>
public  static  ICellStyle GetCellStyle(IWorkbook workbook,  bool  isHeaderRow =  false )
{
     ICellStyle style = workbook.CreateCellStyle();
 
     if  (isHeaderRow)
     {
         style.FillPattern = FillPattern.SolidForeground;
         style.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index;
         IFont f = workbook.CreateFont();
         f.Boldweight = ( short )FontBoldWeight.Bold;
         style.SetFont(f);
     }
 
     style.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
     style.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
     style.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
     style.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
     return  style;
}

发文时,部份方法代码已经更新了,所以实际效果以GIT项目中的为准。

 该类库源码已分享到该路径中:http://git.oschina.net/zuowj/ExcelUtility    GIT Repository路径:git@git.oschina.net:zuowj/ExcelUtility.git

分类:  C#WinForm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值