NPOI封装类

// /// <summary>
    /// Excel操作类
    /// </summary>
    public class NPOIHelper : IDisposable
    {
        private string fileALLPath = "";//Excel物理路径(绝对路径)
        private IWorkbook workbook = null;//使用NPOI初始化的Excel工作簿
        private FileStream fs = null;//Excel文件流
        private bool disposed;
        private string rowsCode = "<%ROWS:{0}%>";//数据行绑定码
        
        public NPOIHelper()
        {
            disposed = false;
        }

        public NPOIHelper(string fileALLPath)
        {
            this.fileALLPath = fileALLPath;
            disposed = false;
            //使用NPOI初始化的Excel工作簿
            this.fs = new FileStream(fileALLPath, FileMode.Open, FileAccess.Read);
            if (fileALLPath.IndexOf(".xlsx") > 0)
            {
                workbook = new XSSFWorkbook(fs);
            }
            else if (fileALLPath.IndexOf(".xls") > 0)
            {
                workbook = new HSSFWorkbook(fs);
            }
        }

        /// <summary>
        /// 将DataTable数据导入到excel中
        /// </summary>
        /// <param name="data">要导入的数据</param>
        /// <param name="isColumnWritten">DataTable的列名是否要导入</param>
        /// <param name="sheetName">要导入的excel的sheet的名称</param>
        /// <returns>导入数据行数(包含列名那一行)</returns>
        public int DataTableToExcel(DataTable data, string sheetName, bool isColumnWritten)
        {
            int i = 0;
            int j = 0;
            int count = 0;
            ISheet sheet = null;

            fs = new FileStream(fileALLPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            if (fileALLPath.IndexOf(".xlsx") > 0) // 2007版本
                workbook = new XSSFWorkbook();
            else if (fileALLPath.IndexOf(".xls") > 0) // 2003版本
                workbook = new HSSFWorkbook();

            try
            {
                if (workbook != null)
                {
                    sheet = workbook.CreateSheet(sheetName);
                }
                else
                {
                    return -1;
                }

                if (isColumnWritten == true) //写入DataTable的列名
                {
                    IRow row = sheet.CreateRow(0);
                    for (j = 0; j < data.Columns.Count; ++j)
                    {
                        row.CreateCell(j).SetCellValue(data.Columns[j].ColumnName);
                    }
                    count = 1;
                }
                else
                {
                    count = 0;
                }

                for (i = 0; i < data.Rows.Count; ++i)
                {
                    IRow row = sheet.CreateRow(count);
                    for (j = 0; j < data.Columns.Count; ++j)
                    {
                        row.CreateCell(j).SetCellValue(data.Rows[i][j].ToString());
                    }
                    ++count;
                }
                workbook.Write(fs); //写入到excel
                return count;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: " + ex.Message);
                return -1;
            }
        }

        /// <summary>
        /// 将excel中的数据导入到DataTable中
        /// </summary>
        /// <param name="sheetName">excel工作薄sheet的名称</param>
        /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param>
        /// <returns>返回的DataTable</returns>
        public DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn)
        {
            ISheet sheet = null;
            DataTable data = new DataTable();
            int startRow = 0;
            try
            {
                fs = new FileStream(fileALLPath, FileMode.Open, FileAccess.Read);
                if (fileALLPath.IndexOf(".xlsx") > 0) // 2007版本
                    workbook = new XSSFWorkbook(fs);
                else if (fileALLPath.IndexOf(".xls") > 0) // 2003版本
                    workbook = new HSSFWorkbook(fs);

                if (sheetName != null)
                {
                    sheet = workbook.GetSheet(sheetName);
                    if (sheet == null) //如果没有找到指定的sheetName对应的sheet,则尝试获取第一个sheet
                    {
                        sheet = workbook.GetSheetAt(0);
                    }
                }
                else
                {
                    sheet = workbook.GetSheetAt(0);
                }

                if (sheet != null)
                {
                    IRow firstRow = sheet.GetRow(0);
                    int cellCount = firstRow.LastCellNum; //一行最后一个cell的编号 即总的列数

                    if (isFirstRowColumn)
                    {
                        for (int i = firstRow.FirstCellNum; i < cellCount; ++i)
                        {
                            ICell cell = firstRow.GetCell(i);
                            if (cell != null)
                            {
                                string cellValue = cell.StringCellValue;
                                if (cellValue != null)
                                {
                                    DataColumn column = new DataColumn(cellValue);
                                    data.Columns.Add(column);
                                }
                            }
                        }
                        startRow = sheet.FirstRowNum + 1;
                    }
                    else
                    {
                        startRow = sheet.FirstRowNum;
                    }

                    //最后一列的标号
                    int rowCount = sheet.LastRowNum;
                    for (int i = startRow; i <= rowCount; ++i)
                    {
                        IRow row = sheet.GetRow(i);
                        if (row == null) continue; //没有数据的行默认是null       

                        DataRow dataRow = data.NewRow();
                        for (int j = row.FirstCellNum; j < cellCount; ++j)
                        {
                            if (row.GetCell(j) != null) //同理,没有数据的单元格都默认是null
                                dataRow[j] = row.GetCell(j).ToString();
                        }
                        data.Rows.Add(dataRow);
                    }
                }

                return data;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: " + ex.Message);
                return null;
            }
        }

        /// <summary>
        /// 获取Excel中Sheet名称集合
        /// </summary>
        /// <returns></returns>
        public string[] SheetNames()
        {
            fs = new FileStream(fileALLPath, FileMode.Open, FileAccess.Read);
            if (fileALLPath.IndexOf(".xlsx") > 0) // 2007版本
                workbook = new XSSFWorkbook(fs);
            else if (fileALLPath.IndexOf(".xls") > 0) // 2003版本
                workbook = new HSSFWorkbook(fs);
            int sheetCount = workbook.NumberOfSheets;
            string[] sheetName = new string[sheetCount];//保存表的名称
            for (int i = 0; i < sheetCount; i++)
            {
                sheetName[i] = workbook.GetSheetName(i);
            }
            return sheetName;
        }

        /// <summary>
        /// 删除指定的Sheets
        /// </summary>
        public void RemoveSheetsByNames(string[] sheetNames)
        {
            foreach (string sheetName in sheetNames)
            {
                ISheet sheet = workbook.GetSheet(sheetName);
                int index = workbook.GetSheetIndex(sheet);
                workbook.RemoveSheetAt(index);
            }
        }

        /// <summary>
        /// 保存修改后的excel
        /// </summary>
        public void Save()
        {
            FileStream fileSave = new FileStream(fileALLPath, FileMode.Open, FileAccess.Write);
            workbook.Write(fileSave);
            fileSave.Close();
        }

        /// <summary>
        /// 填充Sheet
        /// </summary>
        /// <param name="sheetName">sheet名称</param>
        /// <param name="dt">数据源(DataTable)</param>
        /// <param name="isList">填充类型:"对象"还是"集合",true:"集合",false:"对象"</param>
        /// <param name="dtName">DataTable TableName</param>
        /// <param name="isAlarm">是否是:业务风险提示</param>
        /// <param name="rowIndex">遍历Excel范围:行数,默认30行</param>
        /// <param name="colIndex">遍历Excel范围:列数,默认20列</param>
        public void FillSheet(string sheetName, DataTable dt, bool isList, string dtName = "", bool isAlarm = false, int rowIndex = 30, int colIndex = 20)
        {
            if (dt == null || dt.Rows.Count <= 0)
                return;

            ISheet sheet = workbook.GetSheet(sheetName);
            if (sheet == null)
                return;

            if (!isList)
            {
                //"对象填充"
                foreach (DataColumn column in dt.Columns)
                {
                    for (int rowIn = 0; rowIn < rowIndex; rowIn++)
                    {
                        for (int colIn = 0; colIn < colIndex; colIn++)
                        {
                            IRow row = sheet.GetRow(rowIn);
                            if (row == null)
                                continue;
                            ICell cell = row.GetCell(colIn);
                            if (cell == null)
                                continue;

                            if (string.IsNullOrEmpty(dtName))
                            {
                                dtName = dt.TableName;
                            }
                            string a = string.Empty;
                            if (isAlarm)
                            {
                                a = "$" + column.ColumnName;
                            }
                            else
                            {
                                a = "<%" + dtName + ";" + column.ColumnName + "%>";
                            }
                            if (cell.ToString() == a)
                            {
                                var value = dt.Rows[0][column.ColumnName];

                                if (value == DBNull.Value || value == null)
                                {
                                    cell.SetCellValue(string.Empty);
                                }
                                else
                                {
                                    if (column.DataType.FullName == "System.DateTime")
                                    {
                                        cell.SetCellValue(Convert.ToDateTime(value).ToString("yyyy-MM-dd"));
                                    }
                                    else if (column.DataType.FullName == "System.Decimal")
                                    {
                                        cell.SetCellValue(double.Parse(Convert.ToDecimal(value).ToString("N2")));
                                    }
                                    else
                                    {
                                        cell.SetCellValue(value.ToString());
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                //"集合"填充
                ICellStyle style = workbook.CreateCellStyle();
                style.BorderBottom = BorderStyle.Thin;
                style.BorderLeft = BorderStyle.Thin;
                style.BorderRight = BorderStyle.Thin;
                style.BorderTop = BorderStyle.Thin;

                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    IRow row = sheet.CreateRow(i + 1);
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        ICell cell = row.CreateCell(j);
                        cell.SetCellValue(dt.Rows[i][j].ToString());
                        cell.CellStyle = style;
                    }
                }
            }
            sheet.ForceFormulaRecalculation = true;//刷新单元格公式,自动计算
        }

        /// <summary>
        /// 填充Sheet数据(对多Table数据填充)
        /// </summary>
        /// <param name="sheetName">sheet名称</param>
        /// <param name="tableNum">table个数</param>
        /// <param name="tableNames">table的表名(用于匹配数据源中的table和数据模板中数据绑定码</param>
        /// <param name="cellKeys">table的数据列名(用于匹配数据源中对应列数据),如:{{"fieldName1,fliedName2"},{"fieldName1,fieldName2,fieldName3"}},字段名之间使用 , 分割</param>
        /// <param name="dts">数据源</param>
        /// <param name="cellCount">数据列数,默认为0,取第一行的数据列数</param>
        /// <param name="isSum">是否求和,默认不求和。如果为true,会搜索“合计”行,把数据类型为decimal的列求和</param>
        public void FillSheetEx(string sheetName, int tableNum, string[] tableNames, string[] cellKeys, DataSet dts, int cellCount = 0, bool isSum = false)
        {
            if (dts == null || dts.Tables.Count <= 0)
            {
                return;
            }

            ISheet sheet = workbook.GetSheet(sheetName);
            if (sheet == null)
            {
                return;
            }

            if (sheet != null)
            {
                if (cellCount == 0)
                {
                    cellCount = sheet.GetRow(0).LastCellNum;//列数
                }
                int searchRow = 0;//搜索开始行
                int startRow = 0;
                int startCell = 0;
                string content = "";
                for (int i = 0; i < tableNum; i++)
                {
                    content = string.Format(rowsCode, tableNames[i]);//数据绑定码
                    MatchSheetContent(sheet, content, out startRow, out startCell, cellCount, 5, searchRow);//获取插入数据的行和列
                    if (startRow > 0)
                    {
                        sheet.GetRow(startRow).GetCell(startCell).SetCellValue("");//清空数据绑定码信息
                        InsertSheetData(sheet, dts.Tables[tableNames[i]], startRow, dts.Tables[tableNames[i]].Columns.Count, cellKeys[i].Split(','), isSum);//插入数据

                        searchRow = startRow + dts.Tables[tableNames[i]].Rows.Count + 3; //3:表和表之间隔2行
                        if (isSum)
                        {
                            searchRow = searchRow + 1;//合计的1行
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            sheet.ForceFormulaRecalculation = true;//刷新单元格公式,自动计算
        }

        /// <summary>
        /// 下载Excel
        /// </summary>
        /// <param name="fileName">下载时,显示的文件名</param>
        public void Download(string fileName)
        {
            FileStream fs = new FileStream(fileName, FileMode.Open);
            byte[] bytes = new byte[(int)fs.Length];
            fs.Read(bytes, 0, bytes.Length);
            fs.Close();
            System.Web.HttpContext.Current.Response.ContentType = "application/octet-stream;charset=gb2312";
            System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
            System.Web.HttpContext.Current.Response.BinaryWrite(bytes);
            System.Web.HttpContext.Current.Response.Flush();
            System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest();
        }

        /// <summary>
        /// 直接下载Excel文件
        /// </summary>
        /// <param name="fileName"></param>
        public void DownloadEx(string fileName)
        {
            int length = (int)fs.Length;
            byte[] data = new byte[length];
            fs.Position = 0;
            fs.Read(data, 0, length);
            fs.Close();
            byte[] buffer;
            using (MemoryStream ms = new MemoryStream(data))
            {
                buffer = new byte[ms.Capacity];
                if (ms.CanRead)
                {
                    ms.Read(buffer, 0, ms.Capacity);
                }
            }

            System.Web.HttpContext.Current.Response.Clear();
            System.Web.HttpContext.Current.Response.ContentType = "application/octet-stream;charset=gb2312";
            System.Web.HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
            System.Web.HttpContext.Current.Response.BinaryWrite(buffer);
            System.Web.HttpContext.Current.Response.Flush();
            System.Web.HttpContext.Current.ApplicationInstance.CompleteRequest();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    if (fs != null)
                        fs.Close();
                }

                fs = null;
                disposed = true;
            }
        }

        #region 其他成员方法
        /// <summary>
        /// 在sheet中的某个单元格设置计算函数(会导致Excel文件错误,方法待优化)
        /// </summary>
        /// <param name="sheetName"></param>
        /// <param name="rowIndex">设置单元格行索引</param>
        /// <param name="cellIndex">设置单元格列索引</param>
        /// <param name="operatorCode">函数名</param>
        /// <param name="startRowIndex">开始行索引</param>
        /// <param name="startCellIndex">开始列索引</param>
        /// <param name="endRowIndex">结束行索引</param>
        /// <param name="endCellIndex">结束列索引</param>
        ///  <param name="dataFormat">默认:194:数值格式</param>
        public void OperatorFormula(string sheetName, int rowIndex, int cellIndex, string operatorCode, int startRowIndex, int startCellIndex, int endRowIndex, int endCellIndex, short dataFormat = 194)
        {
            ISheet sheet = workbook.GetSheet(sheetName);
            if (sheet == null)
            {
                return;
            }
            string strFormula = GetOperatorFormula(operatorCode, startRowIndex, startCellIndex, endRowIndex, endCellIndex);
            ICell cell = sheet.GetRow(rowIndex).GetCell(cellIndex);
            cell.CellStyle.DataFormat = dataFormat;
            cell.SetCellType(CellType.Formula);
            cell.SetCellFormula(strFormula);
        }
        #endregion

        #region 扩展方法
        /// <summary>
        /// 下载服务器文件
        /// </summary>
        /// <param name="fileAllPath">文件全路径</param>
        /// <param name="fileName">下载文件名(包含扩展名)</param>
        public static void Download(string fileAllPath, string fileName)
        {
            if (!File.Exists(fileAllPath))
            {
                return;
            }
            using (FileStream fs = new FileStream(fileAllPath, FileMode.Open))
            {
                byte[] buffer = new byte[(int)fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                fs.Close();

                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.ContentType = "application/octet-stream;charset=gb2312";
                HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + System.Web.HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
                HttpContext.Current.Response.BinaryWrite(buffer);
                HttpContext.Current.Response.Flush();
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
        }

        /// <summary>
        /// 下载数据文件
        /// </summary>
        /// <param name="workbook">Excel实体</param>
        /// <param name="fileName">下载文件名(包含扩展名)</param>
        public static void Download(HSSFWorkbook workbook, string fileName)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                workbook.Write(ms);
                ms.Flush();
                ms.Position = 0;

                byte[] buffer = new byte[ms.Capacity];
                if (ms.CanRead)
                {
                    ms.Read(buffer, 0, ms.Capacity);
                }
                ms.Close();

                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.ContentType = "application/octet-stream;charset=gb2312";
                HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8));
                HttpContext.Current.Response.BinaryWrite(buffer);
                HttpContext.Current.Response.Flush();
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
        }

        /// <summary>
        /// 创建单元格样式
        /// </summary>
        /// <param name="workbook"></param>
        /// <param name="type">单元格类型</param>
        /// <param name="fontHeightInPoints">字号,传0为默认字号</param>
        /// <param name="foregroundColor">背景色(可通过NPOI.HSSF.Util.HSSFColor获取色值)</param>
        /// <returns></returns>
        public static ICellStyle CreateCellStyle(HSSFWorkbook workbook, SheetCellType type, short fontHeightInPoints = 0, short foregroundColor = 0)
        {
            ICellStyle cellStyle = workbook.CreateCellStyle();
            switch (type.ToString())
            {
                case "CellTitle":
                    #region 标题样式
                    //设置单元格边框
                    cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                    //设置单元格边框颜色
                    cellStyle.BottomBorderColor = HSSFColor.Black.Index;
                    cellStyle.LeftBorderColor = HSSFColor.Black.Index;
                    cellStyle.RightBorderColor = HSSFColor.Black.Index;
                    cellStyle.TopBorderColor = HSSFColor.Black.Index;
                    //设置水平垂直居中
                    cellStyle.VerticalAlignment = VerticalAlignment.Center;
                    cellStyle.Alignment = HorizontalAlignment.Center;
                    //设置单元格背景颜色
                    if (foregroundColor > 0)
                    {
                        cellStyle.FillForegroundColor = foregroundColor;
                        cellStyle.FillPattern = FillPattern.SolidForeground;//填充背景样式
                    }
                    //新建一个字体样式对象
                    IFont titleFont = workbook.CreateFont();
                    //字体大小13.5pt,对应像素18px
                    titleFont.FontHeightInPoints = 16;
                    //设置字体加粗样式
                    titleFont.Boldweight = short.MaxValue;
                    //使用SetFont方法将字体样式添加到单元格样式中 
                    cellStyle.SetFont(titleFont);
                    #endregion
                    break;
                case "CellField":
                    #region 字段名样式
                    //设置单元格边框
                    cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                    //设置单元格边框颜色
                    cellStyle.BottomBorderColor = HSSFColor.Black.Index;
                    cellStyle.LeftBorderColor = HSSFColor.Black.Index;
                    cellStyle.RightBorderColor = HSSFColor.Black.Index;
                    cellStyle.TopBorderColor = HSSFColor.Black.Index;
                    //设置垂直水平居中
                    cellStyle.VerticalAlignment = VerticalAlignment.Center;
                    cellStyle.Alignment = HorizontalAlignment.Center;
                    //设置单元格背景颜色
                    if (foregroundColor > 0)
                    {
                        cellStyle.FillForegroundColor = foregroundColor;
                        cellStyle.FillPattern = FillPattern.SolidForeground;//填充背景样式
                    }
                    IFont FiledFont = workbook.CreateFont();
                    //字体大小10.5pt,对应像素14px
                    FiledFont.FontHeightInPoints = fontHeightInPoints <= 0 ? (short)10 : fontHeightInPoints;
                    //设置字体加粗样式
                    FiledFont.Boldweight = short.MaxValue;
                    cellStyle.SetFont(FiledFont);
                    #endregion
                    break;
                case "CellValue":
                    #region 数据值样式
                    //设置单元格边框
                    cellStyle.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
                    cellStyle.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
                    //设置单元格边框颜色
                    cellStyle.BottomBorderColor = HSSFColor.Black.Index;
                    cellStyle.LeftBorderColor = HSSFColor.Black.Index;
                    cellStyle.RightBorderColor = HSSFColor.Black.Index;
                    cellStyle.TopBorderColor = HSSFColor.Black.Index;
                    //设置垂直水平居中
                    cellStyle.VerticalAlignment = VerticalAlignment.Center;
                    cellStyle.Alignment = HorizontalAlignment.Center;
                    //设置单元格背景颜色
                    if (foregroundColor > 0)
                    {
                        cellStyle.FillForegroundColor = foregroundColor;
                        cellStyle.FillPattern = FillPattern.SolidForeground;//填充背景样式
                    }
                    IFont valueFont = workbook.CreateFont();
                    //字体大小10.5pt,对应像素14px
                    valueFont.FontHeightInPoints = fontHeightInPoints <= 0 ? (short)9 : fontHeightInPoints;
                    cellStyle.SetFont(valueFont);
                    #endregion
                    break;
            }
            return cellStyle;
        }

        /// <summary>
        /// 合并及填充单元格
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="firstRow">第一行的index</param>
        /// <param name="lastRow">最后一行的index</param>
        /// <param name="firstCol">第一列的index</param>
        /// <param name="lastCol">最后一列的index</param>
        /// <param name="content">填充内容</param>
        /// <param name="cellHeight">单元格行高,默认高设置为0(标题一般传值:23.5f)</param>
        /// <param name="cellStyle">单元格样式接口实例</param>
        public static void MergeCell(HSSFSheet sheet, int firstRow, int lastRow, int firstCol, int lastCol, string content = "", float cellHeight = 0, ICellStyle cellStyle = null)
        {
            CellRangeAddress cellRange = new CellRangeAddress(firstRow, lastRow, firstCol, lastCol);
            sheet.AddMergedRegion(cellRange);

            //填充内容
            if (!string.IsNullOrWhiteSpace(content))
            {
                IRow row = sheet.CreateRow(firstRow);
                row.CreateCell(firstCol).SetCellValue(content);
                //对应高度30px
                if (cellHeight > 0)
                {
                    row.Height = (short)(cellHeight * 20);
                }
            }

            //合并单元格的样式
            for (int i = cellRange.FirstRow; i <= cellRange.LastRow; i++)
            {
                IRow row = HSSFCellUtil.GetRow(i, sheet);
                for (int j = cellRange.FirstColumn; j <= cellRange.LastColumn; j++)
                {
                    ICell singleCell = HSSFCellUtil.GetCell(row, (short)j);
                    if (cellStyle != null)
                    {
                        singleCell.CellStyle = cellStyle;
                    }
                }
            }
        }

        /// <summary>
        /// 设置表格自适应宽度
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="cellNum">表格列数</param>
        /// <param name="multiple">单元格显示宽度倍数(如1.5:是内容宽度的1.5倍),默认和内容宽度一致</param>
        /// <param name="defaultLen">数据为空时,单元格的默认填充长度:2</param>
        public static void SetAdaptiveWidth(HSSFSheet sheet, int cellNum, double multiple = 1, int defaultLen = 2)
        {
            int width = defaultLen * 1024;//空数据指定宽度
            int times = Convert.ToInt32(multiple * 10);
            for (int i = 0; i <= cellNum; i++)
            {
                sheet.AutoSizeColumn(i);
                if (sheet.GetColumnWidth(i) >= 2048)
                {
                    width = sheet.GetColumnWidth(i);
                }
                sheet.SetColumnWidth(i, width * times / 10);
            }
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 向Sheet的指定行中插入数据
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="dt">数据源</param>
        /// <param name="startRowIndex">开始插入数据的行索引</param>
        /// <param name="cellCount">数据列数</param>
        /// <param name="cellKeys">列匹配关键字</param>
        /// <param name="isSum">是否求和,默认不求和。如果为true,会搜索“合计”行,把数据类型为decimal的列求和</param>
        private void InsertSheetData(ISheet sheet, DataTable dt, int startRowIndex, int cellCount, string[] cellKeys, bool isSum = false)
        {
            int firstDataRow = startRowIndex;
            sheet.ShiftRows(startRowIndex, sheet.LastRowNum, dt.Rows.Count - 1, true, false);
            string dataType = "";
            IRow row;
            for (int i = 0, len = dt.Rows.Count; i < len; i++)
            {
                row = sheet.CreateRow(startRowIndex);
                //创建列并插入数据
                for (int index = 0; index < cellCount; index++)
                {
                    ICellStyle cellStyle = sheet.GetRow(startRowIndex - 1).GetCell(i).CellStyle;//获取上一行的数据格式
                    dataType = dt.Rows[i][cellKeys[index]].GetType().ToString();
                    if (dataType == "System.DBNull")
                    {
                        row.CreateCell(index).SetCellValue("");
                    }
                    else if (dataType == "System.Decimal")
                    {
                        row.CreateCell(index).SetCellValue(double.Parse(Convert.ToDecimal(dt.Rows[i][cellKeys[index]]).ToString("N2")));
                    }
                    else if (dataType == "System.DateTime")
                    {
                        row.CreateCell(index).SetCellValue(Convert.ToDateTime(dt.Rows[i][cellKeys[index]]).ToString("yyyy-MM-dd"));
                    }
                    else
                    {
                        row.CreateCell(index).SetCellValue(!(dt.Rows[i][cellKeys[index]] is DBNull) ? dt.Rows[i][cellKeys[index]].ToString() : string.Empty);
                    }
                    row.GetCell(index).CellStyle = cellStyle;
                }
                startRowIndex = startRowIndex + 1;
            }

            if (isSum)//求和
            {
                int startRow = 0;
                int startCell = 0;
                MatchSheetContent(sheet, "合计", out startRow, out startCell, cellCount, 5, startRowIndex);
                if (startRow > 0)
                {
                    IRow sumRow = sheet.GetRow(startRow);
                    for (int index = 0; index < dt.Columns.Count; index++)
                    {
                        if (sumRow.GetCell(index).CellType == CellType.Formula)//格式为表达式,求和
                        {
                            sumRow.GetCell(index).SetCellFormula(GetOperatorFormula("SUM", firstDataRow, index, startRow - 1, index));
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 获取Excel简单操作函数
        /// </summary>
        /// <param name="operatorCode">函数名,如:SUM</param>
        /// <param name="startRowIndex">开始行索引</param>
        /// <param name="startCellIndex">开始列索引</param>
        /// <param name="endRowIndex">结束行索引</param>
        /// <param name="endCellIndex">结束列索引</param>
        /// <returns></returns>
        private string GetOperatorFormula(string operatorCode, int startRowIndex, int startCellIndex, int endRowIndex, int endCellIndex)
        {
            string[,] code = { { "A" }, { "B" }, { "C" }, { "D" }, { "E" }, { "F" }, { "G" }, { "H" }, { "I" }, { "J" }, { "K" }, { "L" }, { "M" }, { "N" }, { "O" }, { "P" }, { "Q" }, { "R" }, { "S" }, { "T" }, { "U" }, { "V" }, { "W" }, { "X" }, { "Y" }, { "Z" } };
            string start = string.Format("{0}{1}", code[startCellIndex, 0], startRowIndex + 1);
            string end = string.Format("{0}{1}", code[endCellIndex, 0], endRowIndex + 1);

            return string.Format("{0}({1}:{2})", operatorCode, start, end);
        }

        /// <summary>
        /// 搜索Sheet中匹配信息的单元格所在行和列
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="matchContent">匹配信息</param>
        /// <param name="whichRow">返回信息:哪一行</param>
        /// <param name="whichCell">返回信息:哪一列</param>
        /// <param name="searchCells">搜索Sheet表格宽度,为0时默认取第一行的宽度</param>
        /// <param name="searchRows">搜索的行数,默认搜索5行</param>
        /// <param name="formWhichRow">从第几行开始搜索,默认从第一行</param>
        private void MatchSheetContent(ISheet sheet, string matchContent, out int whichRow, out int whichCell, int searchCells = 0, int searchRows = 5, int formWhichRow = 0)
        {
            whichRow = -1;
            whichCell = -1;
            IRow firstRow = sheet.GetRow(0);
            if (searchCells == 0)
            {
                searchCells = firstRow.LastCellNum;//一行最后一个cell的编号 即总的列数
            }

            //遍历Sheet,找到需要填充数据源的行位置
            IRow currentRow;
            ICell currentCell;
            bool isFinish = false;
            for (int i = formWhichRow; i < formWhichRow + searchRows; i++)
            {
                currentRow = sheet.GetRow(i);
                for (int j = firstRow.FirstCellNum; j < searchCells; j++)
                {
                    currentCell = currentRow.GetCell(j);
                    if (currentCell != null && currentCell.CellType == CellType.String)//仅检测字符串类型的单元格
                    {
                        string cellValue = currentCell.StringCellValue;
                        if (cellValue == matchContent)//找到需要填充数据的行
                        {
                            whichCell = currentCell.ColumnIndex;
                            whichRow = currentCell.RowIndex;
                            isFinish = true;
                            break;
                        }
                    }
                }

                if (isFinish)
                {
                    break;
                }
            }
        }
        #endregion
    }

    /// <summary>
    /// 单元格类型
    /// </summary>
    public enum SheetCellType
    {
        /// <summary>
        /// 标题
        /// </summary>
        CellTitle,
        /// <summary>
        /// 字段名
        /// </summary>
        CellField,
        /// <summary>
        /// 数据值
        /// </summary>
        CellValue
    }

  

原文地址:https://www.cnblogs.com/cdz-sky/p/10195437.html