一、概述
NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目, 使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写。
完整教程:https://www.cnblogs.com/atao/archive/2009/11/15/1603528.html
1、操作Excel的类库:
- NPOI: V2.5.1 快速生成 https://github.com/tonyqus/npoi
- MyXls: (已停止)
- Aspose.Cell.dll: 收费
- EPPlus 5: https://github.com/EPPlusSoftware/
- Spire.XLS: 收费
3、引用DLL
使用时需引用需要引用所有5个dll
- ICSharpCode.SharpZipLib.dll
- NPOI.dll
- NPOI.OOXML.dll
- NPOI.OpenXml4Net.dll
- NPOI.OpenXmlFormats.dll
程序集构成
二、通过NPOI,将Excel文件导到数据表DataTable
DataTable dt = ImportToTable("00.xls"); if (dt != null) { Console.Write(dt.Rows.Count); Console.ReadKey(); }
public static DataTable ImportToTable(string fileName) { DataTable dt = new DataTable(); IWorkbook workbook; string fileExt = Path.GetExtension(fileName).ToLower(); using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { //XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式 if (fileExt == ".xlsx") { workbook = new XSSFWorkbook(fs); } else if (fileExt == ".xls") { workbook = new HSSFWorkbook(fs); } else { workbook = null; return null; } ISheet sheet = workbook.GetSheetAt(0);//Sheet总数量:workbook.NumberOfSheets //表头 IRow header = sheet.GetRow(sheet.FirstRowNum); for (int i = 0; i < header.LastCellNum; i++) { object obj = GetValueType(header.GetCell(i)); if (obj == null || obj.ToString() == string.Empty) { dt.Columns.Add(new DataColumn("Columns" + i.ToString())); } else dt.Columns.Add(new DataColumn(obj.ToString())); } //数据 for (int i = sheet.FirstRowNum + 1; i <= sheet.LastRowNum; i++) { DataRow dr = dt.NewRow(); bool hasValue = false; IRow row = sheet.GetRow(i); for (int j = row.FirstCellNum; j < row.LastCellNum; j++) { dr[j] = GetValueType(sheet.GetRow(i).GetCell(j)); if (dr[j] != null && dr[j].ToString() != string.Empty) { hasValue = true; } } if (hasValue) { dt.Rows.Add(dr); } } return dt; } } /// <summary> /// 获取单元格类型 /// </summary> /// <param name="cell"></param> /// <returns></returns> /// static object GetValueType(ICell cell) { if (cell == null) return null; switch (cell.CellType) { case CellType.Blank: //BLANK: return null; case CellType.Boolean: //BOOLEAN: return cell.BooleanCellValue; case CellType.Numeric: //NUMERIC: return cell.NumericCellValue; case CellType.String: //STRING: return cell.StringCellValue; case CellType.Error: //ERROR: return cell.ErrorCellValue; case CellType.Formula: //FORMULA: default: return "=" + cell.CellFormula; } } }
四、常见用法:
1、查找
IEnumerator rows = sheet.GetEnumerator(); while (rows.MoveNext()) { IRow row = (HSSFRow)rows.Current; ICell cell = row.GetCell(0); if (cell != null && cell.StringCellValue == "XX") { return row.GetCell(1).StringCellValue; } }
2、插入图片
IWorkbook workbook = new HSSFWorkbook(); //add picture data to this workbook. byte[] bytes = System.IO.File.ReadAllBytes(@"00.jpg"); int pictureIdx = workbook.AddPicture(bytes, PictureType.JPEG); //create sheet ISheet sheet = workbook.CreateSheet("Sheet1"); // Create the drawing patriarch. This is the top level container for all shapes. IDrawing patriarch = sheet.CreateDrawingPatriarch(); //add a picture HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 0, 0, 0, 1, 3); IPicture pict = patriarch.CreatePicture(anchor, pictureIdx); //保存为Excel文件 using (FileStream fs = new FileStream("00_new.xls", FileMode.Create, FileAccess.Write)) { workbook.Write(fs); }
五、填充Excel模板
IWorkbook workbook; using (FileStream fs = new FileStream("模板文件.xls", FileMode.Open, FileAccess.Read)) { workbook = new HSSFWorkbook(fs); } ISheet cloneSheet = workbook.CloneSheet(workbook.GetSheetIndex("Sheet1"));//复制第一个模板Sheet cloneSheet.ForceFormulaRecalculation = true; workbook.SetSheetName(workbook.GetSheetIndex(cloneSheet), "SheetClone");//设置新SheetName
cloneSheet.GetRow(4).GetCell(1).SetCellValue("a");//为已经存在的单元格赋值
IRow row = cloneSheet.GetRow(15); if (row == null) row = cloneSheet.CreateRow(15); ICell cell = row.GetCell(7); if (cell == null) cell = row.CreateCell(7); cell.SetCellValue("XX");// 为不存在的单元格,先新建再赋值
cloneSheet.ShiftRows(51, 60, 34);//51-60行(尾部)整体移动34行,腾出更多控件插入多行数据 workbook.RemoveSheetAt(workbook.GetSheetIndex("Sheet1"));//移除原模板Sheet FileStream fs_new = new FileStream(DateTime.Now.Ticks + ".xls", FileMode.Create); workbook.Write(fs_new); fs_new.Close();
六、DataTable导出到Excel文件
1、直接导出到Excel:
调用方式:
ExportToExcel(dt, "00_new.xls");
代码
public static void ExportToExcel(DataTable dt, string fileName) { IWorkbook workbook; string fileExt = Path.GetExtension(fileName).ToLower();
//XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式 if (fileExt == ".xlsx") { workbook = new XSSFWorkbook(); } else if (fileExt == ".xls") { workbook = new HSSFWorkbook(); } else { workbook = null; return; } ISheet sheet = string.IsNullOrEmpty(dt.TableName) ? workbook.CreateSheet("Sheet1") : workbook.CreateSheet(dt.TableName); //表头 IRow row = sheet.CreateRow(0); for (int i = 0; i < dt.Columns.Count; i++) { ICell cell = row.CreateCell(i); cell.SetCellValue(dt.Columns[i].ColumnName); } //数据 for (int i = 0; i < dt.Rows.Count; i++) { IRow row1 = sheet.CreateRow(i + 1); for (int j = 0; j < dt.Columns.Count; j++) { ICell cell = row1.CreateCell(j); cell.SetCellValue(dt.Rows[i][j].ToString()); } } //保存为Excel文件 using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } }
2、将DataTable导出到Excel:先导出到MemoryStream
public static MemoryStream ExportToExcel(DataTable dt, string HeaderText) { var workbook = new HSSFWorkbook(); ISheet sheet = workbook.CreateSheet(string.IsNullOrWhiteSpace(dt.TableName) ? "Sheet1" : dt.TableName); //右击文件“属性”信息 #region 文件属性信息 { var dsi = PropertySetFactory.CreateDocumentSummaryInformation(); dsi.Company = "NPOI"; workbook.DocumentSummaryInformation = dsi; SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); si.Author = "文件作者信息"; si.ApplicationName = "创建程序信息"; si.LastAuthor = "最后保存者信息"; si.Comments = "作者信息"; si.Title = "标题信息"; si.Subject = "主题信息"; si.CreateDateTime = DateTime.Now; workbook.SummaryInformation = si; } #endregion //格式 var dateStyle = workbook.CreateCellStyle(); var format = workbook.CreateDataFormat(); dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd");//日期格式 //取得列宽 var arrColWidth = new int[dt.Columns.Count]; foreach (DataColumn item in dt.Columns) { arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length; } for (var i = 0; i < dt.Rows.Count; i++) { for (var j = 0; j < dt.Columns.Count; j++) { int intTemp = Encoding.GetEncoding(936).GetBytes(dt.Rows[i][j].ToString()).Length; if (intTemp > arrColWidth[j]) { arrColWidth[j] = intTemp; } } } int rowIndex = 0; foreach (DataRow row in dt.Rows) { #region 表头 列头 if (rowIndex == 65535 || rowIndex == 0) { if (rowIndex != 0) { sheet = workbook.CreateSheet();//超过65535行,则新建一个Sheet } #region 表头及样式 { var headerRow = sheet.CreateRow(0); headerRow.HeightInPoints = 25; headerRow.CreateCell(0).SetCellValue(HeaderText); //CellStyle ICellStyle headStyle = workbook.CreateCellStyle(); headStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;// 左右居中 headStyle.VerticalAlignment = VerticalAlignment.Center;// 上下居中 // 设置单元格的背景颜色(单元格的样式会覆盖列或行的样式) headStyle.FillForegroundColor = (short)11; //定义font IFont font = workbook.CreateFont(); font.FontHeightInPoints = 20; font.Boldweight = 700; headStyle.SetFont(font); headerRow.GetCell(0).CellStyle = headStyle; sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dt.Columns.Count - 1));//合并区域 } #endregion #region 列头及样式 { var headerRow = sheet.CreateRow(1); //CellStyle ICellStyle headStyle = workbook.CreateCellStyle(); headStyle.Alignment = NPOI.SS.UserModel.HorizontalAlignment.Center;// 左右居中 headStyle.VerticalAlignment = VerticalAlignment.Center;// 上下居中 //定义font IFont font = workbook.CreateFont(); font.FontHeightInPoints = 10; font.Boldweight = 700; headStyle.SetFont(font); foreach (DataColumn column in dt.Columns) { headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); headerRow.GetCell(column.Ordinal).CellStyle = headStyle; sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256);//设置列宽 } } #endregion rowIndex = 2;//数据行RowIndex为2(表头和列头个占一行) } #endregion #region 内容 var dataRow = sheet.CreateRow(rowIndex); foreach (DataColumn column in dt.Columns) { var newCell = dataRow.CreateCell(column.Ordinal); string drValue = row[column].ToString(); switch (column.DataType.ToString()) { case "System.String"://字符串类型 newCell.SetCellValue(drValue); break; case "System.DateTime"://日期类型 DateTime dateV; DateTime.TryParse(drValue, out dateV); newCell.SetCellValue(dateV); newCell.CellStyle = dateStyle;//格式化显示 break; case "System.Boolean"://布尔型 bool boolV = false; bool.TryParse(drValue, out boolV); newCell.SetCellValue(boolV); break; case "System.Int16"://整型 case "System.Int32": case "System.Int64": case "System.Byte": int intV = 0; int.TryParse(drValue, out intV); newCell.SetCellValue(intV); break; case "System.Decimal"://浮点型 case "System.Double": double doubV = 0; double.TryParse(drValue, out doubV); newCell.SetCellValue(doubV); break; case "System.DBNull"://空值处理 newCell.SetCellValue(""); break; default: newCell.SetCellValue("");//设置单元格公式:newCell.SetCellFormula("SUM($B0:$D0)") break; } } #endregion rowIndex++; } //自动列宽 for (int i = 0; i <= dt.Columns.Count; i++) sheet.AutoSizeColumn(i, true); using (MemoryStream ms = new MemoryStream()) { workbook.Write(ms); ms.Flush(); ms.Position = 0; return ms; } }
3、应用
1、Web导出
public static void ExportToExcelByWeb(DataTable dt, string HeaderText, string FileName) { HttpContext context = HttpContext.Current; context.Response.ContentType = "application/vnd.ms-excel"; context.Response.ContentEncoding = Encoding.UTF8; context.Response.Charset = "UTF-8"; context.Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", HttpUtility.UrlEncode(FileName, Encoding.UTF8))); byte[] data = ExportToExcel(dt, HeaderText).GetBuffer();//Read()方法也可以 context.Response.BinaryWrite(data);// 或者: context.Response.OutputStream.Write(data,0,data.Length) context.Response.End(); }
2、Winform导出
public static void ExportToExcel(DataTable dt, string HeaderText, string FileName) { using (MemoryStream ms = ExportToExcel(dt, HeaderText)) { using (FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.Write)) { byte[] data = ms.ToArray();//跟GetBuffer()对比,速度稍慢,但无空数据 fs.Write(data, 0, data.Length); fs.Flush(); } } }
GridView导出到Excel
Web中的GridView可直接导出到Excel:renderControl()