• 【C#】Excel导出合并行和列并动态加载行与列


    简单的Excel导出比较好做,只要设置表头,循环在表格中赋值添加数据即可,但是如果表头是不固定的,并且个数是不确定的,这就需要根据查询出数据的特点来添加导出了。

        导出效果图:

    如上图所示,商品的个数是不确定的,时间的月份个数也是不确定的,所以简单的通过模板是不可以的。并且数据库中查询出的信息是每个商品不同时间的信息,所以查询出的数据相同时间的可能有多条,一个商品在不同的时间分布,所以也可以是多条。

    代码部分:

    [csharp] view plain copy
     
    1. public int DataTableToExcelByMProduct(DataTable dt_model, string sheetName)  
    2.         {  
    3.             workbook = new HSSFWorkbook();  
    4.             ISheet sheet = workbook.CreateSheet(sheetName);  
    5.             IRow row = null;  
    6.             ICell cell = null;  
    7.             //样式  
    8.             ICellStyle style = workbook.CreateCellStyle();  
    9.             style.Alignment = HorizontalAlignment.CENTER;//设置单元格的样式:水平对齐居中  
    10.             style.VerticalAlignment = VerticalAlignment.CENTER;//设置单元格样式:垂直对齐居中  
    11.             IFont font = workbook.CreateFont();//新建一个字体样式对象  
    12.             font.Boldweight = short.MaxValue;  
    13.             style.SetFont(font);  
    14.             DateTime nowTime = DateTime.Now;  
    15.               
    16.             //商品编码数量  
    17.             var dtgroup=(from p in dt_model.AsEnumerable()  
    18.             group p by new {  
    19.                 RealName=p.Field<string>("RealName"),  
    20.                 Name=p.Field<string>("Name")                
    21.             }into g  
    22.             select new {  
    23.                 RealName=g.Key.RealName,  
    24.                 Name=g.Key.Name,  
    25.                 counts=g.Count()  
    26.             }).ToList();  
    27.             //数据表头,时间  
    28.               
    29.              row = sheet.CreateRow(0);  
    30.             cell = row.CreateCell(0);  
    31.             cell.SetCellValue("时间");  
    32.             cell.CellStyle = style;  
    33.             //CellRangeAddress四个参数:起始行、结束行、起始列、结束列  
    34.             sheet.AddMergedRegion(new CellRangeAddress(0, 2, 0, 0));  
    35.               
    36.             //进出口岸  1,1,2,口岸数*2  
    37.             cell = row.CreateCell(1);  
    38.             cell.SetCellValue(“进出口商品编码”);  
    39.             cell.CellStyle = style;  
    40.             //CellRangeAddress四个参数:起始行、结束行、起始列、结束列  
    41.             sheet.AddMergedRegion(new CellRangeAddress(0, 0, 1, 2*dtgroup.Count));  
    42.               
    43.             //商品拼接  
    44.              row = sheet.CreateRow(1);  
    45.             row = sheet.CreateRow(2);  
    46.             for( int c=0;c<dtgroup.Count;c++)  
    47.             {  
    48.                 //创建进出口岸单元格,开始  
    49.                  cell = row.CreateCell(2*c+1);  
    50.                  cell.SetCellValue(dtgroup[c].RealName);  
    51.                  cell.CellStyle = style;  
    52.             //CellRangeAddress四个参数:起始行、结束行、起始列、结束列  
    53.                 sheet.AddMergedRegion(new CellRangeAddress(1, 1, 2*c+1, 2*c+2));  
    54.                   
    55.                 //创建进口单元格   
    56.                 //创建一列  
    57.                 cell=row.CreateCell(2*c+1);  
    58.                 cell.SetCellValue("进口");  
    59.                 cell=row.CreateCell(2*c+2);     
    60.                 cell.SetCellValue("出口");      
    61.             }  
    62.               
    63.             var AllYearCount=(from p in dt_model.AsEnumerable()  
    64.                               group p by new {Year_Month=p.Field<string>("Year_Month")} into m  
    65.                               select new   
    66.                               {  
    67.                                   YearMonth =m.Key.Year_Month,  
    68.                                   AllYearCount=m.Count()  
    69.                               }).ToList();  
    70.             //年份  
    71.             for (int i=0;i < AllYearCount.Count;i++)  
    72.             {  
    73.                 row=sheet.CreateRow(i+3);  
    74.                 cell=row.CreateCell(0);  
    75.                 string YearMonth=AllYearCount[i].YearMonth;  
    76.                   
    77.                 int month =SafeConvert.ToInt16(YearMonth.Substring(4,2));  
    78.                 cell.SetCellValue("1-"+month+"月");  
    79.   
    80.               
    81.             //贸易额对碰情况  
    82.                 for (int j=0;j<dtgroup.Count;j++)  
    83.                 {  
    84.                     var items=dt_model.AsEnumerable().Where(a=>a.Field<string>("Year_Month")==AllYearCount[i].YearMonth && a.Field<string>("Name")==dtgroup[j].Name).ToList();  
    85.                     if(items.Count>0)  
    86.                     {  
    87.                         cell=row.CreateCell(2*j+1);  
    88.                         cell.SetCellValue(items[0].Field<string>("Export_Desn"));  
    89.                         cell=row.CreateCell(2*j+2);  
    90.                         cell.SetCellValue(items[0].Field<string>("Import_Desn"));  
    91.                     }  
    92.                     else  
    93.                     {  
    94.                         cell=row.CreateCell(2*j+1);  
    95.                         cell.SetCellValue("");  
    96.                         cell=row.CreateCell(2*j+2);  
    97.                         cell.SetCellValue("");  
    98.                     }  
    99.                   
    100.                 }  
    101.             }  
    102.             using(FileStream fsm=File.Open(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite))  
    103.             {  
    104.                 workbook.Write(fsm);  
    105.                 fsm.Close();  
    106.             }  
    107.             return 1;  
    108.               
    109.         }  
    110.               



       其实代码的核心部分就是创建行与列并且为表格赋值,如果已经创建了行就不用创建了,就像这个例子中的时间单元格已经创建了一次行,这样“进出口商品编码”就不用再次创建行了。但是创建了行必须要创建列,列是在行的基础上创建的,所以即使上一行已经创建了列,下一行还是需要重新创建的。

    小结:

         这个方法传入的是datatable和表格名称,如果我们返回的数据不是直接输出的需要做一些处理,我们可以采用给datatable增加字段的方法,将我们想要的结果存储到新加的字段中。

         导出的思想是一样的,都是要循环行和列,在表格中赋值,不同的是从哪里开始赋,把不同的地方解决,导出也一样easy!

  • 相关阅读:
    php redis 延迟队列
    mysql 分库分表
    c++ 指针与引用
    c++ 格式化字符串
    c++ 在class A的构造函数中初始化另一个类的对象(调用B::B())时报错: error: no matching function for call to 'B:B()'
    c++ 正则匹配
    c++ 格式化时间
    c++ 读写文件
    StampedLock
    Mock单元测试入门
  • 原文地址:https://www.cnblogs.com/amylis_chen/p/8462489.html
Copyright © 2020-2023  润新知