C#操作Excel方法有很多,以前用的需要电脑安装office才能用,但因为版权问题公司不允许安装office。所以改用NPOI进行Excel操作,基本上一些简单的Excel操作都没有问题,读写合并单元格等都能实现。
命名空间:
using NPOI; using NPOI.XSSF.UserModel; using NPOI.SS.UserModel; using NPOI.HSSF.UserModel; using NPOI.HSSF.Util;
简单的保存数据:
public void ExcelTest(string path) { IWorkbook workbook = new HSSFWorkbook();//创建Workbook workbook.CreateSheet("sheet1");//创建sheet using (FileStream fs = File.Create(path))//path=mmm.xls; { ISheet sheet = workbook.GetSheetAt(0);//获取sheet sheet.CreateRow(1).CreateCell(0).SetCellValue("nami");//创建第一行/创建第一单元格/设置第一单元格的内容[可以分开创建,但必须先创建行才能创建单元格不然报错] sheet.GetRow(1).CreateCell(1).SetCellValue("robin");//获取第一行/创建第二单元格/设置第二单元格的内容 sheet.CreateRow(2).CreateCell(0).SetCellValue("saber");//创建第二行/创建第一单元格/设置第一单元格的内容 sheet.GetRow(2).CreateCell(1).SetCellValue("luffy");//获取第二行/创建第二单元格/设置第二单元格的内容 sheet.GetRow(1).CreateCell(2).SetCellValue(5); sheet.GetRow(2).CreateCell(2).SetCellValue(2); //添加批注 IDrawing draw = sheet.CreateDrawingPatriarch(); IComment comment = draw.CreateCellComment(new HSSFClientAnchor(0, 0, 0, 0, 1, 2, 4, 4));//里面参数应该是指示批注的位置大小吧 comment.String = new HSSFRichTextString("one-piece");//添加批注内容 comment.Author = "梦琪小生";//添加批注作者 sheet.GetRow(1).GetCell(1).CellComment = comment;//将之前设置的批注给定某个单元格 //单元格格式设置 ICellStyle cellStyle = workbook.CreateCellStyle(); IDataFormat format = workbook.CreateDataFormat(); cellStyle.DataFormat = format.GetFormat("0.00"); sheet.GetRow(2).GetCell(2).CellStyle = cellStyle; //合并单元格 sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, 2)); sheet.CreateRow(0).CreateCell(0).SetCellValue("梦琪小生"); ICellStyle titleStyle = workbook.CreateCellStyle(); IFont titleFont = workbook.CreateFont(); titleFont.FontHeightInPoints = 15;//设置字体大小 titleFont.Color = HSSFColor.BLUE.index;//设置字体颜色 titleStyle.SetFont(titleFont); titleStyle.Alignment = HorizontalAlignment.CENTER;//居中 sheet.GetRow(0).GetCell(0).CellStyle = titleStyle; ICellStyle style = workbook.CreateCellStyle(); style.BorderBottom = BorderStyle.THIN; style.BorderLeft = BorderStyle.THIN; style.BorderRight = BorderStyle.THIN; style.BorderTop = BorderStyle.THIN; sheet.GetRow(1).GetCell(1).CellStyle = style; //插入图片 HSSFClientAnchor anchor2 = new HSSFClientAnchor(0, 0, 0, 0, 0, 5, 6, 10); byte[] bytes = System.IO.File.ReadAllBytes(@"C:UsersAdministratorDesktopimagemqxs.png"); int picID = workbook.AddPicture(bytes, PictureType.PNG); IPicture pic = patriarch.CreatePicture(anchor2, picID); pic.Resize(); workbook.Write(fs);//保存文件 } }
读取Excel返回DataTable:
/// <summary> /// 读取Excel[.xls](返回DataTable) /// </summary> /// <param name="path">Excel路径</param> /// <returns></returns> public static DataTable ReadExcel(string path) { try { DataTable dt = new DataTable(); using (FileStream fs = new FileStream(path, FileMode.Open)) { IWorkbook workbook = new HSSFWorkbook(fs); ISheet sheet = workbook.GetSheetAt(0); int rfirst = sheet.FirstRowNum; int rlast = sheet.LastRowNum; IRow row = sheet.GetRow(rfirst); int cfirst = row.FirstCellNum; int clast = row.LastCellNum; for (int i = cfirst; i < clast; i++) { if (row.GetCell(i) != null) dt.Columns.Add(row.GetCell(i).StringCellValue, System.Type.GetType("System.String")); } row = null; for (int i = rfirst + 1; i <= rlast; i++) { DataRow r = dt.NewRow(); IRow ir = sheet.GetRow(i); for (int j = cfirst; j < clast; j++) { if (ir.GetCell(j) != null) { r[j] = ir.GetCell(j).ToString(); } } dt.Rows.Add(r); ir = null; r = null; } sheet = null; workbook = null; } return dt; } catch { System.Windows.Forms.MessageBox.Show("Excel格式错误或者Excel正由另一进程在访问"); return null; } }
Ok,NPOI也用了一段时间了....
讲一点经验之谈...关于NPOI的单元格样式CellStyles个数是有限制的4000个,所以大家设置单元格样式的时候尽量不要再for循环里面定义,可以在for循环外围定义好使用...减少CellStyles个数,Ok,主要要讲的是下面的那一条....
((HSSFSheet)sheet).SetEnclosedBorderOfRegion(new NPOI.SS.Util.CellRangeAddress(0, 50, 0, 100), BorderStyle.MEDIUM, HSSFColor.BLACK.index);
这句的功能是给合并后的单元格加外边框。
比如这条语句的意思是将单元格0行0列到50行100列绘制一个整体的外边框。用到是很好用...但是很占资源,不知道为什么就这么一句话会占好几个CellStyles...而且速度较慢....
所以这个功能在数据量小的可以用,问题不大,速度基本影响也不大,但数据量一大...这个相对就会拖累速度了又太占资源.
小生我就在这边吃过亏,就是这条语句导致CellStyles个数不够用[当然不是一句就会有问题咯....因为很多地方合并单元格然后加外边框...最终就悲剧了....]....小生觉得这是NPOI的缺陷...
NPOI操作Excel使用说明:
官网教程相当详细,需进一步学习的请移步至官网学习 http://tonyqus.sinaapp.com/npoi2tutorial
2017/05/05补充:
C# Color转NPOI颜色:
/// <summary> /// 获取颜色值 /// </summary> /// <param name="color">颜色RGB</param> /// <param name="workbook">Excel画布</param> /// <returns></returns> public static short GetColorIndex(this HSSFWorkbook workbook,Color color) { HSSFPalette palette = workbook.GetCustomPalette(); var v = palette.FindSimilarColor(color.R, color.G, color.B); if (v == null) { throw new Exception("Color is not in Palette"); } else return v.GetIndex(); }
2018/4/8补充:
获取合并单元格
/// <summary> /// 获取当前单元格所在的合并单元格的位置 /// </summary> /// <param name="sheet">sheet表单</param> /// <param name="rowIndex">行索引 0开始</param> /// <param name="colIndex">列索引 0开始</param> /// <param name="start">合并单元格左上角坐标</param> /// <param name="end">合并单元格右下角坐标</param> /// <returns>返回false表示非合并单元格</returns> private static bool IsMergeCell(ISheet sheet, int rowIndex, int colIndex, out Point start, out Point end) { bool result = false; start = new Point(0, 0); end = new Point(0, 0); if ((rowIndex < 0) || (colIndex < 0)) return result; int regionsCount = sheet.NumMergedRegions; for (int i = 0; i < regionsCount; i++) { CellRangeAddress range = sheet.GetMergedRegion(i); //sheet.IsMergedRegion(range); if (rowIndex >= range.FirstRow && rowIndex <= range.LastRow && colIndex >= range.FirstColumn && colIndex <= range.LastColumn) { start = new Point(range.FirstRow, range.FirstColumn); end = new Point(range.LastRow, range.LastColumn); result = true; break; } } return result; }
扫码关注微信公众号