欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

NPOI实现两级分组合并功能(示例讲解)

程序员文章站 2023-12-16 22:33:28
npoi版本:2.2.1.0 最近公司有这样的需求: 统计每个部门下面,多个费用使用情况。部门存在多级,但统计时,只需统计到2级,2级以下的,归到第2级的部门下。并且要...

npoi版本:2.2.1.0

最近公司有这样的需求:

统计每个部门下面,多个费用使用情况。部门存在多级,但统计时,只需统计到2级,2级以下的,归到第2级的部门下。并且要求,第2级部门有个小计,第1级部门需要有个合计。最后,还需提供总计。

本来对npoi研究的还不够深入的,以前都是直接通过别人提供的代码来实现对datatable中的数据进行全部导出,但里面不带合并,及合计功能,不满足当前需求。不得已,只有好好地研究一下了。还好,最终实现了要求。

在此,也感谢其他提供相关资料的人员,让我实现了此功能。

简要说明一下使用:

1、export2template2方法直接使用。datatable原始数据,必须是已经按要求排好序的数据。全部是逐行向下处理。

2、要导出的列名,取自cellkeys中。列名必须为source中存在的。

3、相同值合并的第1列,为cellkeys[0],合并的第2列,为cellkeys[1],如需要其它列的合并,可以此基础上,按自己的需求进行调整。(合并时,只会比较上下行的数据内容)

4、要导出的数据中,数值类型,自动居右。其它类型,自动居中。

5、小计,合计,总计的字体,全部加黑

6、小计,合计,总计,自动对数值类型进行汇总。其它类型数据全部置空。

7、合并的列数:mergecolumns。如果>2,自动只处理前2列。如果<1,则不做合并处理。

直接上可用的代码

/// <summary>
/// 根据模版导出excel -- 特别处理,每个分组带合计
/// </summary>
/// <param name="source">源datatable</param>
/// <param name="cellkeys">需要导出的对应的列字段 例:string[] cellkeys = { "date","remarks" };</param>
/// <param name="strfilename">要保存的文件名称(包含后缀) 例:"要保存的文件名.xls"</param>
/// <param name="templatefile">模版文件名(包含路径后缀) 例:"模板文件名.xls"</param>
/// <param name="rowindex">从第几行开始创建数据行,第一行为0</param>
/// <param name="mergecolumns">值相同时,可合并的前几列 最多支持2列 1=只合并第一列,2=判断前2列</param>
/// <param name="isconver">是否覆盖数据,=false,将把原数据下移。=true,将覆盖插入行后面的数据</param>
/// <param name="istotal">是否带小计/合计项</param>
/// <param name="addalltotal">是否添加总计项</param>
/// <returns>是否导出成功</returns>
public static bool export2template2(datatable source, string[] cellkeys, string strfilename, string templatefile, int rowindex, int mergecolumns, bool isconver, bool istotal, bool addalltotal)
{
 bool bn = false;
 int cellcount = cellkeys.length; //总列数,第一列为0
 // iworkbook workbook = null;
 hssfworkbook workbook = null;
 string temp0 = "", temp1 = "";
 int start0 = 0, start1 = 0; // 记录1,2列值相同的开始序号
 int end0 = 0, end1 = 0;// 记录1,2列值相同的结束序号
 
 try
 {
  using (filestream file = new filestream(templatefile, filemode.open, fileaccess.read))
  {
   workbook = new hssfworkbook(file);
  }
 
  #region 定义四类数据的单元格样式
  // 内容数据格式 -- 数值
  icellstyle stylenum = workbook.createcellstyle();
  stylenum.borderbottom = borderstyle.thin;
  stylenum.borderleft = borderstyle.thin;
  stylenum.borderright = borderstyle.thin;
  stylenum.bordertop = borderstyle.thin;
  // stylenum.verticalalignment = verticalalignment.center;
  // stylenum.alignment = horizontalalignment.center;
 
  // 内容数据格式 -- 字符串(做居中处理)
  icellstyle stylestr = workbook.createcellstyle();
  stylestr.borderbottom = borderstyle.thin;
  stylestr.borderleft = borderstyle.thin;
  stylestr.borderright = borderstyle.thin;
  stylestr.bordertop = borderstyle.thin;
  stylestr.verticalalignment = verticalalignment.center;
  stylestr.alignment = horizontalalignment.center;
 
  // 汇总数据格式 -- 数值
  icellstyle styletotalnum = workbook.createcellstyle();
  styletotalnum.borderbottom = borderstyle.thin;
  styletotalnum.borderleft = borderstyle.thin;
  styletotalnum.borderright = borderstyle.thin;
  styletotalnum.bordertop = borderstyle.thin;
  styletotalnum.fillforegroundcolor = npoi.hssf.util.hssfcolor.grey25percent.index;
  styletotalnum.fillpattern = fillpattern.solidforeground;
  styletotalnum.fillbackgroundcolor = npoi.hssf.util.hssfcolor.red.index;
  // 设置字体颜色
  hssffont ffont0 = (hssffont)workbook.createfont();
  // ffont0.fontheight = 14 * 14;
  // ffont0.fontname = "宋体";
  ffont0.isbold = true;
  //ffont0.color = hssfcolor.red.index;
  styletotalnum.setfont(ffont0);
 
  // 汇总数据格式 -- 字符串(做居中处理)
  icellstyle styletotalstr = workbook.createcellstyle();
  styletotalstr.borderbottom = borderstyle.thin;
  styletotalstr.borderleft = borderstyle.thin;
  styletotalstr.borderright = borderstyle.thin;
  styletotalstr.bordertop = borderstyle.thin;
  styletotalstr.verticalalignment = verticalalignment.center;
  styletotalstr.alignment = horizontalalignment.center;
  styletotalstr.fillforegroundcolor = npoi.hssf.util.hssfcolor.grey25percent.index;
  styletotalstr.fillpattern = fillpattern.solidforeground;
  // 设置字体颜色
  hssffont ffont1 = (hssffont)workbook.createfont();
  // ffont1.fontheight = 14 * 14;
  // ffont1.fontname = "宋体";
  ffont1.isbold = true;
  //ffont.color = hssfcolor.red.index;
  styletotalstr.setfont(ffont1);
  #endregion
 
  isheet sheet = workbook.getsheetat(0); // 打开第一个sheet页
  if (sheet != null && source != null && source.rows.count > 0) // 模板内容为空,不做处理
  {
   irow row;
   for (int i = 0, len = source.rows.count; i < len; i++)
   {
    if (!isconver) sheet.shiftrows(rowindex, sheet.lastrownum, 1, true, false); // 不覆盖,数据向下移
 
    #region 第一行,写入数据后,对变量赋初值
    if (i == 0) // 第一行,赋初值
    {
     row = sheet.createrow(rowindex);
     #region 创建列并插入数据
     //创建列并插入数据
     for (int index = 0; index < cellcount; index++)
     {
      icell cell = row.createcell(index);
 
      string strvalue = !(source.rows[i][cellkeys[index]] is dbnull) ? source.rows[i][cellkeys[index]].tostring() : string.empty;
      // 其它列数据,数值进行汇总
      switch (source.columns[cellkeys[index]].datatype.tostring())
      {
       case "system.int16": //整型
       case "system.int32":
       case "system.int64":
       case "system.byte":
        int intv = 0;
        int.tryparse(strvalue, out intv);
        cell.cellstyle = stylenum; // 设置格式
        cell.setcellvalue(intv);
        break;
       case "system.decimal": //浮点型
       case "system.double":
       case "system.single":
        double doubv = 0;
        double.tryparse(strvalue, out doubv);
        cell.cellstyle = stylenum; // 设置格式
        cell.setcellvalue(doubv);
        break;
       default:
        cell.cellstyle = stylestr; // 设置格式
        cell.setcellvalue(strvalue);
        break;
      }
     }
     #endregion
 
     if (mergecolumns > 0)
     {
      temp0 = source.rows[i][cellkeys[0]].tostring(); // 保存第1列值
      start0 = rowindex;
      end0 = rowindex;
     }
     if (mergecolumns > 1)
     {
      temp1 = source.rows[i][cellkeys[1]].tostring(); // 保存第2列值     
      start1 = rowindex;
      end1 = rowindex;
     }
 
     rowindex++;
     continue;
    }
    #endregion
 
    // 不是第一行数据的处理
    // 判断1列值变化没
    string celltext0 = source.rows[i][cellkeys[0]].tostring();
    if (temp0 != celltext0) // 第1列值有变化
    {
     #region 第2列要合并
     if (mergecolumns > 1) // 第2列要合并
     {
      if (start1 != end1) // 开始行和结束行不相同,才进行合并
      {
       cellrangeaddress region1 = new cellrangeaddress(start1, end1, 1, 1); // 合并第二列
       sheet.addmergedregion(region1);
      }
 
      #region 第2列加小计
      if (istotal) // 加小计
      {
       if (!isconver) sheet.shiftrows(rowindex, sheet.lastrownum, 1, true, false); // 不覆盖,数据向下移
 
       irow rowtotal1 = sheet.createrow(rowindex);
       //创建列并插入数据
       #region 插入小计数据
       for (int index = 0; index < cellcount; index++)
       {
        object obj1;
        icell newcell = rowtotal1.createcell(index);
        if (index == 0) //第1列
        {
         newcell.cellstyle = styletotalstr;
         newcell.setcellvalue(temp0);
         continue;
        }
        if (index == 1) // 第2列
        {
         newcell.cellstyle = styletotalstr;
         newcell.setcellvalue("小计");
         continue;
        }
 
        // 其它列数据,数值进行汇总
        switch (source.columns[cellkeys[index]].datatype.tostring())
        {
         case "system.int16": //整型
         case "system.int32":
         case "system.int64":
         case "system.byte":
          obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' and {2} = '{3}' ", cellkeys[0], temp0, cellkeys[1], temp1));
          int intv = 0;
          int.tryparse(obj1.tostring(), out intv);
          newcell.cellstyle = styletotalnum;
          newcell.setcellvalue(intv);
          break;
         case "system.decimal": //浮点型
         case "system.double":
         case "system.single":
          obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' and {2} = '{3}' ", cellkeys[0], temp0, cellkeys[1], temp1));
          double doubv = 0;
          double.tryparse(obj1.tostring(), out doubv);
          newcell.cellstyle = styletotalnum;
          newcell.setcellvalue(doubv);
          break;
         default:
          newcell.cellstyle = styletotalstr;
          newcell.setcellvalue("");
          break;
        }
       }
       #endregion
 
       // 合并小计
       cellrangeaddress region0 = new cellrangeaddress(rowindex, rowindex, 1, 2); // 合并小计
       sheet.addmergedregion(region0);
 
      }
      #endregion
      temp1 = source.rows[i][cellkeys[1]].tostring();
      end0++;
      rowindex++;
     }
     #endregion
 
     #region 第1列要合并
     if (mergecolumns > 0) // 第1列要合并
     {
      if (start0 != end0) // 开始行和结束行不相同,才进行合并
      {
       cellrangeaddress region0 = new cellrangeaddress(start0, end0, 0, 0); // 合并第二列
       sheet.addmergedregion(region0);
      }
 
      #region 第1列加合计
      if (istotal) // 加合计
      {
       if (!isconver) sheet.shiftrows(rowindex, sheet.lastrownum, 1, true, false); // 不覆盖,数据向下移
 
       irow rowtotal0 = sheet.createrow(rowindex);
       //创建列并插入数据
       #region 加合计列
       for (int index = 0; index < cellcount; index++)
       {
        object obj1;
        icell newcell = rowtotal0.createcell(index);
        if (index == 0)
        {
         newcell.cellstyle = styletotalstr;
         newcell.setcellvalue("合计"); //第1列
         continue;
        }
        if (index == 1)
        {
         newcell.cellstyle = styletotalstr;
         newcell.setcellvalue(""); // 第2列
         continue;
        }
 
        switch (source.columns[cellkeys[index]].datatype.tostring())
        {
         case "system.int16": //整型
         case "system.int32":
         case "system.int64":
         case "system.byte":
          obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' ", cellkeys[0], temp0));
          int intv = 0;
          int.tryparse(obj1.tostring(), out intv);
          newcell.cellstyle = styletotalnum;
          newcell.setcellvalue(intv);
          break;
         case "system.decimal": //浮点型
         case "system.double":
         case "system.single":
          obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' ", cellkeys[0], temp0));
          double doubv = 0;
          double.tryparse(obj1.tostring(), out doubv);
          newcell.cellstyle = styletotalnum;
          newcell.setcellvalue(doubv);
          break;
         default:
          newcell.cellstyle = styletotalstr;
          newcell.setcellvalue("");
          break;
        }
       }
       #endregion
 
       // 合并合计
       cellrangeaddress region0 = new cellrangeaddress(rowindex, rowindex, 0, 2); // 合并合计
       sheet.addmergedregion(region0);
 
       end0++;
       rowindex++;
      }
      #endregion
      temp0 = celltext0;
     }
     #endregion
 
     // 重新赋值
     start0 = rowindex;
     end0 = rowindex;
     start1 = rowindex;
     end1 = rowindex;
    }
    else // 第1列值没有变化
    {
     end0++;
     // 判断第2列是否有变化
     string celltext1 = source.rows[i][cellkeys[1]].tostring();
     if (celltext1 != temp1) // 第1列没变,第2列变化
     {
      #region 第2列要合并
      if (mergecolumns > 1) // 第2列要合并
      {
       if (start1 != end1) // 开始行和结束行不相同,才进行合并
       {
        cellrangeaddress region1 = new cellrangeaddress(start1, end1, 1, 1); // 合并第二列
        sheet.addmergedregion(region1);
       }
 
       #region 第2列加小计
       if (istotal) // 加小计
       {
        if (!isconver) sheet.shiftrows(rowindex, sheet.lastrownum, 1, true, false); // 不覆盖,数据向下移
 
        irow rowtotal1 = sheet.createrow(rowindex);
        //创建列并插入数据
        #region 插入小计数据
        for (int index = 0; index < cellcount; index++)
        {
         object obj1;
         icell newcell = rowtotal1.createcell(index);
         if (index == 0) //第1列
         {
          newcell.cellstyle = styletotalstr;
          newcell.setcellvalue(temp0);
          continue;
         }
         if (index == 1) // 第2列
         {
          newcell.cellstyle = styletotalstr;
          newcell.setcellvalue("小计");
          continue;
         }
 
         // 其它列数据,数值进行汇总
         switch (source.columns[cellkeys[index]].datatype.tostring())
         {
          case "system.int16": //整型
          case "system.int32":
          case "system.int64":
          case "system.byte":
           obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' and {2} = '{3}' ", cellkeys[0], temp0, cellkeys[1], temp1));
           int intv = 0;
           int.tryparse(obj1.tostring(), out intv);
           newcell.cellstyle = styletotalnum;
           newcell.setcellvalue(intv);
           break;
          case "system.decimal": //浮点型
          case "system.double":
          case "system.single":
           obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' and {2} = '{3}' ", cellkeys[0], temp0, cellkeys[1], temp1));
           double doubv = 0;
           double.tryparse(obj1.tostring(), out doubv);
           newcell.cellstyle = styletotalnum;
           newcell.setcellvalue(doubv);
           break;
          default:
           newcell.cellstyle = styletotalstr;
           newcell.setcellvalue("");
           break;
         }
        }
        #endregion
        // 合并小计
        cellrangeaddress region0 = new cellrangeaddress(rowindex, rowindex, 1, 2); // 合并小计
        sheet.addmergedregion(region0);
 
        end0++;
        rowindex++;
       }
       temp1 = celltext1; // 要合并,才进行重新赋值
       start1 = rowindex;
       end1 = rowindex;
       #endregion
      }
      #endregion
     }
     else // 第1列值没变,第2列也没变
      end1++;
    }
 
    // 插入当前数据
    row = sheet.createrow(rowindex);
    #region 创建行并插入当前记录的数据
    //创建行并插入当前记录的数据
    for (int index = 0; index < cellcount; index++)
    {
     icell cell = row.createcell(index);<br>
     string strvalue = !(source.rows[i][cellkeys[index]] is dbnull) ? source.rows[i][cellkeys[index]].tostring() : string.empty; // 取值
     switch (source.columns[cellkeys[index]].datatype.tostring())
     {
      case "system.int16": //整型
      case "system.int32":
      case "system.int64":
      case "system.byte":
       int intv = 0;
       int.tryparse(strvalue, out intv);
       cell.cellstyle = stylenum;
       cell.setcellvalue(intv);
       break;
      case "system.decimal": //浮点型
      case "system.double":
      case "system.single":
       double doubv = 0;
       double.tryparse(strvalue, out doubv);
       cell.cellstyle = stylenum;
       cell.setcellvalue(doubv);
       break;
      default:
       cell.cellstyle = stylestr;
       cell.setcellvalue(strvalue);
       break;
     }
    }
    #endregion
    // 下移一行
    rowindex++;
   }
 
   // 最后一条记录的合计
   #region 对第2列进行合并
   if (mergecolumns > 1) // 对第2列合并
   {
    if (start1 != end1) // 开始行和结束行不等,进行合并
    {
     cellrangeaddress region1 = new cellrangeaddress(start1, end1, 1, 1); // 合并第二列
     sheet.addmergedregion(region1);
    }
 
    #region 第2列加小计
    if (istotal) // 加小计
    {
     if (!isconver) sheet.shiftrows(rowindex, sheet.lastrownum, 1, true, false); // 不覆盖,数据向下移
 
     irow rowtotal1 = sheet.createrow(rowindex);
     //创建列并插入数据
     #region 插入小计数据
     for (int index = 0; index < cellcount; index++)
     {
      object obj1;
      icell newcell = rowtotal1.createcell(index);
      #region 列值处理
      if (index == 0) //第1列
      {
       newcell.cellstyle = styletotalstr;
       newcell.setcellvalue(temp0);
       continue;
      }
      if (index == 1) // 第2列
      {
       newcell.cellstyle = styletotalstr;
       newcell.setcellvalue("小计");
       continue;
      }
 
      // 其它列数据,数值进行汇总
      switch (source.columns[cellkeys[index]].datatype.tostring())
      {
       case "system.int16": //整型
       case "system.int32":
       case "system.int64":
       case "system.byte":
        obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' and {2} = '{3}' ", cellkeys[0], temp0, cellkeys[1], temp1));
        int intv = 0;
        int.tryparse(obj1.tostring(), out intv);
        newcell.cellstyle = styletotalnum;
        newcell.setcellvalue(intv);
        break;
       case "system.decimal": //浮点型
       case "system.double":
       case "system.single":
        obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' and {2} = '{3}' ", cellkeys[0], temp0, cellkeys[1], temp1));
        double doubv = 0;
        double.tryparse(obj1.tostring(), out doubv);
        newcell.cellstyle = styletotalnum;
        newcell.setcellvalue(doubv);
        break;
       default:
        newcell.cellstyle = styletotalstr;
        newcell.setcellvalue("");
        break;
      }
      #endregion
     }
     #endregion
     // 合并小计
     cellrangeaddress region0 = new cellrangeaddress(rowindex, rowindex, 1, 2); // 合并小计
     sheet.addmergedregion(region0);
 
     rowindex++;
     end0++;
    }
    #endregion
   }
   #endregion
 
   #region 对第1列合并
   if (mergecolumns > 0) // 对第1列合并
   {
    if (start0 != end0) // 开始行和结束行不等,进行合并
    {
     cellrangeaddress region1 = new cellrangeaddress(start0, end0, 0, 0); // 合并第二列
     sheet.addmergedregion(region1);
    }
 
    #region 第1列加合计
    if (istotal) // 加合计
    {
     if (!isconver) sheet.shiftrows(rowindex, sheet.lastrownum, 1, true, false); // 不覆盖,数据向下移
 
     irow rowtotal0 = sheet.createrow(rowindex);
     //创建列并插入数据
     #region 插入合计数据
     for (int index = 0; index < cellcount; index++)
     {
      object obj1;
      icell newcell = rowtotal0.createcell(index);
      #region 列值处理
      if (index == 0) //第1列
      {
       newcell.cellstyle = styletotalstr;
       newcell.setcellvalue("合计");
       continue;
      }
      if (index == 1) // 第2列
      {
       newcell.cellstyle = styletotalstr;
       newcell.setcellvalue("");
       continue;
      }
 
      // 其它列数据,数值进行汇总
      switch (source.columns[cellkeys[index]].datatype.tostring())
      {
       case "system.int16": //整型
       case "system.int32":
       case "system.int64":
       case "system.byte":
        obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' ", cellkeys[0], temp0));
        int intv = 0;
        newcell.cellstyle = styletotalnum;
        int.tryparse(obj1.tostring(), out intv);
        newcell.setcellvalue(intv);
        break;
       case "system.decimal": //浮点型
       case "system.double":
       case "system.single":
        obj1 = source.compute(string.format("sum({0})", cellkeys[index]), string.format("{0} = '{1}' ", cellkeys[0], temp0));
        double doubv = 0;
        double.tryparse(obj1.tostring(), out doubv);
        newcell.cellstyle = styletotalnum;
        newcell.setcellvalue(doubv);
        break;
       default:
        newcell.cellstyle = styletotalstr;
        newcell.setcellvalue("");
        break;
      }
      #endregion
     }
     #endregion
 
     // 合并合计
     cellrangeaddress region0 = new cellrangeaddress(rowindex, rowindex, 0, 2); // 合并合计
     sheet.addmergedregion(region0);
 
    }
    rowindex++;
    #endregion
   }
   #endregion
 
 
 
   #region 进行汇总 - 加总计     
   if (addalltotal) // 加总计
   {
    if (!isconver) sheet.shiftrows(rowindex, sheet.lastrownum, 1, true, false); // 不覆盖,数据向下移
 
    irow rowtotal0 = sheet.createrow(rowindex);
    //创建列并插入数据
    #region 插入总计数据
    for (int index = 0; index < cellcount; index++)
    {
     object obj1;
     icell newcell = rowtotal0.createcell(index);
     #region 列值处理
     if (index == 0) //第1列
     {
      newcell.cellstyle = styletotalstr;
      newcell.setcellvalue("总计");
      continue;
     }
     if (index == 1) // 第2列
     {
      newcell.cellstyle = styletotalstr;
      newcell.setcellvalue("");
      continue;
     }
 
     // 其它列数据,数值进行汇总
     switch (source.columns[cellkeys[index]].datatype.tostring())
     {
      case "system.int16": //整型
      case "system.int32":
      case "system.int64":
      case "system.byte":
       obj1 = source.compute(string.format("sum({0})", cellkeys[index]), "");
       int intv = 0;
       int.tryparse(obj1.tostring(), out intv);
       newcell.cellstyle = styletotalnum;
       newcell.setcellvalue(intv);
       break;
      case "system.decimal": //浮点型
      case "system.double":
      case "system.single":
       obj1 = source.compute(string.format("sum({0})", cellkeys[index]), "");
       double doubv = 0;
       double.tryparse(obj1.tostring(), out doubv);
       newcell.cellstyle = styletotalnum;
       newcell.setcellvalue(doubv);
       break;
      default:
       newcell.cellstyle = styletotalstr;
       newcell.setcellvalue("");
       break;
     }
     #endregion
    }
    #endregion
 
    // 合并总计
    cellrangeaddress region0 = new cellrangeaddress(rowindex, rowindex, 0, 2); // 合并总计
    sheet.addmergedregion(region0);
 
   }
   #endregion
 
  }
  return save2xls(strfilename, workbook); // 保存为xls文件
 }
 catch (exception ex)
 {
  // filehelper.writeline(logfile, "处理数据异常:" + ex.message);
  // msg = ex.message;
 }
 return bn;
}

保存文件的代码:

public static bool save2xls(string filename, iworkbook workbook)
{
 bool bn = false;
 try
 {
  filestream fs = new filestream(filename, filemode.openorcreate);
 
  memorystream ms = new memorystream();
  workbook.write(ms);
  binarywriter w = new binarywriter(fs);
  w.write(ms.toarray());
  fs.close();
  ms.close();
 
  bn = true;
 }
 catch(exception ex)
 {
  //filehelper.writeline(logfile, "保存文件异常:" + ex.message);
 }
 return bn;
}

以上这篇npoi实现两级分组合并功能(示例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

上一篇:

下一篇: