EasyExcel根据模板生成excel文件【xls、xlsx】

news2024/9/22 17:16:54

1、简介
如下图所示,template目录下是准备好的模板,export目录下是生成数据文件。我们这里以第一个模板《theUser蒸汽历史数据.xls》为例进行测试,theUser为占位符,生成的文件中会被替换成对应的用户名。

我这里的代码逻辑是根据选取的用户、起始时间导出用户的历史数据,一个用户一个excel文件,所有用户数据文件在一个目录下,最后把这个目录再压缩成zip,最后用户点击导出的就是这个压缩文件。
———————————————

 提示:红色框框都是使用到的,其它的不用管,这里使用的 EasyExcel 所以需要引入依赖:如下

 <!-- knife4j -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

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

2、模板格式

占位符这里分两种:

  • {字段名} :{theUser} 和 {reportDate}
  • {自定义名称.字段名}:数据类字段占位符,字段对应entity文件夹中的HistoryData对象的字段,hisData在代码中定义。

 HistoryData对象:如下

package com.example.fengqing.ExcelTemplates.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author FengQing
 * @program fengqing
 * @description
 * @date 2024/03/19
 */
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class HistoryData {

    // 时间
    private String time;

    // 温度
    private Double temp;

    // 压力
    private Double press;

    // 瞬时流量
    private Double insFlow;

    // 累计流量
    private Double accFlow;

    // 瞬时热量
    private Double insHeat;

    // 累计热量
    private Double accHeat;
}

3、这里为方便没有编写impl业务层,直接写在Controller 层(一般情况下不建议在Controller层写业务

package com.example.fengqing.ExcelTemplates.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.example.fengqing.ExcelTemplates.ExcelGenerator;
import com.example.fengqing.ExcelTemplates.entity.HistoryData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author FengQing
 * @program fengqing
 * @description
 * @date 2024/03/20
 */
@Slf4j
@RestController
@RequestMapping("/template")
public class TemplatesController {

    /**
     * 指定模板下载
     * @param response
     * @throws IOException
     */
    @PostMapping("/downFrozenTemplate")
    public void downFrozenTemplate(HttpServletResponse response) throws IOException {
        try {
            String reportDate = DateUtil.date().toString("yyyy年MM月dd日");
       // 获取resources/templates目录下的模板文件
            InputStream templateStream = TemplatesController.class.getResourceAsStream("/templates/theUser蒸汽历史数据.xlsx");
            if (templateStream == null) {
                throw new FileNotFoundException("未找到模板文件");
            }
            String resultFileName = "蒸汽模板.xlsx";
            // 生成目标文件
            ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(templateStream).build();
            WriteSheet writeSheet = EasyExcel.writerSheet().build();
            // 每次都会重新生成新的一行,而不是使用下面的空行
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            // 替换第一种占位符
            Map<String, Object> map = new HashMap<>();
            map.put("theUser", "测试有限公司");
            map.put("reportDate", reportDate);
            excelWriter.fill(map, writeSheet);
            // 第二种占位符替换,这里定义了 hisData
            excelWriter.fill(new FillWrapper("thsData", hisData()), fillConfig, writeSheet);
            excelWriter.finish();
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + resultFileName + "\"");
            // 关闭模板流
            templateStream.close();
        } catch (FileNotFoundException e) {
            // 处理文件未找到异常
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            // 返回适当的错误消息
            response.getWriter().write("未找到模板文件");
        } catch (Exception e) {
            // 处理其他异常
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            // 返回适当的错误消息
            response.getWriter().write("内部服务器错误");
        }
    }

    private static List<HistoryData> hisData(){
        List<HistoryData> resList = new ArrayList<>();
        String today = DateUtil.now();
        String yesterday = DateUtil.yesterday().toString();
        HistoryData yesData = HistoryData.builder()
                .time(today)
                .temp(34.211)
                .press(1.222)
                .insFlow(34.211)
                .accFlow(233.125)
                .insHeat(20.532)
                .accHeat(112.562)
                .build();
        HistoryData nowData = HistoryData.builder()
                .time(yesterday)
                .temp(34.211)
                .press(1.222)
                .insFlow(34.211)
                .accFlow(233.125)
                .insHeat(20.532)
                .accHeat(112.562)
                .build();
        resList.add(yesData);
        resList.add(nowData);
        return resList;
    }

}

 4、以上代码已完成,接下来使用 postman 来测试,如图:

5、最终效果:

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

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

相关文章

[Linux]:信号(下)

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;Linux学习 贝蒂的主页&#xff1a;Betty’s blog 1. 信号的阻塞 1.1 基本概念 信号被操作系统发送给进程之后&#xff0c;进程…

语言模型的在线策略提炼:从自我错误中学习

原论文&#xff1a;On-Policy Distillation of Language Models: Learning from Self-Generated Mistakes 摘要 知识蒸馏&#xff08;KD&#xff09;被广泛用于通过训练较小的学生模型来压缩教师模型&#xff0c;以降低推理成本和内存占用。然而&#xff0c;当前用于自回归序…

【笔记】材料分析测试:晶体学

晶体与晶体结构Crystal and Crystal Structure 1.晶体主要特征 固态物质可以分为晶态和非晶态两大类&#xff0c;分别称为晶体和非晶体。 晶体和非晶体在微观结构上的区别在于是否具有长程有序。 晶体&#xff08;长程有序&#xff09;非晶&#xff08;短程有序&#xff09…

Selenium4.0实现自动搜索功能

01.Selenium4.0实现搜索功能 1.安装Selenium及查看Selenium版本 pip install selenium pip show seleniumfrom selenium import webdriver from chromedriver_py import binary_path import time from selenium.webdriver.common.by import By from selenium.webdriver.commo…

postman控制变量和常用方法

1、添加环境&#xff1a; 2、环境添加变量&#xff1a; 3、配置不同的环境&#xff1a;local、dev、sit、uat、pro 4、 接口调用 5、清除cookie方法&#xff1a; 6、下载文件方法&#xff1a;

SSM+vue音乐播放器管理系统

音乐播放器管理系统 随着社会的发展&#xff0c;计算机的优势和普及使得音乐播放器管理系统的开发成为必需。音乐播放器管理系统主要是借助计算机&#xff0c;通过对首页、音乐推荐、付费音乐、论坛信息、个人中心、后台管理等信息进行管理。减少管理员的工作&#xff0c;同时…

c# 线程等待变量的值符合条件

在C#中&#xff0c;如果你想让一个线程等待直到某个变量的值满足特定条件&#xff0c;你可以使用ManualResetEvent或者AutoResetEvent来实现线程间的同步。以下是使用AutoResetEvent实现的一个简单例子&#xff1a; 在这个例子中&#xff0c;同时实现了如何让static函数访问非…

高等数学 3.6 函数图像的描绘

利用导数描绘函数图形的一般步骤如下&#xff1a; &#xff08;1&#xff09;确定函数 y f ( x ) y f(x) yf(x) 的定义域及函数所具有的某些特性&#xff08;如奇偶性、周期性等&#xff09;&#xff0c;并求出函数的一阶导数 f ′ ( x ) f^{}(x) f′(x) 和二阶导数 f ′ …

【YOLO目标检测手势识别数据集】共55952张、已标注txt格式、有训练好的yolov5的模型

目录 说明图片示例 说明 数据集格式&#xff1a;YOLO格式 图片数量&#xff1a;55952 标注数量(txt文件个数)&#xff1a;55952 标注类别数&#xff1a;7 标注类别名称&#xff1a; one two three four five good ok 数据集下载&#xff1a;手势识别数据集 图片示例 数…

【CSS】伪类选择器 :root 声明全局CSS变量

语法 <style>:root {/* ... */} </style>这个 CSS 伪类 :root 匹配文档树的根元素&#xff0c;表示选中 <html> 元素&#xff0c;除了优先级更高之外&#xff0c;与 html 选择器相同 <style>/* 选中文档的根元素&#xff08;HTML 中的 <html>&a…

制造业的智能化革命:工业物联网(IIoT)的优势、层级应用及挑战解析

在全球制造业的蓬勃发展中&#xff0c;工业物联网&#xff08;IIoT&#xff09;作为一股颠覆性力量&#xff0c;正逐步重塑传统制造业的面貌。IIoT技术通过无缝连接设备、系统与人员&#xff0c;促进了数据的即时流通与处理&#xff0c;不仅极大地提升了制造效率&#xff0c;还…

pikachu XXE(XML外部实体注入)通关

靶场&#xff1a;pikachu 环境: 系统&#xff1a;Windows10 服务器&#xff1a;PHPstudy2018 靶场&#xff1a;pikachu 关卡提示说&#xff1a;这是一个接收xml数据的api 常用的Payload 回显 <?xml version"1.0"?> <!DOCTYPE foo [ <!ENTITY …

【Godot4.3】基于状态切换的游戏元素概论

提示 本文的设想性质比较大,只是探讨一种设计思路。完全理论阶段&#xff0c;不可行就当是闹了个笑话O(∩_∩)O哈哈~但很符合我瞎搞的气质。 概述 一些游戏元素&#xff0c;其实是拥有多个状态的。比如一个宝箱&#xff0c;有打开和关闭两个状态。那么只需要设定两个状态的图…

演示:基于WPF的DrawingVisual开发的Chart图表和表格绘制

一、目的&#xff1a;基于WPF的DrawingVisual开发的Chart图表和表格绘制 二、预览 钻井井轨迹表格数据演示示例&#xff08;应用Table布局&#xff0c;模拟井轨迹深度的绘制&#xff09; 饼图表格数据演示示例&#xff08;应用Table布局&#xff0c;模拟多个饼状图组合显示&am…

OpenCV_图像膨胀腐蚀与形态学操作及具体应用详解

在本教程中&#xff0c;您将学习如何&#xff1a; 应用两个非常常见的形态运算符&#xff1a;腐蚀和膨胀&#xff1a; cv::erodecv::dilate 使用OpenCV函数cv :: morphologyEx应用形态转换&#xff0c;如&#xff1a; 开运算闭运算形态学梯度顶帽运算黑帽运算 形态作业 简…

算法-环形链表(141)

这道题其实是一个非常经典的快慢指针的问题 &#xff0c;也成为Floyd的乌龟和兔子算法。 设置两个指针&#xff0c;一个快指针&#xff0c;一个满指针&#xff0c;都从头节点开始遍历&#xff0c;如果链表中存在环&#xff0c;那么快指针最终会在环内某个节点相遇&#xff0c;…

Linux网络工具:用于查询DNS(域名系统)域名解析信息的命令nslookup详解

目录 一、概述 二、基本功能 1、查询域名对应的IP地址 2、查询IP地址对应的主机名 3、查询特定类型的DNS记录 三、用法 1、命令格式 2、常用选项 五、nslookup的安装 1. 打开终端 2. 更新的系统包列表 3. 安装 bind-utils 软件包 &#xff08;1&#xff09;对于Ce…

树和二叉树的概念以及结构

一起加油学数据结构 目录 树的概念以及结构 树的概念 树的相关概念 树的表示 二叉树的概念以及结构 二叉树的概念 特殊的二叉树 二叉树的性质 二叉树的存储结构 树的概念以及结构 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09…

【Elasticsearch系列十九】评分机制详解

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…