java基于HuTool工具类ExcelWriter合并单元格

2023-10-28

HuTool工具类ExcelWriter合并单元格

基于HuTool工具类ExcelWriter合并单元格并且使用 jdk1.8 lambda表达式
效果如下:
在这里插入图片描述

  1. 创建注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Intellij IDEA. Copyright@ zqy
 *
 * @Author: zqy
 * @Date: 2021/8/11
 * @Description: excel表头注解
 */

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HeaderName {
    String value() default "";
}
  1. 创建实类
import java.io.Serializable;
import java.math.BigDecimal;

import cn.stylefeng.guns.modular.business.annotation.HeaderName;
import lombok.Data;

/**
 * Created by Intellij IDEA. Copyright@ zqy
 * 
 * @Author: zqy
 * @Date: 2021/8/2
 * @Description:
 */

/**
 * 材料实验
 */
@Data
public class MaterialsTestExcelVO implements Serializable {
    private static final long serialVersionUID = -3621354299691315539L;

    /**
     * 来源名称
     */
    @HeaderName("来源名称")
    private String msName;

    /**
     * 材料名称
     */
    @HeaderName("材料名称")
    private String mName;

    /**
     * 上端材料
     */
    @HeaderName("上端材料")
    private String materialSpringSide;

    /**
     * 下端材料
     */
    @HeaderName("下端材料")
    private String materialCarriageSide;

    /**
     * 温度
     */
    @HeaderName("温度")
    private String temp;

    /**
     * 相对湿度
     */
    @HeaderName("相对湿度")
    private String relattiveHumiduty;

    /**
     * 压力
     */
    @HeaderName("压力")
    private Integer normalForce;

    /**
     * 批次名称
     */
    @HeaderName("批次名称")
    private String batch;

    /**
     * 速度
     */
    @HeaderName("速度")
    private String relativeVelocity;

    /**
     * 啸叫率
     */
    @HeaderName("啸叫率")
    private BigDecimal groanGate;

    /**
     * 滑动摩擦力
     */
    @HeaderName("滑动摩擦力")
    private BigDecimal dynFrictForce;

    /**
     * 静摩擦力
     */
    @HeaderName("静摩擦力")
    private BigDecimal statFrictForce;

    /**
     * 测试时间
     */
    @HeaderName("测试时间")
    private String testTime;
}
  1. 代码逻辑
    1.查找数据库返回数据voList
    2.设置导出表头数据
    3.用lambda表达式获取字段分组数据;
    4.遍历数据,设置合并规则:
    5.将数据保存在list中
    6.ExcelWriter导出excel文件
  2. 代码:
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import lombok.SneakyThrows;
/***
 * @Description: 导出数据查询
 * @Author: zqy
 * @Date: 2021/8/12 14:56
 * @Param: dto response
 * @Return: void
 */
@SneakyThrows
@Override
public void export(MaterialsTestListSearchDTO dto, HttpServletResponse response) {
    List<MaterialsTestExcelVO> voList = testMapper.findExcelList(dto);
    downloadReport(voList, response);
}
/***
 * @Description: 下载数据
 * @Author: zqy
 * @Date: 2021/8/12 14:57
 * @Param: voList response
 * @Return: void
 */
public void downloadReport(List<MaterialsTestExcelVO> voList, HttpServletResponse response) throws IOException {
    // 定义基础数据
    List<String> rowHead = loadRowHead(MaterialsTestExcelVO.class);
    ExcelWriter writer = ExcelUtil.getBigWriter();
    // 写入标题
    writer.writeHeadRow(rowHead);
    // 获取导出数据
    List<List<Object>> rows = loadRowList(voList, writer);
    // 导出数据
    // 一次性写出内容,使用默认样式,强制输出标题
    writer.write(rows, true);
    // response为HttpServletResponse对象
    response.setContentType("application/vnd.ms-excel;charset=utf-8");
    // test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
    response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
    ServletOutputStream out = response.getOutputStream();
    writer.flush(out, true);
    // 此处记得关闭输出Servlet流
    IoUtil.close(out);
}
/***
 * @Description: 封装导出数据,并合并列
 * @Author: zqy
 * @Date: 2021/8/12 14:59
 * @Param: voList writer
 * @Return: java.util.List<java.util.List<java.lang.Object>>
 */
private List<List<Object>> loadRowList(List<MaterialsTestExcelVO> voList, ExcelWriter writer) {
    // 定义启始行
    int index = 1;
    int index2 = 1;
    int index3 = 1;
    int index4 = 1;
    List<List<Object>> rows = new LinkedList<>();
    // 按照姓名分组数据汇总处理(lambda表达式,不了解可以百度)
    Map<String, List<MaterialsTestExcelVO>> msGroupMaps = voList.stream()
        .collect(Collectors.groupingBy(MaterialsTestExcelVO::getMsName, LinkedHashMap::new, Collectors.toList()));
    for (Map.Entry<String, List<MaterialsTestExcelVO>> listEntry : msGroupMaps.entrySet()) {
        List<MaterialsTestExcelVO> msList = listEntry.getValue();
        // 根据数据条数设置合并单元格信息
        if (msList.size() == 1) {// 一条数据不合并
            index = index + msList.size();
            index2 = index2 + msList.size();
            index3 = index3 + msList.size();
            index4 = index4 + msList.size();
        } else {
            // 规则编写
            writer.merge(index, index + msList.size() - 1, 0, 0, null, true);
            // 标题
            index = index + msList.size();
            // 按照编码进行分组
            Map<String, List<MaterialsTestExcelVO>> mGroupMaps = msList.stream().collect(
                Collectors.groupingBy(MaterialsTestExcelVO::getMName, LinkedHashMap::new, Collectors.toList()));
            for (Map.Entry<String, List<MaterialsTestExcelVO>> list2Entry : mGroupMaps.entrySet()) {
                List<MaterialsTestExcelVO> mList = list2Entry.getValue();
                // 根据数据条数设置合并单元格信息
                if (mList.size() == 1) {// 一条数据不合并
                    index2 = index2 + mList.size();
                    index3 = index3 + mList.size();
                    index4 = index4 + mList.size();
                } else {
                    // 规则编写
                    writer.merge(index2, index2 + mList.size() - 1, 1, 1, null, true);
                    index2 = index2 + mList.size();

                    // 按照编码进行分组
                    Map<String, List<MaterialsTestExcelVO>> ssGroupMaps =
                        mList.stream().collect(Collectors.groupingBy(MaterialsTestExcelVO::getMaterialSpringSide,
                            LinkedHashMap::new, Collectors.toList()));
                    for (Map.Entry<String, List<MaterialsTestExcelVO>> list3Entry : ssGroupMaps.entrySet()) {
                        List<MaterialsTestExcelVO> ssList = list3Entry.getValue();
                        // 根据数据条数设置合并单元格信息
                        if (ssList.size() == 1) {// 一条数据不合并
                            index3 = index3 + ssList.size();
                            index4 = index4 + ssList.size();
                        } else {
                            // 规则编写
                            writer.merge(index3, index3 + ssList.size() - 1, 2, 2, null, true);
                            index3 = index3 + ssList.size();

                            // 按照编码进行分组
                            Map<String,
                                List<MaterialsTestExcelVO>> csGroupMaps = ssList.stream()
                                    .collect(Collectors.groupingBy(MaterialsTestExcelVO::getMaterialCarriageSide,
                                        LinkedHashMap::new, Collectors.toList()));
                            for (Map.Entry<String, List<MaterialsTestExcelVO>> list4Entry : csGroupMaps
                                .entrySet()) {
                                List<MaterialsTestExcelVO> csList = list4Entry.getValue();
                                // 根据数据条数设置合并单元格信息
                                if (csList.size() == 1) {// 一条数据不合并
                                    index4 = index4 + csList.size();
                                } else {
                                    // 规则编写
                                    writer.merge(index4, index4 + csList.size() - 1, 3, 3, null, true);
                                    index4 = index4 + csList.size();
                                }
                            }
                        }
                    }
                }
            }
        }
        // 保存数据
        msList.forEach(sList -> {	
            List<Object> rowA = null;
            rowA = CollUtil.newArrayList(sList.getMsName(), sList.getMName(), sList.getMaterialSpringSide(),
                sList.getMaterialCarriageSide(), sList.getTemp(), sList.getRelattiveHumiduty(), sList.getBatch(),
                sList.getNormalForce(), sList.getRelativeVelocity(),  sList.getGroanGate(), sList.getDynFrictForce(), sList.getStatFrictForce(),
                sList.getTestTime());
            rows.add(rowA);
        });
    }
    return rows;
}
/***
 * @Description: 封装表头
 * @Author: zqy
 * @Date: 2021/8/12 15:00
 * @Param: albumClass 实体类class
 * @Return: java.util.List<java.lang.String>
 */
private List<String> loadRowHead(Class<?> albumClass) {
    List<String> rowHead = new ArrayList<>();
    // 获取 实体类 中所有的字段
    Field[] declaredFields = albumClass.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        // 这里设置为 true 才可以访问到 实体类中的 private 字段
        declaredField.setAccessible(true);
        // 获取字段所对应的注解
        HeaderName annotation = declaredField.getAnnotation(HeaderName.class);
        if (null != annotation) {
            // 有注解 则 获取 注解的值(表头名称)
            rowHead.add(annotation.value());
        }
    }
    return rowHead;
}

借鉴地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java基于HuTool工具类ExcelWriter合并单元格 的相关文章

  • 从文本文件中读取阿拉伯字符

    我完成了一个项目 在该项目中我读取了用记事本编写的文本文件 我的文本文件中的字符是阿拉伯语 文件编码类型是UTF 8 当在 Netbeans 7 0 1 中启动我的项目时 一切似乎都正常 但是当我将项目构建为 jar 文件时 字符以这种方式
  • 将 MouseListener 添加到面板

    我正在尝试将鼠标操作添加到我的面板中 这就是程序应该做的事情 编写一个程序 允许用户通过按三下鼠标来指定一个三角形 第一次按下鼠标后 画一个小点 第二次按下鼠标后 绘制一条连接前两个点的线 第三次按下鼠标后 绘制整个三角形 第四次按下鼠标会
  • 如何在url请求中发送数组

    我的要求如下 我想给出演员姓名 开始日期 结束日期并获取他在该时期出演的所有电影 因此 我的服务请求是这样的 http localhost 8080 MovieDB GetJson name Actor startDate 20120101
  • Java 卡布局。多张卡中的一个组件

    一个组件 例如JLabel 在多张卡中使用CardLayout 目前看来该组件仅出现在它添加到的最后一张卡上 如果有办法做到这一点 我应该吗 这是不好的做法吗 或者有其他选择吗 你是对的 它只出现在 添加到的最后一张卡 中 但这与CardL
  • 在哪里保存选项值、重要文件的路径等[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我正在创建一个程序 需要设置一些选项值以及图像文件的一些路径 SQLite 数据库的路径 有关各种按钮上文本的一些信息 有关要使用哪个数据库的信
  • 无法访问“不安全”java方法的java表达式语言

    我正在开发一个项目 让用户向服务器提交小 脚本 然后我将执行这些脚本 有很多脚本语言可以嵌入到Java程序中 例如mvel ognl uel clojure rhino javascript等 但是 据我所知 它们都允许脚本编写者调用Jav
  • JUnit5 平台启动器 API - 如果没有至少一个测试引擎,则无法创建启动器

    我正在尝试升级我们的自动化测试套件的测试能力以接受 JUnit5 测试并遵循JUnit 平台启动器 API 说明 https junit org junit5 docs current user guide launcher api我收到错
  • 根据单元格值向用户窗体添加复选框

    我对 VBA 很陌生 只有 3 天 但我发现它非常有用且易于使用 但现在我面临一个问题 我需要制作一个具有不同复选框的用户窗体 但我需要根据工作表某一列中使用的信息自动添加它们 我相信我可以使用 For Each Next 但我真的不知道如
  • 无法从资源加载图片

    So I am trying to load a image file from a resource so that when I export my application into a jar file it could be use
  • 如何将 Java 地图转换为在 Scala 中使用?

    我正在开发一个 Scala 程序 该程序调用 Java 库中的函数 处理结果并生成 CSV 有问题的 Java 函数如下所示 Map
  • Java:SortedMap、TreeMap、可比较?如何使用?

    我有一个对象列表 需要根据其中一个字段的属性进行排序 我听说 SortedMap 和 Comparator 是实现此目的的最佳方法 我是否要与正在排序的类实现 Comparable 还是创建一个新类 如何实例化 SortedMap 并传入
  • 用于层次结构树角色的 Spring Security / Java EE 解决方案

    我知道 Spring Security 非常适合标准角色和基于权限的授权 我不确定的是这种情况 系统中管理着 10 000 名员工 员工被组织成组织结构图 跨部门的谁向谁报告的树 其中一些员工是用户 这些用户仅被允许访问其职责范围内的员工
  • 正确签名的 JNLP 应用程序无法在 Java 7 中运行

    我有一个 JNLP 应用程序 由于证书过期需要更新 我有一个经过 CA 验证的新证书 我已将新证书导入到我的密钥库中 我已导入完整的证书链 我的构建文件对构建中的 jar 进行签名和时间戳
  • 如何从字符串中解析一个大整数? [复制]

    这个问题在这里已经有答案了 我有一个这样的方法 Integer parseInt myInt 不是这个整数变得很长 我得到以下异常 java lang NumberFormatException For input string 40001
  • BadPaddingException:无效的密文

    我需要一些帮助 因为这是我第一次编写加密代码 加密代码似乎工作正常 但解密会引发错误 我得到的错误是 de flexiprovider api exceptions BadPaddingException 无效的密文 in the 解密函数
  • 删除 JFX 中选项卡后面的灰色背景

    So is there any way to remove the gray area behind the tab s 我尝试过用 CSS 来做到这一点 但没有找到方法 要设置 tabpane 标题的背景颜色 请在 CSS 文件中写入 t
  • Axis2 错误:要输出的文本中的空白字符 (0x4) 无效

    我创建了一个 Java 客户端 使用 Axis2 1 7 6 作为代码生成器与 SOAP Web 服务进行交互 问题在于客户端的某些输入抛出异常并显示以下消息 org apache axis2 AxisFault Invalid white
  • 在实现使用原始类型的接口时如何避免警告?

    我正在实施流程工厂 http help eclipse org ganymede index jsp topic org eclipse platform doc isv reference api org eclipse debug co
  • 如何建立与 FileZilla Server 1.2.0 的 FTPS 数据连接

    使用 Apache commons net 的 Java FTPSClient 进行会话恢复是一个已知问题 会话恢复是 FTPS 服务器数据连接所需的一项安全功能 Apache FTPSClient 不支持会话恢复 并且 JDK API 使
  • mybatis:使用带有 XML 配置的映射器接口作为全局参数

    我喜欢使用 XML 表示法来指定全局参数 例如连接字符串 我也喜欢 Mapper 注释 当我尝试将两者结合起来时 我得到这个例外 https stackoverflow com questions 4263832 type interfac

随机推荐

  • LDA(Latent Dirichlet Allocation)主题模型

    LDA于2003年由 David Blei Andrew Ng和 Michael I Jordan提出 因为模型的简单和有效 掀起了主题模型研究的波浪 虽然说LDA模型简单 但是它的数学推导却不是那么平易近人 一般初学者会深陷数学细节推导中
  • Java中对象的引用(Java对象的引用 )

    Java对象的引用 一 概念 什么是Java对象的引用 每种编程语言都有自己的数据处理方式 有些时候 程序员必须注意将要处理的数据是什么类型 你是直接操纵元素 还是用某种基于特殊语法的间接表示 例如C C 里的指针 来操作对象 所有这些在
  • git 001--建本地仓库和远程仓库和拉代码

    要使用Git对我们的代码进行管理 首先需要获得Git仓库 获取Git仓库通常有两种方式 在本地初始化Git仓库 不常用 从远程仓库克隆 常用 一 建本地仓库 方法一 在自己电脑的任意目录下创建一个空目录 例如桌面的aaa 作为我们的本地Gi
  • 新手入门必看MyBatis-Plus&Druid数据源

    MyBatis Plus Druid数据源 我们就一起来了解下Mybatis Plus吧 什么是MyBatis Plus MyBatis Plus的优势 MyBatis Plus简单来说就是在原本的MyBatis的基础上加了Buff或者说是
  • [系统安全] 四十四.恶意代码同源分析及BinDiff软件基础用法

    您可能之前看到过我写的类似文章 为什么还要重复撰写呢 只是想更好地帮助初学者了解病毒逆向分析和系统安全 更加成体系且不破坏之前的系列 因此 我重新开设了这个专栏 准备系统整理和深入学习系统安全 逆向分析和恶意代码检测 系统安全 系列文章会更
  • 外盘期货的几个级别 你到达几级了?

    01 小白 如果开始赔了钱 就收手不做或者学会敬畏市场还好 但如果开始的福利期太顺或者太容易 就及其容易造成信心爆棚 对行情存在 赌 的思想 反而不利于以后的成长 这种情况基本出现在刚刚入市 实盘交易时间短的小白身上 02 筑基期 处在这一
  • 二叉树的扩展——主要方法和基本算法等

    1 求树的高度 思路 二叉树的高度等于左右子树里面的最大高度 int high BtNode ptr if ptr NULL return 0 int L high ptr gt lchild int R high ptr gt rchil
  • java.lang.IllegalStateException

    Caused by java lang IllegalStateException The specified child already has a parent You must call removeView on the child
  • 【SQL】保姆级教程:MySQL配置全过程 & 编辑器DBeaver的安装配置

    MySQL 是最流行的关系型数据库管理系统 在 WEB 应用方面 MySQL 是最好的 RDBMS Relational Database Management System 关系数据库管理系统 应用软件之一 文章目录 一 什么是数据库 二
  • 数字水印技术的原理、实现及其应用

    概述 数字水印 是指将特定的信息嵌入数字信号中 数字信号可能是音频 图片或是视频等 数字水印可分为浮现式和隐藏式两种 明水印 visible watermarking 其所包含的信息可在观看图片或视频时同时被看见 盲水印 blind wat
  • 计蒜客T1461——校验信用卡号码

    如题 本题需要解决的本质就是多个字符串转换为整型数据的过程 主要的考点在于如下3个 1 循环输入多个字符串并不间断 2 将字符串处理为整型数据 3 完成对整形数据的检验 上述三个要求通过STL可以很轻松地解决 具体做法写在了代码注释之中 i
  • Unity3D 4.0新功能:Mecanim动画系统基础教程

    作为Unity4 0的主要更新功能 Mecanim动画被寄予了很多的期望 系统有先进的地方 也有不足的地方 这些我们留到最后再来总结 阿赵粗略的学习了一下 写下以下的教程 这篇教程简单的说明了Mecanim系统的用法和控制方式 里面用到的资
  • electron-vue中报错 Cannot use import statement outside a module解决方案(亲测有效!!!)

    错误 Cannot use import statement outside a module 不能在模块之外使用导入语句 原因 安装的某个依赖包里使用了import语法 因为我们打包输出的是commonjs规范 所以不识别import语法
  • 学习笔记 React(一)Hello React例子及创建虚拟DOM的两种方式

    React官网地址 React库 最基础的例子 官网 1 英文官网 https reactjs org 2 中文官网 https react docschina org React库 babel min js ES6 gt ES5 JSX
  • C++中函数原型和函数定义

    C 中函数原型和函数定义 C 函数原型指的是函数声明的语法形式 它告诉编译器函数的名称 返回类型和参数列表 函数原型的语法形式如下 return type function name parameter list 其中 return typ
  • 什么是强制缓存?什么是协商缓存?cache

    强制缓存和协商缓存是用于在Web浏览器和服务器之间进行缓存控制的两种机制 强制缓存 强缓存 强制缓存 强制缓存是通过设置HTTP响应头来实现的 它告诉浏览器在一定时间内直接使用缓存的副本 而不需要再向服务器发起请求 常见的强制缓存相关的响应
  • PHP Filter伪协议Trick总结

    PHP Filter伪协议Trick总结 前言 最近在学习的过程中碰到了很多的filter协议的小trick 在此做一个总结以及对filter协议的一些探索 PHP Filter协议介绍 php filter是php中独有的一种协议 它是一
  • 题目0010-数据分类

    数据分类 题目描述 对一个数据a进行分类 分类方法是 此数据a 4个字节大小 的4个字节相加对一个给定值b取模 如果得到的结果小于一个给定的值c则数据a为有效类型 其类型为取模的值 如果得到的结果大于或者等于c则数据a为无效类型 比如一个数
  • SpringBoot配置文件

    1 springboot提供两种配置文件类型 properties和yml yaml 2 默认配置文件名称 properties 3 在同一级目录下优先级为 peoperties gt yml gt yaml YAML定义 三种配置文件写法
  • java基于HuTool工具类ExcelWriter合并单元格

    HuTool工具类ExcelWriter合并单元格 基于HuTool工具类ExcelWriter合并单元格并且使用 jdk1 8 lambda表达式 效果如下 创建注解 import java lang annotation Element