.NET Core 使用Web API导出Excel并合并单元格

 

创建一个.NET Web API项目,这里使用的是.NET Core 3.1框架,导出Excel这里使用开源组件NPOI,常规的导入导出,肯定得不陌生,今天,我们讲一讲,复杂的单元格合并,样式如下:

 可以看到,设备类型,这一块是一个合并的,那么在.NET Core中,如何实现呢?通过SQL语句,我们得到如下的数据:



 

  1.  我们首先第一步,查询出数据,记作【equipmentResps】
     
     List<EquipmentResp> equipmentResps = _equipmentService.GetEquipmentResps().ToList();
    
  2. 使用NPOI手动创建一个Excel,引入NPOI,本次使用NPOI, Version=2.5.3.0

    完整导出代码如下:
     
    //创建Workbook
    IWorkbook workbook = new HSSFWorkbook();
    //创建一个sheet
    workbook.CreateSheet("设备管理");
    //设置一个随机用户名
    string path = $"{Guid.NewGuid().ToString()}.xls";
    //找到当前项目所在文件夹,需要注入IWebHostEnvironment
    string filePath = $"{_webHostEnvironment.ContentRootPath}\\Export\\";
    if (!System.IO.Directory.Exists(filePath))
     {
       Directory.CreateDirectory(filePath);
     }
    using (FileStream fs = System.IO.File.Create(filePath + path))
    {
      ISheet sheet = workbook.GetSheetAt(0);//获取sheet
      IRow rowHeader = sheet.CreateRow(0);
       //创建头部
      rowHeader.CreateCell(0).SetCellValue("设备类型");
      rowHeader.CreateCell(1).SetCellValue("设备分类");
     rowHeader.CreateCell(2).SetCellValue("设备数量(台)"); rowHeader.CreateCell(3).SetCellValue("完好设备数量(台)");
    rowHeader.CreateCell(4).SetCellValue("完好率(%)");
    //创建头部样式和列宽度
     ICellStyle titleStyle = workbook.CreateCellStyle();
      titleStyle.Alignment = HorizontalAlignment.Center; // 居中
     IFont titleFont = workbook.CreateFont();
      titleFont.IsBold = true;
       titleFont.FontHeightInPoints = 12;
     titleFont.Color = HSSFColor.Black.Index;//设置字体颜色
        titleStyle.SetFont(titleFont);
    heet.GetRow(0).GetCell(0).CellStyle = titleStyle;
    sheet.GetRow(0).GetCell(1).CellStyle = titleStyle;
    sheet.GetRow(0).GetCell(2).CellStyle = titleStyle;
    sheet.GetRow(0).GetCell(4).CellStyle = titleStyle;
    sheet.SetColumnWidth(0, 3000);
    sheet.SetColumnWidth(1, 3000);
    sheet.SetColumnWidth(2, 5000);
    sheet.SetColumnWidth(3, 5000);
    sheet.SetColumnWidth(4, 4000);
        //创建内容样式
    ICellStyle style = workbook.CreateCellStyle();
    style.Alignment = HorizontalAlignment.Center;
    style.VerticalAlignment = VerticalAlignment.Center; ;//垂直居中   
    IFont font = workbook.CreateFont();
    font.IsBold = false;
    font.FontHeightInPoints = 12;
    font.Color = HSSFColor.Black.Index;
     style.SetFont(font);
    //赋值
    for (int i = 0; i < equipmentResps.ToList().Count(); i++)
     {
    IRow rowData = sheet.CreateRow(i + 1);
    rowData.CreateCell(0).SetCellValue(equipmentResps[i].type);
    if (!keyValues.ContainsKey(equipmentResps[i].type))
    {
      keyValues.Add(equipmentResps[i].type, equipmentResps[i].type);
    }
    rowData.GetCell(0).CellStyle = style;
    rowData.CreateCell(1).SetCellValue(equipmentResps[i].Grade);
    rowData.GetCell(1).CellStyle = style; rowData.CreateCell(2).SetCellValue(equipmentResps[i].Number);
    rowData.GetCell(2).CellStyle = style;
    rowData.CreateCell(3).SetCellValue(equipmentResps[i].perfectNumber);
    rowData.GetCell(3).CellStyle = style;
    rowData.CreateCell(4).SetCellValue(equipmentResps[i].IntactRate.ToString() + "%");
    rowData.GetCell(4).CellStyle = style;
     }
      foreach (var item in keyValues)
    {
        int start = equipmentResps.IndexOf(equipmentResps.FirstOrDefault(x => x.type == item.Key));
        int end = equipmentResps.IndexOf(equipmentResps.LastOrDefault(x => x.type == item.Key));
         sheet.AddMergedRegion(new CellRangeAddress(start + 1, end + 1, 0, 0));
    }
       MemoryStream ms = new MemoryStream();
       workbook.Write(ms);
       ms.Seek(0, SeekOrigin.Begin);
       string fileName = $"{DateTime.Now.ToString("yyyy-MM")}设备完好率.xls";
       return File(ms, "application/vnd.ms-excel", fileName);
     }

     
  3. 合并单元格子解析

通过NPOI官网,我们可以看到,合并单元格,需要使用AddMergedRegion函数,AddMergedRegion有四个参数,

分别是:【开始行、结束行、开始列、结束列】,其实很好记,就是从哪一行开始,合并到哪一行,包含那些列,通过对上面excel分析,我们得出【电气设备】在第2行,记作N,需要合并3行,即N+1,其余需要合并的以此类推,我们可以通过代码做如下分析:


// Dictionary<string, string> keyValues = new Dictionary<string, string>();
//keyValues 里面其实只记录了type的值,通过循环这个值,进行合并
foreach (var item in keyValues)
{
//IndexOf 找到列表出现相同信息的下标,使用FirstOrDefault是为了找到第一次出现此数据的行号
 int start = equipmentResps.IndexOf(equipmentResps.FirstOrDefault(x => x.type == item.Key));
//同样的方式,通过LastOrDefault是为了找到第=最后一次出现此数据的行号
 int end = equipmentResps.IndexOf(equipmentResps.LastOrDefault(x => x.type == item.Key));
//然后使用NPOI合并的方式进行合并,因为本次我们都是出现在第一列(excel从0开始),所以后面两个参数都
//是0
 sheet.AddMergedRegion(new CellRangeAddress(start + 1, end + 1, 0, 0));
}

前端可以使用<a>标签,比如【<a href='我们部署的接口地址'>导出</a>】可直接导出,也可以使用请求接口,然后回调的方式进行导出。
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值