excel自定义导出实现(使用反射)

news2024/11/24 11:27:21

前言

项目中接到需求,需要对导出的字段进行自定义导出 ,用户可在前端选择自定义导出的字段(如图),实现过程做以下记录,仅供参考;
在这里插入图片描述

思路

跟前端约定好所有要导出的字段名称(headName)跟对应的实体名称(fieldName),勾选导出的字段后就传字段到后端,后端根据反射去匹配要导出的字段最后输出;

实现

  • 约定导出的字段名称、实体名
    在这里插入图片描述
  • 导出字段实体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApproveExcelHeader {
    /**
     * 要导出的字段名称
     */
    private String fieldName;
    /**
     * 要导出的表头名称
     */
    private String headName;
    /**
     * 是否导出
     */
    private String disabled;
}
  • 定义接口
 /**
     * 根据前端传入的字段自定义导出的列
     * @param dto
     * @throws IOException
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    @ApiOperation("导出")
    @PostMapping("/exportExcel")
    public void exportExcel(@RequestBody aqglRiskQuarterApproveDto dto, HttpServletResponse response) throws IOException, NoSuchFieldException, IllegalAccessException {
        Assert.notNull(dto.getRiskCycle(), "周期不能为空!");
        List<ApproveExcelHeader > exportFiledList =dto.getExportFiled();
        List<String> headNamelist = exportFiledList.stream().map(ApproveExcelHeader ::getHeadName).collect(Collectors.toList());
        if(headNamelist.isEmpty()){
            throw new BusinessException("要导出的字段不能为空!");
        }
        List<Map<String, Object>> exportList = approveService.riskQuarterRecognitionExportList(dto);
        List<String> headNameList = exportFiledList.stream().map(ApproveExcelHeader ::getHeadName).collect(Collectors.toList());
        String fileName ="导出文件名";
        ExportUtils.dynamicsExportExcel(fileName, headNameList, exportList,response);

    }
  • 处理类
  • 此处主要根据前端传进来的字段去查询出的字段利用反射匹配;
 public List<Map<String, Object>>riskQuarterRecognitionExportList(aqglRiskQuarterApproveDto dto) throws IllegalAccessException {      
        List<AqglRiskQuarterRecognitionExportVo> quarterRecognitionExportList = aqglRiskQuarterApproveMapper.riskQuarterRecognitionExportList(dto.getRiskCycle(), companyName, projectName, riskLevelCode, isPlanConditionCheck);
        List<Map<String, Object>> exportData = new ArrayList<>();
        if (!quarterRecognitionExportList.isEmpty()) {
            List<AqglQuarterApproveExcelHeader> exportFiledList = dto.getExportFiled();
            try {
                for (AqglRiskQuarterRecognitionExportVo quarterRecognitionExportVo : quarterRecognitionExportList) {
                	//此处根据反射去匹配查询出的所有字段跟前端传进来的字段
                    Class<?> voClass = quarterRecognitionExportVo.getClass();
                    Map<String, Object> row = new HashMap<>();
                    for (AqglQuarterApproveExcelHeader header : exportFiledList) {
                        Field field = voClass.getDeclaredField(header.getFieldName());
                        field.setAccessible(true);
                       // String fieldValue = field.get(quarterRecognitionExportVo).toString();
                        row.put(header.getHeadName(), field.get(quarterRecognitionExportVo));
                    }
                    exportData.add(row);
                }
            } catch (NoSuchFieldException e) {
                throw new BusinessException("未匹配到导出字段:" + e.getMessage());
            }
        }else {
            throw new BusinessException("未获取到需要导出的数据!");
        }
        return exportData;
    }
  • 导出工具类(Workbook)
public static void dynamicsExportExcel(String fileName, List<String> headers, List<Map<String, Object>> data,HttpServletResponse response) throws IOException {
        Workbook workbook = new XSSFWorkbook(); // 创建工作簿
        Sheet sheet = workbook.createSheet("Sheet1"); // 创建工作表

        // sheet样式
        CellStyle sheetStyle = workbook.createCellStyle();
        sheetStyle.setBorderTop(BorderStyle.THIN); // 顶部边框
        sheetStyle.setBorderBottom(BorderStyle.THIN); // 底部边框
        sheetStyle.setBorderLeft(BorderStyle.THIN); // 左边边框
        sheetStyle.setBorderRight(BorderStyle.THIN); // 右边边框
        sheetStyle.setWrapText(true);  //设置自动换行
        sheetStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
        sheetStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        // 创建表头
        Row headerRow = sheet.createRow(0);
        headerRow.setHeight((short) 1000);
        //表头样式
        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setBorderTop(BorderStyle.THIN); // 顶部边框
        headerStyle.setBorderBottom(BorderStyle.THIN); // 底部边框
        headerStyle.setBorderLeft(BorderStyle.THIN); // 左边边框
        headerStyle.setBorderRight(BorderStyle.THIN); // 右边边框
        headerStyle.setWrapText(true);  //设置自动换行
        headerStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
        headerStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中
        //设置字体
        XSSFFont font = (XSSFFont) workbook.createFont();
        font.setBold(true); // 设置加粗
        headerStyle.setFont(font);


        for (int i = 0; i < headers.size(); i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers.get(i));
            cell.setCellStyle(headerStyle);

        }


        // 填充数据、设置表格样式
        for (int i = 0; i < data.size(); i++) {
            Row dataRow = sheet.createRow(i + 1);
            Map<String, Object> rowData = data.get(i);
            for (int j = 0; j < headers.size(); j++) {
                Cell cell = dataRow.createCell(j);
                cell.setCellStyle(sheetStyle);
                Object value = rowData.get(headers.get(j));
                if (value != null) {
                    cell.setCellValue(value.toString());
                }
            }
        }

        //设置列宽度
        for (int i = 0; i < headers.size(); i++) {
            sheet.setColumnWidth(i,18 * 256);
        }

        ServletOutputStream outputStream =null;
        try {
            // 写入文件
            String name = URLEncoder.encode(fileName+".xlsx", "UTF-8");
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition", "attachment;filename="+name);
            outputStream = response.getOutputStream();
            workbook.write(outputStream);

        } catch (IOException e) {
            e.printStackTrace();
            log.error("文件导出失败");
        } finally {
            try {
                workbook.close();
                log.info(fileName + "文件导出完成!");
            } catch (IOException e) {
                log.error("文件导出失败");
                e.printStackTrace();
            }
        }

    }
  • 导出的效果
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2229002.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

练习LabVIEW第十七题

学习目标&#xff1a; 刚学了LabVIEW&#xff0c;在网上找了些题&#xff0c;练习一下LabVIEW&#xff0c;有不对不好不足的地方欢迎指正&#xff01; 第十七题&#xff1a; 编写一个程序,用labview的信号生成函数产生一个三角波并显示在chart上,在编写例外一个程序读出数据…

【论文阅读】PGAN

1. WHY 问题 图像超分辨率一直是一个热门研究课题&#xff0c;具有重要的应用价值。基于生成对抗网络GAN的单幅图像超分辨率方法显示重建图像与人类视觉特征更一致。因此&#xff0c;基于 GAN 的网络优化已成为图像超分辨率的主流。然而&#xff0c;一些最新研究表明&#xf…

江协科技STM32学习- P28 USART串口数据包

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

C# Retry库

比如网络访问或硬件参数设置需要重试&#xff0c;可引用gunet上的Polly库。 同步方式&#xff08;每次重试有不同的时间间隔&#xff09; var polly Policy.Handle<Exception>().WaitAndRetry(new[] { new TimeSpan(0, 0, 1), new TimeSpan(0, 0, 2), new TimeSpan(0, …

Java避坑案例 - 线程池使用中的风险识别与应对

文章目录 线程池的基本概念创建线程池的注意事项实例1&#xff1a; newFixedThreadPool 使用无界队列&#xff0c;可能因任务积压导致 OOM实例2&#xff1a; newCachedThreadPool 会创建大量线程&#xff0c;可能因线程数量过多导致无法创建新线程。 线程池参数设置的最佳实践线…

基于SSM+微信小程序的社区垃圾回收管理系统(垃圾1)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于ssm微信小程序的社区垃圾回收管理系统&#xff0c;有管理员&#xff0c;回收员&#xff0c;用户三个角色。 1、管理员功能有个人中心&#xff0c;用户管理&#xff0c;回收员管理&am…

确保组织决策权清晰的有效策略

在组织中&#xff0c;明确的决策权、有效的沟通机制、权责明确的结构是确定和维护清晰决策权的关键要素。明确的决策权确保了每个成员知道自己的职责和权限&#xff0c;有效的沟通机制促进了信息的流通和理解&#xff0c;权责明确的结构则为组织的运作提供了清晰的框架。明确的…

SpringBoot3+SpringSecurity6基于若依系统整合自定义登录流程

SpringBoot3SpringSecurity6基于若依系统整合自定义登录流程 问题背景 在做项目时遇到了要对接统一认证的需求&#xff0c;但是由于框架的不兼容性&#xff08;我们项目是springboot3&#xff0c;jdk17&#xff0c;springsecurity6.1.5&#xff09;等因素&#xff0c;不得不使…

WPF+MVVM案例实战(十四)- 封装一个自定义消息弹窗控件(下)

文章目录 1、案例效果2、弹窗空间使用1.引入用户控件2、按钮命令实现 3、总结4、源代码获取 1、案例效果 2、弹窗空间使用 1.引入用户控件 打开 Wpf_Examples 项目&#xff0c;在引用中添加用户控件库&#xff0c;在 MainWindow.xaml 界面引用控件库&#xff0c;代码如下&…

【论文精读】ID-like Prompt Learning for Few-Shot Out-of-Distribution Detection

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;论文精读_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 注&#xff1a;下文…

PIDNet(语义分割)排坑

PIDNet训练自己的数据集 1. 前言2. 准备工作3. 配置环境4. 排坑过程4.1.1 configs增加了VOC文件夹 并在里面写了yaml参数文件4.1.2 加载VOC格式数据集的类4.1.3 train.py调试 1. 前言 paper小修时reviewer说baseline太老&#xff0c;所以对CVPR2023的PIDNet进行复现&#xff0…

Google Recaptcha V2 简单使用

最新的版本是v3&#xff0c;但是一直习惯用v2&#xff0c;就记录一下v2 的简单用法&#xff0c;以免将来忘记了 首先在这里注册你域名&#xff0c;如果是本机可以直接直接填 localhost 或127.0.0.1 https://www.google.com/recaptcha/about/ 这是列子 网站密钥&#xff1a;是…

autMan奥特曼机器人-内置Redis

autMan内置了redis服务&#xff0c;有的脚本运行需要redis支持 几个注意事项&#xff1a; 启用redis服务后要重启autMan生效&#xff0c;关闭一样的道理。启用redis服务后会增加约200M的内存占用多个autMan的redis服务可以组成集群redis服务

五、快速入门K8s之Pod容器的生命周期

一、容器的初始化init ⭐️ init c &#xff1a; init contariner 初始化容器&#xff0c;只是用来初始化&#xff0c;初始化完成就会死亡可以大于的等于一也可以没有&#xff0c;每个init只有在前一个init c执行完成后才可以执行下一个、init容器总是运行到成功完成为止&#…

sqoop问题汇总记录

此篇博客仅记录在使用sqoop时遇到的各种问题。持续更新&#xff0c;有问题评论区一起探讨&#xff0c;写得有不足之处见谅。 Oracle_to_hive 1. main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTr…

C++对象模型:Function 语意学

Member 的各种调用方式 Nonstatic Member Function 使用C时&#xff0c;成员函数和非成员函数在性能上应该是等价的。当设计类时&#xff0c;我们不应该因为担心效率问题而避免使用成员函数。 实现&#xff1a;编译器会将成员函数转换为一个带有额外this指针参数的非成员函数…

二叉树中的深搜 算法专题

二叉树中的深搜 一. 计算布尔二叉树的值 计算布尔二叉树的值 class Solution {public boolean evaluateTree(TreeNode root) {if(root.left null) return root.val 0? false: true;boolean left evaluateTree(root.left);boolean right evaluateTree(root.right);return…

【Linux】环境ChatGLM-4-9B 模型部署

一、模型介绍 GLM-4-9B 是智谱 AI 推出的最新一代预训练模型 GLM-4 系列中的开源版本。 在语义、数学、推理、代码和知识等多方面的数据集测评中&#xff0c; GLM-4-9B 及其人类偏好对齐的版本 GLM-4-9B-Chat 均表现出超越 Llama-3-8B 的卓越性能。除了能进行多轮对话&#xf…

深入理解Java 线程并发编排工具: 概述和应用场景

目录 前言概述1. CountDownLatch2. CyclicBarrier3. Semaphore&#xff08;信号量)4. Condition 案例CountDownLatch-马拉松场景CyclicBarrier-马拉松场景Semaphore-公交车占座场景Condition-线程等待唤醒场景 前言 在 Java 的 java.util.concurrent (JUC) 包中&#xff0c;提…

C++初阶(八)--内存管理

目录 引入&#xff1a; 一、C中的内存布局 1.内存区域 2.示例变量存储位置说明 二、C语言中动态内存管理 三、C内存管理方式 1.new/delete操作内置类型 2.new和delete操作自定义类型 四、operator new与operator delete函数&#xff08;重要点进行讲解&#xff09; …