动态列的excel导出

news2024/11/18 4:42:51

动态列的excel导出

由于上次写的动态列的excel导入时挖下的坑。

上一篇在这里:动态列的excel导入

喝水不忘挖井人,至于乱挖井,咱们先不说好不好吧,万一砸到了花花草草也不好啊,所以说啊,挖坑就得用军工铲,至于铲车好不好用,那当然是要挖掘机来决定。总而总之,言而言之。挖掘机技术哪家强,山东技校找蓝翔嘛。啊 ~
所以说这个咱们挖的坑,就必须咱们来填了它。
于是这次我们来写动态列的导出吧。

先看效果

在这里插入图片描述

表结构

在这里插入图片描述


表结构是一对多的,非动态列的部分是一,动态部分是多,如果你是单纯的列表转列可以不关注主表,只关注多表的部分,道理都是一样的。
(图中的表结构与测试效果图不一致,给个示例,达到效果能理解就行了)


依赖

我们这里依然使用的是easyexcel来做导出

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>easyexcel</artifactId>
    <version>2.2.6</version>
</dependency>

接下来看代码


parseFactorList()方法中将多表的属性名称转成多列表头名称的列表
重点在于 .registerWriteHandler(new DynamicMergeStrategy(excelVoList,factorList)) ,使用自定义的合并策略,画出需要导出的excel的样式


@Override
    public void exportList(HttpServletResponse response, ListDto dto) throws IOException, NoSuchFieldException, IllegalAccessException {
        List<UniDto> excelVoList = uniDao.listDto(dto);

        if(CollectionUtil.isEmpty(excelVoList)) {
            return;
        }

		// 将多表的属性名称转成多列表头名称的列表
        List<String> factorList = parseFactorList(excelVoList);

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf8");
        response.setHeader("Content-disposition", "attachment;filename=全部数据.xlsx");

        EasyExcel.write(response.getOutputStream())
                .registerWriteHandler(new DynamicMergeStrategy(excelVoList,factorList)) // 使用自定义的合并策略,画出需要导出的excel的样式
                .excelType(ExcelTypeEnum.XLSX)
                .sheet("运单列表")
                .doWrite(factorList);
    }

	private <T> List<String> parseFactorList(List<T> excelVoList) throws IllegalAccessException, NoSuchFieldException {
        Set<String> set = new TreeSet<>();
        for (T t : excelVoList) {
            Class<?> clazz = UniPmsPriceDto.class;
            Field factorListField = clazz.getDeclaredField("factorList");
            factorListField.setAccessible(true);

            List<UniDtl> factorList = (List<UniDtl>) factorListField.get(t);
            if(CollectionUtil.isEmpty(factorList)) {
                continue;
            }

            for (UniDtl uniDtl : factorList) {
                set.add(uniDtl.getPriceFactor());
            }
        }

        return new ArrayList<>(set);
    }

自定义合并策略(重点)


先用 titleHandle() 方法,将标题画出来,

for (int i = 0; i < factorList.size(); i++) {
            Cell celli = row0.createCell(25 + i);
            celli.setCellValue(factorList.get(i));
            celli.setCellStyle(cellStyle);
            setCellBorder(celli, BorderStyle.THIN, IndexedColors.BLACK.getIndex());
        }

在这段代码中,将前面获取到的标题名称列表遍历设置成标题

在使用 valueHandle() 方法,将数据填充到excel中

下面是完整代码⬇


public class PmsPriceSeaDynamicMergeStrategy implements RowWriteHandler {
    private List<UniPmsPriceSeaDto> excelList;
    private List<String> factorList;

    public PmsPriceSeaDynamicMergeStrategy(List<UniPmsPriceSeaDto> excelList, List<String> factorList) {
        this.excelList = excelList;
        this.factorList = factorList;
    }

    @Override
    public void beforeRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Integer rowIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterRowCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterRowDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Integer relativeRowIndex, Boolean isHead) {

        Sheet sheet = writeSheetHolder.getSheet();
        Row row0 = sheet.createRow(0);
        titleHandle(sheet,row0,factorList);

        for (int i = 0; i < excelList.size(); i++) {
            UniPmsPriceSeaDto uniPmsPriceSeaDto = excelList.get(i);
            Row rowValue = sheet.createRow(i + 1);

            valueHandle(uniPmsPriceSeaDto, rowValue, factorList);
        }
    }

    /**
     * 创建标题
     * @param sheet
     * @param row0
     * @param factorList
     */
    private void titleHandle(Sheet sheet, Row row0, List<String> factorList) {
        Workbook workbook = sheet.getWorkbook();
		// 创建字体
        Font font = workbook.createFont();
        font.setBold(true); // 加粗
        font.setFontHeightInPoints((short)14); // 字体高度(大小)

        CellStyle cellStyle = workbook.createCellStyle();
        // 内容居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
        cellStyle.setFont(font); // 设置字体

        // 设置单元格的背景颜色为灰色
        cellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); // 设置填充模式为实心

        Cell cell19 = row0.createCell(20);
        cell19.setCellValue("备注");
        sheet.setColumnWidth(20, 6000);
        cell19.setCellStyle(cellStyle);
        // 设置边框
        setCellBorder(cell19, BorderStyle.THIN, IndexedColors.BLACK.getIndex());

        Cell cell20 = row0.createCell(21);
        cell20.setCellValue("创建人");
        cell20.setCellStyle(cellStyle);
        sheet.setColumnWidth(21, 5000);
        setCellBorder(cell20, BorderStyle.THIN, IndexedColors.BLACK.getIndex());

        Cell cell21 = row0.createCell(22);
        cell21.setCellValue("创建时间");
        cell21.setCellStyle(cellStyle);
        sheet.setColumnWidth(22, 6000);
        setCellBorder(cell21, BorderStyle.THIN, IndexedColors.BLACK.getIndex());

        Cell cell22 = row0.createCell(23);
        cell22.setCellValue("更新人");
        cell22.setCellStyle(cellStyle);
        sheet.setColumnWidth(23, 5000);
        setCellBorder(cell22, BorderStyle.THIN, IndexedColors.BLACK.getIndex());

        Cell cell23 = row0.createCell(24);
        cell23.setCellValue("更新时间");
        cell23.setCellStyle(cellStyle);
        sheet.setColumnWidth(24, 6000);
        setCellBorder(cell23, BorderStyle.THIN, IndexedColors.BLACK.getIndex());

		// 设置动态列标题列
        for (int i = 0; i < factorList.size(); i++) {
            Cell celli = row0.createCell(25 + i);
            celli.setCellValue(factorList.get(i));
            celli.setCellStyle(cellStyle);
            setCellBorder(celli, BorderStyle.THIN, IndexedColors.BLACK.getIndex());
        }
    }

    // 设置单元格边框
    public static void setCellBorder(Cell cell, BorderStyle borderStyle, short borderColor) {
        CellStyle cellStyle = cell.getCellStyle();
        cellStyle.setBorderTop(borderStyle);
        cellStyle.setBorderRight(borderStyle);
        cellStyle.setBorderBottom(borderStyle);
        cellStyle.setBorderLeft(borderStyle);

        cellStyle.setTopBorderColor(borderColor);
        cellStyle.setRightBorderColor(borderColor);
        cellStyle.setBottomBorderColor(borderColor);
        cellStyle.setLeftBorderColor(borderColor);

        cell.setCellStyle(cellStyle);
    }
    
    private void valueHandle(UniPmsPriceSeaDto uniPmsPriceSeaDto, Row rowValue, List<String> factorList) {
     
        Cell cell19 = rowValue.createCell(20);
        cell19.setCellValue(uniPmsPriceSeaDto.getRemarks());

        Cell cell20 = rowValue.createCell(21);
        cell20.setCellValue(uniPmsPriceSeaDto.getInsertedBy());

        Cell cell21 = rowValue.createCell(22);
        cell21.setCellValue(uniPmsPriceSeaDto.getInsertTime());

        Cell cell22 = rowValue.createCell(23);
        cell22.setCellValue(uniPmsPriceSeaDto.getUpdatedBy());

        Cell cell23 = rowValue.createCell(24);
        cell23.setCellValue(uniPmsPriceSeaDto.getUpdateTime());

        List<UniPmsPriceDtl> factorListValue = uniPmsPriceSeaDto.getFactorList();
        if(CollectionUtil.isEmpty(factorListValue)) {
            return;
        }

        Map<String, BigDecimal> factorMap = factorListValue.stream().collect(Collectors.toMap(item -> item.getPriceFactor(), UniPmsPriceDtl::getAmtCostPrice));
        
        // 填充动态列的值
        for (int i = 0; i < factorList.size(); i++) {
            String factor = factorList.get(i);
            BigDecimal amt = DecimalUtils.getDecimal(factorMap.get(factor));

            Cell celli = rowValue.createCell(25 + i);
            celli.setCellValue(DecimalUtils.eqZero(amt) ? "" : String.valueOf(amt));
        }

    }
}

下一篇我们来填上一篇挖合并单元格和样式的坑

(相别容易见时难,别后相思独凄然,千山万水总是情,点个关注行不行)

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

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

相关文章

MySQL数据库技术笔记(4)

关系型数据库需要使用设计范式&#xff1a; 第一范式&#xff1a;遵从原子性&#xff0c;属性不可再分&#xff0c;数据库表的每一列都是不可分割的基本数据项&#xff0c;同一列中不能有多个值。 例如&#xff1a;需要创建一张地址表&#xff0c;存储地址信息。将地址信息划…

UE4和C++ 开发-UE4怎么删除C++类

1 关闭visual stdio&#xff0c;关闭UE4引擎。 2 打开你的项目文件夹。找到你要删除的.h,.cpp文件删除。 3、删除Binaries文件夹。 4 右击.uproiect文件&#xff0c;点击Generate Visual Studio project files. 5 双击.uproiect文件,忽略警告打开就看到已经删除了想要删除的C类…

区块链加密虚拟货币交易平台安全解决方案

区块链机密货币交易锁遭入侵&#xff0c;安全存在隐患。使用泰雷兹Protect server HSM加密机&#xff0c;多方位保护您的数据&#xff0c;并通过集中化管理&#xff0c;安全的存储密钥。 引文部分&#xff1a; 损失7000万美元!黑客入侵香港区块链加密货币交易所 2023年9月&…

Qt 窗口与部署应用程序发布包 day6

Qt 窗口与部署应用程序发布包 day6 QWidget QWidget是所有可视控件的基类&#xff0c;每个控件都是矩形按照Z轴顺序排序如果控件没有父控件&#xff0c;则称为窗口 设置exe窗口图标 在项目文件中新建一个文件夹Resource&#xff0c;来存放图标文件 第一种方法 用绝对路…

java过滤非中英文的特殊字符,四字节表情字符

过滤非中英文的特殊字符 /*** 过滤特殊字符* param str str* return String*/ public static String filterStr(String str) {if (StringUtils.isBlank(str)) {return str;}String regEx "[~!#$%^&*()|{}:;,\\[\\].<>/?~&#xff01;#&#xffe5;%……&…

源码部署lamt架构

源码部署lamt架构 lamt由apache&#xff0c;mysql&#xff0c;tomcat三者组成 文章目录 源码部署lamt架构1.准备工作1.1.配置yum源&#xff0c;关闭防火墙和selinux1.2.拉取相应源码包 2.安装apache3.安装mariadb4.安装tomcat 1.准备工作 1.1.配置yum源&#xff0c;关闭防火墙…

“Python+”集成技术高光谱遥感数据处理与机器学习深度应用

高光谱遥感数据处理的基础、python开发基础、机器学习和应用实践。重点解释高光谱数据处理所涉及的基本概念和理论&#xff0c;旨在帮助学员深入理解科学原理。结合Python编程工具&#xff0c;专注于解决高光谱数据读取、数据预处理、高光谱数据机器学习等技术难题&#xff0c;…

SpringBoot配置输出的日志文件

SpringBoot配置输出的日志文件 1、无需导入依赖&#xff0c;因为我们创建springboot时&#xff0c;导入的关于springboot的依赖中已经包含了。 2、我们在项目的resources 资源文件下创建logback.xml文件&#xff0c;文件内容如下 作用&#xff1a; 如果是开发时启动的项目&a…

Android Native 开发 要点记录

Android Studio 中写 C 代码 android studio创建C项目_android studio native c-CSDN博客 项目配置参考 【CMake】CMakeLists.txt的超傻瓜手把手教程&#xff08;附实例源码&#xff09;_【cmake】cmakelists.txt的超傻瓜手把手教程(附实例源码)-CSDN博客 CMakeLists.txt 讲解…

竞赛选题 深度学习 植物识别算法系统

文章目录 0 前言2 相关技术2.1 VGG-Net模型2.2 VGG-Net在植物识别的优势(1) 卷积核&#xff0c;池化核大小固定(2) 特征提取更全面(3) 网络训练误差收敛速度较快 3 VGG-Net的搭建3.1 Tornado简介(1) 优势(2) 关键代码 4 Inception V3 神经网络4.1 网络结构 5 开始训练5.1 数据集…

OpenCV4(C++)—— 创建窗口滑动条来调参

文章目录 创建滑动条 —— createTrackbar 创建滑动条 —— createTrackbar createTrackbar是OpenCV中的一个函数&#xff0c;用于创建一个可调节的滑动条&#xff08;Trackbar&#xff09;&#xff0c;以便在图像处理过程中实时调整参数 int cv::createTrackbar(const String…

异地监控如何实现远程访问?贝锐蒲公英无需公网IP即可实现

当前&#xff0c;视频监控系统在各领域都得到了广泛的应用。在交通行业&#xff0c;江苏某科技企业专门从事系统集成、软件开发以及交通信息工程的设计、研发和实施&#xff0c;为高速公路信息化建设提供了一系列解决方案&#xff0c;包括机电系统、视频联网监控系统、征收管理…

I2VGen-XL高清图像生成视频大模型

本项目I2VGen-XL旨在解决根据输入图像生成高清视频任务。I2VGen-XL由达摩院研发的高清视频生成基础模型之一&#xff0c;其核心部分包含两个阶段&#xff0c;分别解决语义一致性和清晰度的问题&#xff0c;参数量共计约37亿&#xff0c;模型经过在大规模视频和图像数据混合预训…

虹科分享 | 独特的FRER机制:TSN如何确保网络的可靠性?

1.IEEE802.1 CB协议 Frame Replication and Elimination for Reliability(FRER)是IEEE 802.1CB协议的一个重要特性&#xff0c;旨在增强以太网网络的可靠性。FRER利用帧复制和消除技术提供冗余保护和从连接故障中快速恢复。 FRER-IEEE 802.1CB协议的应用场景&#xff1a; 高…

Navicat如何连接远程服务器的MySQL

参考:https://blog.csdn.net/a648119398/article/details/122420906 1.Navicat for Mysql 2.腾讯云轻量级服务器一台&#xff08;Centos 7&#xff09; 3.Mysql 8.0.24&#xff08;远程服务器内安装的&#xff09; 4.Xshell7&#xff08;连接操作远程服务器&#xff09; 一、修…

【AI视野·今日Robot 机器人论文速览 第五十一期】Tue, 10 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 10 Oct 2023 Totally 54 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers On Multi-Fidelity Impedance Tuning for Human-Robot Cooperative Manipulation Authors Ethan Lau, Vaibhav Srivastava, Sh…

skywalking动态配置[集成nacos/apollo/consul]

说明:以下配置仅关于的阈值规则的动态配置,其他参数也可以进行配置。 1,skywalking动态配置集成nacos 编辑application.yml nacos配置参数如下: nacos:# Nacos Server HostserverAddr: 10.10.5.145# Nacos Server Portport: 8848# Nacos Configuration Groupgroup: skywal…

塑胶材料检测对激光焊机的作用

塑胶材料的激光焊接已经普遍用于各种零配件&#xff0c;而塑料的透光率是焊接工艺质量的一个重要指标。针对这类塑胶材料推出这款专门检测塑胶材料近红外透光率特性的透光率检测仪&#xff0c;对注塑件的透光率进行全画面扫描。 全球工业致力于贯彻绿色环保、节能减排发展理念&…

IntelliJ IDEA Maven 项目的依赖分析

在一个 maven 的项目中&#xff0c;我们需要知道我们的项目中使用的包可能有哪些冲突。 这个在 IntelliJ IDEA 中提供了贴心的查看。 选择 Maven 项目中的分析依赖。 随后&#xff0c;IntelliJ IDEA 将会打开一个依赖分析的标签页。 在这个标签页中&#xff0c;我们可以看到…

【C++11】function包装器,bind函数模板使用

&#x1f30f;博客主页&#xff1a; 主页 &#x1f516;系列专栏&#xff1a; C ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ &#x1f60d;期待与大家一起进步&#xff01; 文章目录 前言一、function的原型二、function的使用三、bind1.绑定普通函数2.绑定类中的静态成…