NPOI导出EXCEL 合并单元格、统计列、单元格样式设置

先上效果图:
在这里插入图片描述
先声明一个IWorkbook对象:

				IWorkbook workbook;
                //XSSFWorkbook 适用XLSX格式,HSSFWorkbook 适用XLS格式
                string fileExt = Path.GetExtension(fileName).ToLower();
                if (fileExt == ".xlsx") {
                    workbook = new XSSFWorkboo
                 }
                else if (fileExt == ".xls") {
                    workbook = new HSSFWorkbook();
                } else {
                    workbook = null;
                }
                if (workbook == null)  {
                    return;
                }

标题合并单元格,字体居中加粗,先定义单元格样式:

                ICellStyle cellStyle = workbook.CreateCellStyle();//声明样式
                cellStyle.Alignment = HorizontalAlignment.Center;//水平居中
                cellStyle.VerticalAlignment = VerticalAlignment.Center;//垂直居中
                IFont font = workbook.CreateFont();//声明字体
                font.Boldweight = (Int16)FontBoldWeight.Bold;//加粗
                font.FontHeightInPoints = 18;//字体大小
                cellStyle.SetFont(font);//加入单元格

其次实现单元格合并:

				IRow row0 = sheet.CreateRow(0);//创建行
                row0.HeightInPoints = 35;//行高
                ICell cell0 = row0.CreateCell(0);//创建单元格
                cell0.SetCellValue("XXXX年XX月对账单");//赋值
                cell0.CellStyle = cellStyle;//设置样式
                 sheet.AddMergedRegion(new CellRangeAddress(0, 0, 0, dtBody.Columns.Count-1));//合并单元格(第几行,到第几行,第几列,到第几列)

这样第一列的标题效果完成,接下来是一行的多个单元格合并,步骤如上,需要注意的是,单元格赋值的时候,下标要写每个合并单元格域的第一列,不然会被覆盖。
接下来是一个DataTable的读取,可以先计算每一列的列宽:

int[] arrColWidth = new int[dtBody.Columns.Count];//声明列宽数组
                foreach (DataColumn item in dtBody.Columns)//先存储列头的宽度
                {
                    arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length;
                }
                for (int i = 0; i < dtBody.Rows.Count; i++)//遍历整张表,如果宽度大于列头宽度,则替换
                {
                    for (int j = 0; j < dtBody.Columns.Count; j++)
                    {
                        int intTemp = Encoding.GetEncoding(936).GetBytes(dtBody.Rows[i][j].ToString()).Length;
                        if (intTemp > arrColWidth[j])
                        {
                            arrColWidth[j] = intTemp;
                        }
                    }
                }

接下来填充数据:

				#region 填充表头
                IRow row = sheet.CreateRow(2);//先前占用了2行,表头从3开始
                for (int i = 0; i < dtBody.Columns.Count; i++)
                {
                    ICell cell = row.CreateCell(i);
                    cell.SetCellValue(dtBody.Columns[i].ColumnName);
                    sheet.SetColumnWidth(i, arrColWidth[i] * 300);
                    cell.CellStyle = dateStyle;
                }
                #endregion

                #region  填充表身
                for (int i = 0; i < dtBody.Rows.Count; i++)
                {
                    IRow row1 = sheet.CreateRow(i + 3);//表身从3开始
                    for (int j = 0; j < dtBody.Columns.Count; j++)
                    {
                        ICell cell = row1.CreateCell(j);
                        if (dtBody.Columns[j].DataType.FullName == "System.Decimal")//数字类型的值单独的样式
                        {
                            cell.SetCellType(CellType.Numeric);
                            if (dtBody.Rows[i][j].ToString() == "")
                            {
                                cell.SetCellValue(0);
                            }
                            else
                            {
                                cell.SetCellValue(double.Parse(dtBody.Rows[i][j].ToString()));
                            }
                            cell.CellStyle = numberStyle;//数字样式
                        }
                        else
                        {
                            cell.SetCellValue(dtBody.Rows[i][j].ToString());
                            cell.CellStyle = initStyle;
                        }
                    }
                   #region 统计行
                    if (i == dtBody.Rows.Count - 1)//最后一行
                    {
                        IRow rowCount = sheet.CreateRow(i + 4);//追加一行统计列
                        sheet.AddMergedRegion(new CellRangeAddress(i+ 4, i+4 , 0, 5));//合并单元格(第几行,到第几行,第几列,到第几列)
                        ICell cellEnd1 = rowCount.CreateCell(6);//创建单元格
                        ICell cellEnd2 = rowCount.CreateCell(7);
                        ICell cellEnd3 = rowCount.CreateCell(8);
                        ICell cellEnd4 = rowCount.CreateCell(9);;
                        cellEnd1.SetCellValue("对帐总金额:");
                        cellEnd3.SetCellValue("确认总金额:");
                        cellEnd1.CellStyle = textStyle;
                        cellEnd3.CellStyle = textStyle;
                        cellEnd2.CellStyle = moneyStyle;
                        cellEnd4.CellStyle = moneyStyle;
                        sheet.SetColumnWidth(6, 16 * 256);//设置单元格宽度
                        sheet.SetColumnWidth(7, 14 * 256);
                        sheet.SetColumnWidth(8, 16 * 256);
                        sheet.SetColumnWidth(9, 14 * 256);
                        string CellFormulaString1= "sum(I4:I"+ (dtBody.Rows.Count + 3) + ")"; //计算表达式,行统计: sum(A1:C1),列统计:sum(B1:B10)
                        string CellFormulaString2= "sum(J4:J"+ (dtBody.Rows.Count + 3) + ")"; //计算表达式
                        sheet.GetRow(dtBody.Rows.Count + 3).GetCell(7).SetCellFormula(CellFormulaString1);//赋值表达式
                        sheet.GetRow(dtBody.Rows.Count + 3).GetCell(9).SetCellFormula(CellFormulaString2);
                    }
                    #endregion
                }

                #endregion

统计行中moneyStyle单元格样式中需要添加“¥”字符,网上搜了很久的方法没有找到,自己无意中试出来的:

				ICellStyle moneyStyle= workbook.CreateCellStyle();
                IFont font1 = workbook.CreateFont();
                font1.Color = (Int16)FontColor.Red;
                moneyStyle.SetFont(font1);
                IDataFormat dataformat = workbook.CreateDataFormat();
                style3.DataFormat = dataformat.GetFormat("¥0.00"); ;

填充完数据之后,需要将其写入文件中,然后导出:

				MemoryStream stream = new MemoryStream(); 
                workbook.Write(stream);
                var buf = stream.ToArray();//转为字节数组 
                //创建文件
                using (FileStream fs = new FileStream(savePath, FileMode.CreateNew, FileAccess.Write))//savePath为文件保存路径
                {
                    fs.Write(buf, 0, buf.Length);
                    fs.Flush();
                }

至此,后端完成

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值