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

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

概述NPOI版本:2.2.1.0最近公司有这样的需求:统计每个部门下面,多个费用使用情况。部门存在多级,但统计时,只需统计到2级,2级以下的,归到第2级的部门下。并且要求,第2级部门有个小计,第1级部门需要有个合计。最

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); // 合并第二列       sheet.AddMergedRegion(region1);      }       #region 第2列加小计      if (isTotal) // 加小计      {       if (!isConver) sheet.ShiftRows(rowIndex,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})",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,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); // 合并第二列       sheet.AddMergedRegion(region0);      }       #region 第1列加合计      if (isTotal) // 加合计      {       if (!isConver) sheet.ShiftRows(rowIndex,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})",string.Format("{0} = '{1}' ",temp0));          int intV = 0;          int.TryParse(obj1.ToString(),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,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,1); // 合并第二列        sheet.AddMergedRegion(region1);       }        #region 第2列加小计       if (isTotal) // 加小计       {        if (!isConver) sheet.ShiftRows(rowIndex,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})",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})",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,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,1); // 合并第二列     sheet.AddMergedRegion(region1);    }     #region 第2列加小计    if (isTotal) // 加小计    {     if (!isConver) sheet.ShiftRows(rowIndex,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})",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})",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,2); // 合并小计     sheet.AddMergedRegion(region0);      rowIndex++;     end0++;    }    #endregion   }   #endregion    #region 对第1列合并   if (mergeColumns > 0) // 对第1列合并   {    if (start0 != end0) // 开始行和结束行不等,进行合并    {     CellRangeAddress region1 = new CellRangeAddress(start0,0); // 合并第二列     sheet.AddMergedRegion(region1);    }     #region 第1列加合计    if (isTotal) // 加合计    {     if (!isConver) sheet.ShiftRows(rowIndex,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})",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})",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,2); // 合并合计     sheet.AddMergedRegion(region0);     }    rowIndex++;    #endregion   }   #endregion      #region 进行汇总 - 加总计        if (addAllTotal) // 加总计   {    if (!isConver) sheet.ShiftRows(rowIndex,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})","");       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})","");       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,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实现两级分组合并功能(示例讲解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程小技巧。

总结

以上是内存溢出为你收集整理的NPOI实现两级分组合并功能(示例讲解)全部内容,希望文章能够帮你解决NPOI实现两级分组合并功能(示例讲解)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1253632.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存