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);
        }
    }
}

  

posted @ 2022-08-09 15:58  互联网CV工程师  阅读(180)  评论(0编辑  收藏  举报