首先介绍一下NPOI吧。
NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。
使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写。NPOI是构建在POI 3.x版本之上的,它可以在没有安装Office的情况下对Word/Excel文档进行读写操作。
NPOI的优势:
(一)传统操作Excel遇到的问题:
1、如果是.NET,需要在服务器端装Office,且及时更新它,以防漏洞,还需要设定权限允许.NET访问COM+,如果在导出过程中出问题可能导致服务器宕机。
2、Excel会把只包含数字的列进行类型转换,本来是文本型的,Excel会将其转成数值型的,比如编号000123会变成123。
3、导出时,如果字段内容以“-”或“=”开头,Excel会把它当成公式进行,会报错。
4、Excel会根据Excel文件前8行分析数据类型,如果正好你前8行某一列只是数字,那它会认为该列为数值型,自动将该列转变成类似1.42702E+17格式,日期列变成包含日期和数字的。
(二)使用NPOI的优势
1、你不需要在服务器上安装微软的Office,可以避免版权问题。
2、使用起来比Office PIA的API更加方便,更人性化。
3、你不用去花大力气维护NPOI,NPOI Team会不断更新、改善NPOI,绝对省成本。
基于office导出到Excel实现:
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
|
public static void ExportExcel( string fileName, DataGridView myDGV, bool isShowDialog) { string saveFileName = "" ; if (isShowDialog) { //bool fileSaved = false; SaveFileDialog saveDialog = new SaveFileDialog(); saveDialog.DefaultExt = "xls" ; saveDialog.Filter = "Excel文件|*.xls" ; saveDialog.FileName = fileName; saveDialog.ShowDialog(); saveFileName = saveDialog.FileName; if (saveFileName.IndexOf( ":" ) < 0) return ; //被点了取消 } else { // saveFileName = Application.StartupPath + @"\导出记录\" + fileName + ".xls"; saveFileName = fileName; } Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application(); if (xlApp == null ) { MessageBox.Show( "无法创建Excel对象,可能您的机子未安装Excel" ); return ; } Microsoft.Office.Interop.Excel.Workbooks workbooks = xlApp.Workbooks; Microsoft.Office.Interop.Excel.Workbook workbook = workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet); Microsoft.Office.Interop.Excel.Worksheet worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Worksheets[1]; //取得sheet1 //写入标题 for ( int i = 0; i < myDGV.ColumnCount; i++) { worksheet.Cells[1, i + 1] = myDGV.Columns[i].HeaderText; } //写入数值 for ( int r = 0; r < myDGV.Rows.Count; r++) { for ( int i = 0; i < myDGV.ColumnCount; i++) { if (myDGV[i, r].ValueType == typeof ( string ) || myDGV[i, r].ValueType == typeof (DateTime)) //这里就是验证DataGridView单元格中的类型,如果是string或是DataTime类型,则在放入缓 存时在该内容前加入" "; { worksheet.Cells[r + 2, i + 1] = "'" + myDGV.Rows[r].Cells[i].Value; } else { worksheet.Cells[r + 2, i + 1] = myDGV.Rows[r].Cells[i].Value; } } System.Windows.Forms.Application.DoEvents(); } worksheet.Columns.EntireColumn.AutoFit(); //列宽自适应 //if (Microsoft.Office.Interop.cmbxType.Text != "Notification") //{ // Excel.Range rg = worksheet.get_Range(worksheet.Cells[2, 2], worksheet.Cells[ds.Tables[0].Rows.Count + 1, 2]); // rg.NumberFormat = "00000000"; //} if (saveFileName != "" ) { try { workbook.Saved = true ; workbook.SaveCopyAs(saveFileName); //fileSaved = true; } catch (Exception ex) { //fileSaved = false; MessageBox.Show( "导出文件时出错,文件可能正被打开!\n" + ex.Message); } } //else //{ // fileSaved = false; //} xlApp.Quit(); GC.Collect(); //强行销毁 // if (fileSaved && System.IO.File.Exists(saveFileName)) System.Diagnostics.Process.Start(saveFileName); //打开EXCEL MessageBox.Show(fileName + "保存成功" , "提示" , MessageBoxButtons.OK); } |
NPOI导出到Excel表实现:
/// <summary> /// NPOI导出Excel,不依赖本地是否装有Excel,导出速度快 /// </summary> /// <param name="dataGridView1">要导出的dataGridView控件</param> /// <param name="sheetName">sheet表名</param> public static void ExportToExcel(DataGridView dataGridView1, string sheetName) { SaveFileDialog fileDialog = new SaveFileDialog(); fileDialog.Filter = "Excel|*.xls" ; if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) { return ; } //不允许dataGridView显示添加行,负责导出时会报最后一行未实例化错误 dataGridView1.AllowUserToAddRows = false ; HSSFWorkbook workbook = new HSSFWorkbook(); ISheet sheet = workbook.CreateSheet(sheetName); IRow rowHead = sheet.CreateRow(0); //填写表头 for ( int i = 0; i < dataGridView1.Columns.Count; i++) { rowHead.CreateCell(i, CellType.STRING).SetCellValue(dataGridView1.Columns[i].HeaderText.ToString()); } //填写内容 for ( int i = 0; i < dataGridView1.Rows.Count; i++) { IRow row = sheet.CreateRow(i + 1); for ( int j = 0; j < dataGridView1.Columns.Count; j++) { row.CreateCell(j, CellType.STRING).SetCellValue(dataGridView1.Rows[i].Cells[j].Value.ToString()); } } using (FileStream stream = File.OpenWrite(fileDialog.FileName)) { workbook.Write(stream); stream.Close(); } MessageBox.Show( "导出数据成功!" , "提示" , MessageBoxButtons.OK, MessageBoxIcon.Information); GC.Collect(); } |
经过比较:如果导出50000条int类型的数据,基于office导出需要10分钟左右的时间,NPOI导出则需要3秒钟左右的时间。
NPOI导出时间截图如下:
基于office导出时间截图如下: