Npoi 操作excel
using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp { /// <summary> /// NPOIExcel 针对2.5.1.0出的NPOI操作Excel类的常用方法; /// </summary> public class NPOIHelper { /// <summary> /// 记录打开的Excel的路径 /// </summary> private string npoiFileName; /// <summary> /// 工作簿,全局变量 /// </summary> protected IWorkbook workbook; /// <summary> /// 获取工作表或是创建的 /// </summary> private NPOI.SS.UserModel.ISheet sheet; /// <summary> /// 构造方法 /// </summary> public NPOIHelper() { npoiFileName = ""; workbook = new XSSFWorkbook(); } /// <summary> /// 打开 /// </summary> /// <param name="filename">excel文件路径</param> public void Open(string filename) { using (FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read)) { string ext = Path.GetExtension(filename).ToLower(); if (ext == ".xlsx") workbook = new XSSFWorkbook(fileStream); else { workbook = new HSSFWorkbook(fileStream); } } npoiFileName = filename; } /// <summary> /// 创建一个Excel对象,该对象为可见的 /// </summary> public void Create(string sheetname = "Sheet1") { sheet = workbook.CreateSheet(sheetname); } /// <summary> /// 获取一个工作表 /// </summary> /// <param name="SheetName">工作表名称</param> /// <returns></returns> public ISheet GetSheet(string SheetName) { return (sheet = workbook.GetSheet(SheetName) ?? workbook.CreateSheet(SheetName)); } /// <summary> /// 添加一个工作表 /// </summary> /// <param name="SheetName">工作表名称</param> /// <returns></returns> public ISheet AddSheet(string SheetName) { ISheet s = workbook.CreateSheet(SheetName); return s; } /// <summary> /// 删除一个工作表 /// </summary> /// <param name="SheetName">工作表名称</param> public void DelSheet(string SheetName) { int index = workbook.GetNameIndex(SheetName); workbook.RemoveSheetAt(index); } /// <summary> /// 重命名一个工作表 /// </summary> /// <param name="OldSheetName">老工作表名称</param> /// <param name="NewSheetName">新工作表名称</param> /// <returns></returns> public ISheet ReNameSheet(string OldSheetName, string NewSheetName) { int index = workbook.GetNameIndex(OldSheetName); workbook.SetSheetName(index, NewSheetName); return workbook.GetSheetAt(index); } /// <summary> /// 设置单元格的值 /// </summary> /// <param name="sheetName">工作表名称</param> /// <param name="row">行</param> /// <param name="col">列</param> /// <param name="value">设置的值</param> private void SetCellValue(ISheet sheetName, int row, int col, object value) { IRow _row = sheetName.GetRow(row) ?? sheetName.CreateRow(row); ICell cell = _row.GetCell(col) ?? _row.CreateCell(col); string valuetype = value.GetType().Name.ToLower(); switch (valuetype) { case "string"://字符串类型 case "system.string": case "datetime": case "system.datetime"://日期类型 case "boolean"://布尔型 case "system.boolean"://布尔型 cell.SetCellType(CellType.String); cell.SetCellValue(value.ToString()); break; case "byte": case "int": case "int16": case "int32": case "int64": case "system.int16"://整型 case "system.int32": case "system.int64": case "system.byte": cell.SetCellType(CellType.Numeric); cell.SetCellValue(Convert.ToInt32(value)); break; case "single": case "system.single": case "double": case "system.double": case "decimal": case "system.decimal": cell.SetCellType(CellType.Numeric); cell.SetCellValue(Convert.ToDouble(value)); break; case "dbnull"://空值处理 case "system.dbnull"://空值处理 cell.SetCellValue(""); break; default: cell.SetCellValue(value.ToString()); break; } } /// <summary> /// 要设值的工作表的名称 X行Y列 value 值 /// </summary> /// <param name="sheetName">工作表名</param> /// <param name="row">行</param> /// <param name="col">列</param> /// <param name="value">插入的值</param> public void SetCellValue(string sheetName, int row, int col, object value) { ISheet s = GetSheet(sheetName); SetCellValue(s, row, col, value); } /// <summary> /// 获取单元格值 /// </summary> /// <param name="sheetName">工作表名</param> /// <param name="row">行</param> /// <param name="col">列</param> /// <returns></returns> public ICell GetCell(string sheetName, int row, int col) { return GetSheet(sheetName).GetRow(row).Cells[col]; } /// <summary> /// 获取单元格值 /// </summary> /// <param name="sheetName">工作表名</param> /// <param name="row">行</param> /// <param name="col">列</param> /// <returns></returns> private ICell GetCell(ISheet sheetName, int row, int col) { //return ws.GetRow(row).Cells[col]; return sheetName.GetRow(row).GetCell(col); } /// <summary> /// 获取当前sheet的所有有数据的单元格 /// </summary> /// <param name="sheetName"></param> /// <returns></returns> public List<ICell> GetHasValueCell(string sheetName) { List<ICell> values = new List<ICell>(); var sheet = GetSheet(sheetName); int maxRow = sheet.LastRowNum + 1; int maxCol = MaxCellIndex(sheetName); for (int row = 0; row < maxRow; row++) { for (int col = 0; col < maxCol; col++) { try { //这一行查不到值的话会报错 ICell cell = sheet.GetRow(row)?.GetCell(col); if (cell != null) values.Add(cell); } catch (Exception) { } } } return values; } /// <summary> /// 得到最大有效数据行索引 /// </summary> /// <param name="sheetName"></param> /// <returns></returns> public int MaxRowIndex(string sheetName) { var sheet = GetSheet(sheetName); return sheet.LastRowNum; } /// <summary> /// 得到最大有效数据列从1开始 /// </summary> /// <param name="sheetName"></param> /// <returns></returns> public int MaxCellIndex(string sheetName) { int maxCellIndex = -1; var sheet = GetSheet(sheetName); for (int rowCnt = sheet.FirstRowNum; rowCnt <= sheet.LastRowNum; rowCnt++)//迭代所有行 { IRow row = sheet.GetRow(rowCnt); if (row != null && row.LastCellNum > maxCellIndex) { maxCellIndex = row.LastCellNum; } } return maxCellIndex; } /// <summary> /// 得到最大行和最大列的索引行从0开始列从0开始 /// </summary> /// <param name="sheetName"></param> /// <returns></returns> public (int, int) GetMaxRowIndexAndCellIndex(string sheetName) { return (MaxRowIndex(sheetName), MaxCellIndex(sheetName) - 1); } /// <summary> /// 得到最大行和最大列的索引,行从0开始列从1开始 /// </summary> /// <param name="sheetName"></param> /// <returns></returns> public (int, int) GetMaxRowIndexAndCell(string sheetName) { return (MaxRowIndex(sheetName), MaxCellIndex(sheetName)); } /// <summary> /// 清除某行的值和样式 /// </summary> /// <param name="sheetName"></param> /// <param name="rowIndex"></param> public void ClearRowValue(string sheetName, int rowIndex) { var sheet = GetSheet(sheetName); if (sheet == null) return; IRow row = sheet.GetRow(rowIndex); if (row == null) return; for (int i = 0; i < row.LastCellNum; i++) { try { ICell cell = row.GetCell(i); cell.CellStyle = null; cell.SetCellValue(string.Empty); } catch (Exception) { } } } /// <summary> /// 获取起止范围内的行列值 /// </summary> /// <param name="sheetName"></param> /// <param name="startRow"></param> /// <param name="startCol"></param> /// <param name="endRow"></param> /// <param name="endCol"></param> /// <returns></returns> public IList<ICell> GetCellsOfRange(string sheetName, int startRow, int startCol, int endRow, int endCol) { return (GetCellsOfRange(GetSheet(sheetName), startRow, startCol, endRow, endCol)); } /// <summary> /// 获取起止范围内的行列值 /// </summary> /// <param name="sheetName"></param> /// <param name="startRow"></param> /// <param name="startCol"></param> /// <param name="endRow"></param> /// <param name="endCol"></param> /// <returns></returns> private IList<ICell> GetCellsOfRange(ISheet sheetName, int startRow, int startCol, int endRow, int endCol) { IList<ICell> allCell = new List<ICell>(); for (int i = startRow; i <= endRow; i++) for (int j = startCol; j <= endCol; j++) { allCell.Add(GetCell(sheetName, i, j)); } return allCell; } /// <summary> /// 合并单元格 /// </summary> /// <param name="sheetName"></param> /// <param name="startRow"></param> /// <param name="endRow"></param> /// <param name="startCol"></param> /// <param name="endCol"></param> private void MergedCells(ISheet sheetName, int startRow, int endRow, int startCol, int endCol) { //CellRangeAddress四个参数为:起始行,结束行,起始列,结束列 var region = new CellRangeAddress(startRow, endRow, startCol, endCol); sheetName.AddMergedRegion(region); } /// <summary> /// 合并单元格 /// </summary> /// <param name="sheetName"></param> /// <param name="startRow"></param> /// <param name="startCol"></param> /// <param name="endRow"></param> /// <param name="endCol"></param> public void MergedCells(string sheetName, int startRow, int startCol, int endRow, int endCol) { MergedCells(GetSheet(sheetName), startRow, endRow, startCol, endCol); } /// <summary> /// 文档另存为 /// </summary> /// <param name="FileName"></param> /// <returns></returns> public bool SaveAs(string FileName) { npoiFileName = FileName; try { using (FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.Write)) { workbook.Write(fs); } return true; } catch { return false; } } /// <summary> /// 关闭 /// </summary> public void Close() { workbook.Close(); } /// <summary> /// 自适应宽度 /// </summary> /// <param name="sheetName">表名</param> /// <param name="startCol">起始列</param> /// <param name="endCol">结束列</param> public void AutoColumnWidth(string sheetName, int startCol, int endCol) { AutoColumnWidth(GetSheet(sheetName), startCol, endCol); } /// <summary> /// 自适应宽度 /// </summary> /// <param name="sheet"></param> /// <param name="cols"></param> private void AutoColumnWidth(ISheet sheet, int startCol, int endCol) { for (int col = startCol; col <= endCol; col++) { sheet.AutoSizeColumn(col);//但是其实还是比实际文本要宽 } } /// <summary> /// 设置起止范围的行高,单位为磅 /// </summary> /// <param name="sheetName">工作表名称</param> /// <param name="startRow">起始行</param> /// <param name="endRow">结束行</param> /// <param name="heightValue">设置的高值</param> public void SetRowsHeight(string sheetName, int startRow, int endRow, int heightValue) { ISheet sheet = GetSheet(sheetName); for (int i = startRow; i <= endRow; i++) { //sheet.GetRow(i).Height = Height * 20; sheet.GetRow(i).HeightInPoints = heightValue; } } /// <summary> /// 设置起止列的宽度,单位为字符 /// </summary> /// <param name="sheetName">工作表名称</param> /// <param name="startCol">起始列</param> /// <param name="endCol">结束列</param> /// <param name="widthValue">设置的宽度值</param> public void SetColumnsWidth(string sheetName, int startCol, int endCol, int widthValue) { ISheet sheet = GetSheet(sheetName); for (int j = startCol; j <= endCol; j++) { sheet.SetColumnWidth(j, widthValue * 256); } } /// <summary> /// 插入新行 /// </summary> /// <param name="sheetName">工作表名</param> /// <param name="insertRowIndex">插入的行索引位置</param> /// <param name="insertRowCount">插入的行数量</param> /// <param name="formatRowIndex">获取插入行的参照样式的行索引</param> public void InsertRow(string sheetName, int insertRowIndex, int insertRowCount, int formatRowIndex) { ISheet sheet = GetSheet(sheetName); IRow formatRow = sheet.GetRow(formatRowIndex); InsertRow(sheet, insertRowIndex, insertRowCount, formatRow); } /// <summary> /// 插入新行 /// </summary> /// <param name="sheetName"></param> /// <param name="insertRowIndex"></param> /// <param name="insertRowCount"></param> /// <param name="formatRow"></param> private void InsertRow(ISheet sheetName, int insertRowIndex, int insertRowCount, IRow formatRow) { sheet.ShiftRows(insertRowIndex, sheet.LastRowNum, insertRowCount, true, false); for (int i = insertRowIndex; i < insertRowIndex + insertRowCount; i++) { IRow targetRow = null; ICell sourceCell = null; ICell targetCell = null; targetRow = sheet.CreateRow(i); for (int m = formatRow.FirstCellNum; m < formatRow.LastCellNum; m++) { sourceCell = formatRow.GetCell(m); if (sourceCell == null) { continue; } targetCell = targetRow.CreateCell(m); targetCell.CellStyle = sourceCell.CellStyle; targetCell.SetCellType(sourceCell.CellType); } } for (int i = insertRowIndex; i < insertRowIndex + insertRowCount; i++) { IRow firstTargetRow = sheet.GetRow(i); ICell firstSourceCell = null; ICell firstTargetCell = null; for (int m = formatRow.FirstCellNum; m < formatRow.LastCellNum; m++) { firstSourceCell = formatRow.GetCell(m, MissingCellPolicy.CREATE_NULL_AS_BLANK); if (firstSourceCell == null) { continue; } firstTargetCell = firstTargetRow.GetCell(m, MissingCellPolicy.CREATE_NULL_AS_BLANK); firstTargetCell.CellStyle = firstSourceCell.CellStyle; firstTargetCell.SetCellType(firstSourceCell.CellType); } } } //--------------------------------------------------------------------新增的方法------------------------------------- #region 自定义样式 /// <summary> /// 自定义样式 /// </summary> /// <param name="fontSize"></param> /// <param name="fontName"></param> /// <param name="horizontalAlignment"></param> /// <param name="verticalAlignment"></param> /// <returns></returns> public ICellStyle CreateCellStyle(int fontSize, string fontName, bool fontBold, HorizontalAlignment horizontal, VerticalAlignment vertical, BorderStyle borderStyle) { ICellStyle style = workbook.CreateCellStyle(); IFont font = workbook.CreateFont(); font.FontName = fontName; font.FontHeightInPoints = (short)fontSize; if (fontBold) font.Boldweight = (short)FontBoldWeight.Bold;//字体加粗 style.Alignment = horizontal; style.VerticalAlignment = vertical; style.SetFont(font); style.BorderLeft = borderStyle; style.BorderRight = borderStyle; style.BorderTop = borderStyle; style.BorderBottom = borderStyle; return style; } /// <summary> /// 得到数据行常规样式(11 字号+居中对齐) /// </summary> /// <returns></returns> public ICellStyle GetNormalCellStyle() { return GetNormalCellStyle(11, HorizontalAlignment.Center); } public ICellStyle GetNormalCellStyle(int fontSize, HorizontalAlignment horizontal) { return CreateCellStyle(fontSize, "Arial", false, horizontal, VerticalAlignment.Center, BorderStyle.Thin); } /// <summary> /// 得到标题样式(20字号+加粗+居中对齐) /// </summary> /// <returns></returns> public ICellStyle GetHeaderCellStyle() { return CreateCellStyle(20, "Arial", true, HorizontalAlignment.Center, VerticalAlignment.Center, BorderStyle.Thin); } #endregion #region 设置行列的边框,以及样式 /// <summary> /// 设置指定列,指定范围行的边框 (传从0 开始的索引) /// </summary> public void SetCellRangeBorder(string sheetName, int cellIndex, int startRow, int endRow, ICellStyle cellStyle) { SetRengeBorder(sheetName, startRow, cellIndex, endRow, cellIndex, cellStyle); } /// <summary> /// 设置指定行指定范围列的边框(传从0 开始的索引) /// </summary> public void SetRowRangeBorder(string sheetName, int rowIndex, int startCell, int endCell, ICellStyle cellStyle) { SetRengeBorder(sheetName, rowIndex, startCell, rowIndex, endCell, cellStyle); } /// <summary> /// 设置指定范围的边框,(传从0 开始的索引) /// </summary> public void SetRengeBorder(string sheetName, int startRow, int startCell, int endRow, int endCell, ICellStyle cellStyle) { var sheet = GetSheet(sheetName); for (int i = startRow; i <= endRow; i++) { for (int n = startCell; n <= endCell; n++) { var row = sheet.GetRow(i) ?? sheet.CreateRow(i); var cell = row.GetCell(n); if (cell == null) { cell = sheet.GetRow(i).CreateCell(n); } cell.CellStyle = cellStyle; } } } #endregion #region 合并单元格,带样式 /// <summary> /// 合并单元格常规样式 /// </summary> /// <param name="sheetName"></param> /// <param name="startRow"></param> /// <param name="startCol"></param> /// <param name="endRow"></param> /// <param name="endCol"></param> public void MergedCellsStyle(string sheetName, int startRow, int startCol, int endRow, int endCol) { MergedCellsStyle(sheetName, startRow, startCol, endRow, endCol, GetNormalCellStyle()); } /// <summary> /// 合并单元格指定样式 /// </summary> /// <param name="sheetName"></param> /// <param name="startRow"></param> /// <param name="startCol"></param> /// <param name="endRow"></param> /// <param name="endCol"></param> /// <param name="cellStyle"></param> public void MergedCellsStyle(string sheetName, int startRow, int startCol, int endRow, int endCol, ICellStyle cellStyle) { MergedCells(GetSheet(sheetName), startRow, endRow, startCol, endCol); for (int i = startRow; i <= endRow; i++) { SetRowRangeBorder(sheetName, i, startCol, endCol, cellStyle); } } #endregion /// <summary> /// 设置表格内有效数据行样式(全部行)(填充完数据后调用) /// </summary> /// <param name="sheetName"></param> /// <param name="cellStyle">样式</param> /// <param name="isIgnoreHeader">是否忽略掉标题,前两行</param> /// <param name="isAutoW">内容是否自适应宽度</param> public void SetValidDataRowStyle(string sheetName, ICellStyle cellStyle, bool isIgnoreHeader = true, bool isAutoW = true) { var (row, cell) = GetMaxRowIndexAndCellIndex(sheetName); int startRow = isIgnoreHeader ? 2 : 0; SetRengeBorder(sheetName, startRow, 0, row, cell, cellStyle); if (isAutoW) AutoColumnWidth(sheetName, 0, cell); } } }