zoukankan      html  css  js  c++  java
  • abp框架Excel导出——基于vue

    abp框架Excel导出——基于vue

    1.技术栈

    1.1 前端采用vue,官方提供

    UI套件用的是iview

    1.2 后台是abp——aspnetboilerplate

    即abp v1,https://github.com/aspnetboilerplate/aspnetboilerplate。 下载时选择的是net core 3.1。

    2. Excel导出需求

    管理后台系统,主要以图表统计形式归档数据,用户经常会有Excel导出报表的需求。可以以文件形式保存,更加地直观,符合使用习惯。

    3. 升级日志Excel导出

    物联网中的设备是核心资产,而维护设备经常需要一些升级割接操作,因此,升级日志(升级失败,升级成功,升级时间)等是用户比较关心的数据。

    4. 技术实现方案

    4.1 后台

    4.1.1 EPPlus导出静态方法

    需要nuget安装EPPlus.Core库。运用了委托的方法方便地实现了对导出表单进行添加标题,填充内容数据,渲染单元格样式,委托的一大优势就是方便调用,层次感很明显。该方法如果看得还不是很明白,请耐心继续往下看。

        public abstract class EPPlusExcelExporterBase : AbpServiceBase
        {
            protected EPPlusExcelExporterBase( )
            {}
            public static byte[] CreateExcelPackage(string fileName, Action<ExcelPackage> creator)
            {
                var excelPackage = new ExcelPackage();
                creator(excelPackage);
                using (var stream = new MemoryStream())
                {
                    excelPackage.SaveAs(stream);
                    excelPackage.Dispose();
                    return stream.ToArray();
                }
            }
    
            public static void AddHeader(ExcelWorksheet sheet, params string[] headerTexts)
            {
                if (headerTexts.IsNullOrEmpty())
                {
                    return;
                }
                for (var i = 0; i < headerTexts.Length; i++)
                {
                    AddHeader(sheet, i + 1, headerTexts[i]);
                }
            }
    
            protected static void AddHeader(ExcelWorksheet sheet, int columnIndex, string headerText)
            {
                sheet.Cells[1, columnIndex].Value = headerText;
                sheet.Cells[1, columnIndex].Style.Font.Bold = true;
            }
    
            public static void AddObjects<T>(ExcelWorksheet sheet, int startRowIndex, IList<T> items, params Func<T, object>[] propertySelectors)
            {
                if (items.IsNullOrEmpty() || propertySelectors.IsNullOrEmpty())
                {
                    return;
                }
    
                for (var i = 0; i < items.Count; i++)
                {
                    for (var j = 0; j < propertySelectors.Length; j++)
                    {
                        sheet.Cells[i + startRowIndex, j + 1].Value = propertySelectors[j](items[i]);
                    }
                }
            }
        }
    

    4.1.2 生成升级日志列表

    此部分代码与主业务相关,因为原本业务与区域权限有关,简化起见,故删除其他无关代码,主要就是从数据库获取了升级列表,并且按照了升级时间进行了倒序排列。读者不同的业务可进行不同操作。需要转义的转义,联表的联表,过滤的过滤,排序的排序。

    var dbQuery = from upgradeLog in _fsuUpgradeResultRepository.GetAll();
    
    var UpgradeLogDtoList = await dbQuery
         .OrderByDescending(x => x.Updatetime)
         .ToListAsync();
    
    

    4.1.3 将升级日志列表放到Excel导出静态方法中去

               var data= EPPlusExcelExporterBase.CreateExcelPackage(
                    "UpgradeLog.xlsx",
                    excelPackage =>
                    {
                        var sheet = excelPackage.Workbook.Worksheets.Add("UpgradeLog");
                        sheet.OutLineApplyStyle = true;
    
                        EPPlusExcelExporterBase.AddHeader(
                            sheet,
                            "Fsu资产编码",
                            "升级结果",
                            "是否反馈",
                            "Fsu IP地址",
                            "更新时间"
                            );
    
                        EPPlusExcelExporterBase.AddObjects(
                            sheet, 2, UpgradeLogDtoList,
                            _ => _.FsuId,
                            _ => _.Result,
                            _ => _.IsReport,
                            _ => _.FsuIp,
                            _ => _.Updatetime
                            );
    
                        //Formatting cells
                        var UpdatetimeColumn = sheet.Column(5);
                        UpdatetimeColumn.Style.Numberformat.Format = "yyyy-mm-dd-hh:mm:ss";
    
                        for (var i = 1; i <= 5; i++)
                        {
                            sheet.Column(i).AutoFit();
                        }
                    });
    

    委托里面流程分下:添加报表表头,添加内容,设置显示样式(时间格式),添加样式(设置单元格自适应内容大小)。
    通过CreateExcelPackage方法放回了文件比特流。

    4.1.4 abp框架中前后端分离模式文件流传输

    以FileResult形式返回前端传来的请求。需要注意的是FileResult是 Microsoft.AspNetCore.Mvc.Core中的一个类。

            public async Task<FileResult> GetUpgradeReport()
            {
     var dbQuery = from upgradeLog in _fsuUpgradeResultRepository.GetAll();
    
                var UpgradeLogDtoList = await dbQuery
                     .OrderByDescending(x => x.Updatetime)
                     .ToListAsync();
    
                foreach (var item in UpgradeLogDtoList)
                {
                    ConvertDto(item);//对升级结果,是否上报铁塔平台进行解析
                }
    
               var data= EPPlusExcelExporterBase.CreateExcelPackage(
                    "UpgradeLog.xlsx",
                    excelPackage =>
                    {
                        var sheet = excelPackage.Workbook.Worksheets.Add("UpgradeLog");
                        sheet.OutLineApplyStyle = true;
    
                        EPPlusExcelExporterBase.AddHeader(
                            sheet,
                            "Fsu资产编码",
                            "升级结果",
                            "是否反馈",
                            "Fsu IP地址",
                            "更新时间"
                            );
    
                        EPPlusExcelExporterBase.AddObjects(
                            sheet, 2, UpgradeLogDtoList,
                            _ => _.FsuId,
                            _ => _.Result,
                            _ => _.IsReport,
                            _ => _.FsuIp,
                            _ => _.Updatetime
                            );
    
                        //Formatting cells
                        var UpdatetimeColumn = sheet.Column(5);
                        UpdatetimeColumn.Style.Numberformat.Format = "yyyy-mm-dd-hh:mm:ss";
    
                        for (var i = 1; i <= 5; i++)
                        {
                            sheet.Column(i).AutoFit();
                        }
                    });
    
                var fileContentResult = new FileContentResult(data, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                {
                    FileDownloadName = "升级日志报表.xlsx"
                };
    
                return fileContentResult;
            }
    

    4.2 前端

    4.2.1 vuex的action中添加请求方法

    代码如下:

        actions = {
            async getUpgradeLogReport(context: ActionContext<UpgradeLogState, any>) {
                let data= await Ajax.get('/api/services/app/Upgrade/GetUpgradeReport',{
                    responseType: 'blob',
                    headers: {
                      'Content-Type': 'application/json'
                    }});
                    return data;
            }
        }
    
    

    告诉后台以blob形式返回。当然请求方法你也可以直接普通形式封装,不一定封装在vuex里,这里封装在vuex的一个好处是有些状态数据可以保存在vuex,所有页面可以共享该数据。

    4.2.2 upgradeLog.vue升级页面

    4.2.2.1 增加下载方法

       async  downloadUpgradeLogReport(){
           await this.$store.dispatch({
          type: "upgradelog/getUpgradeLogReport"
        }).then(res => {
          if (res.status == "200") {
            var excelBlob = new Blob([res.data], {
              type: "application/vnd.ms-excel"
            });
            var fileName = "升级日志报表.xlsx";
            
              var oa = document.createElement("a");
              oa.href = URL.createObjectURL(excelBlob);
              oa.download = fileName;
              document.body.appendChild(oa);
              oa.click();
            
          }
        });
        }
    

    创建一个blob对象,以创建url方式将此对象下载。

    4.2.2.2 点击导出报表按钮调用下载方法

     <Button @click="downloadUpgradeLogReport()">导出升级日志报表</Button>
    

    5. 最终效果

    5.1 点击按钮

    5.2 报表展示

    6.小结

    • 笔者下载使用过多个开源方案导出Excel,此种方式方法比较轻量,使用比较简洁;
    • 在abp中返回Excel的形式需要思考,因为如果无法继承ControllerBase,就无法使用ActionResult这种万能返回形式(C#中只能继承一个基类,可以继承多个接口);
    • vue中ajax接收Excel返回数据时需要注意设置返回类型为Blob,否则将会下载不成功;
    • 这里Excel导出是借鉴了Abp Zero 8.1的思路,他是类以瞬时模式注入容器,我是写成了静态方法。但是Abp Zero Excel导出的思路大有不同,首先是生成文件在Cache里,然后返回文件GUID(Token),用户再拿着GUID(Token)通过fileController从cache导出需要下载的文件。缓存有效期1分钟,目的是为了防止有人拿到链接攻击,不停下载。

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
    本文链接:https://www.cnblogs.com/JerryMouseLi/p/13399027.html
  • 相关阅读:
    ServletConfig对象
    乱码问题
    response request
    mysql
    数据库三范式 简单理解
    会话 cookie
    ServletContext对象
    读取工程中的配置文件
    Servlet与缓存
    C#捕获异常崩溃时
  • 原文地址:https://www.cnblogs.com/JerryMouseLi/p/13399027.html
Copyright © 2011-2022 走看看