springboot导出数据到excel模板,使用hutool导出数据到指定excel,java写入数据到excel模板

最近遇到一个需求,需要从数据库查询数据,写入到对应的excel导入模板中。再把导出的数据进行修改,上传。
我们项目用的是easyExcel,一顿百度搜索,不得其法。
主要是要把数据填充到指定单元格中,跟平时用到的导出不一样。项目中也没有引入其它poi。

后来忽然想起来,项目中集成的有hutool,可以用hutool的导入导出功能,先把excel导入模板读取出来,再给excel模板加工数据,最后再导出。

然后又开始了百度之旅~

终于在Two thousand years later~

写一个样例:
excel导入模板长这样:(随便画得)
第一个sheet页
第二个sheet页
第三个sheet页

想要的效果大概是这样:
稍微写了一点点数据,根据业务,自己完善。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码:

关于hutool版本,和导入导出所需依赖,可参考我篇文章。hutool导入导出,java使用hutool导入导出,hutool导出多级标题复杂表头,hutool大数据量导出

因为我这个项目是springboot的,所以我把excel模板放在了这里。方便读取。

在这里插入图片描述

 package com.demo.controller;

import cn.hutool.json.JSONUtil;
import io.swagger.annotations.Api;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Api(tags = "控制类")
@RequestMapping("/user")
public class UserController {

    @GetMapping("/download")
    public void download(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //添加测试数据
        List<Map<String,String>> list1 = new ArrayList<>();
        Map<String, String> map = new HashMap<>();
        map.put("q1","moveNo");
        map.put("q2","moveNo");
        map.put("q3","78");
        map.put("q4","moveNo");
        map.put("q5","moveNo");
        map.put("q6","moveNo");
        map.put("q7","moveNo");
        Map<String, String> map1 = new HashMap<>();
        map1.put("q5","moveNo");
        map1.put("q6","moveNo");
        map1.put("q7","moveNo");
        list1.add(map);
        list1.add(map1);


        //添加测试数据
        List<Map<String,Object>> printVoList = new ArrayList<>();
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("COL1","123");
        hashMap.put("COL2","234");
        hashMap.put("COL3","345");
        hashMap.put("COL4","456");
        Map<String, Object> hashMap1 = new HashMap<>();
        hashMap1.put("COL1","哈");
        hashMap1.put("COL2","吧");
        hashMap1.put("COL3","吗");
        printVoList.add(hashMap);
        printVoList.add(hashMap1);


        //获取文件输入流
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("123.xlsx");

        //设置返回
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("我测试的", "utf-8") + ".xlsx");
        OutputStream out = response.getOutputStream();

        if (inputStream == null){
            throw new RuntimeException("文件未找到!");
        }

        //获取工作簿
        Workbook workbook = new XSSFWorkbook(inputStream);

        //获取创建工作簿的第一页
        Sheet sheet=workbook.getSheetAt(0);
        //给指定的sheet命名
//        workbook.setSheetName(0,"dataSheet");
        //获取当前工作簿的行数
//        int totalRows=sheet.getPhysicalNumberOfRows();
        //****遍历模板sheet,根据当中的设定进行赋值****
        int newRowIndex = 3;//起始行 从第4行开始
        for (int i=0;i<list1.size();i++) {
            Row row = sheet.createRow(newRowIndex++);
            int column = row.getLastCellNum();
            int j = 0;
            (row.getCell(j)!=null?row.getCell(j):row.createCell(j)).setCellValue(list1.get(i).get("q1"));
            j++;(row.getCell(j)!=null?row.getCell(j):row.createCell(j) ).setCellValue(list1.get(i).get("q2"));
            j++;(row.getCell(j)!=null?row.getCell(j):row.createCell(j) ).setCellValue(list1.get(i).get("q3"));
            j++;(row.getCell(j)!=null?row.getCell(j):row.createCell(j) ).setCellValue(list1.get(i).get("q4"));
            j++;(row.getCell(j)!=null?row.getCell(j):row.createCell(j) ).setCellValue(list1.get(i).get("q5"));
            j++;(row.getCell(j)!=null?row.getCell(j):row.createCell(j) ).setCellValue(list1.get(i).get("q6"));
            j++;(row.getCell(j)!=null?row.getCell(j):row.createCell(j) ).setCellValue(list1.get(i).get("q7"));
        }


        //获取创建工作簿的第2页
        Sheet sheet1=workbook.getSheetAt(1);
        //获取当前工作簿的行数
        int totalRows=sheet1.getPhysicalNumberOfRows();
        for (int i = 0;i<totalRows;i++){
            Row row = sheet1.getRow(i);
            if (row == null) continue;
            System.out.println(row.getRowNum() + JSONUtil.toJsonStr(row));;
        }
        sheet1.getRow(4).getCell(3).setCellValue("1");
        sheet1.getRow(5).getCell(3).setCellValue("1");
        //获取创建工作簿的第3页
        Sheet sheet2=workbook.getSheetAt(2);
        System.out.println("================");
        for (int i = 0;i<sheet2.getPhysicalNumberOfRows();i++){
            Row row = sheet2.getRow(i);
            if (row == null) continue;
            System.out.println(row.getRowNum() + JSONUtil.toJsonStr(row));;
        }
        //获取当前工作簿的行数
//        int totalRows2=sheet1.getPhysicalNumberOfRows();

        sheet2.getRow(2).getCell(3).setCellValue("1");
        sheet2.getRow(3).getCell(3).setCellValue("3");
        sheet2.getRow(5).getCell(3).setCellValue("111");
        sheet2.getRow(5).getCell(5).setCellValue("3333");
        sheet2.getRow(11).getCell(3).setCellValue("3333");
        sheet2.getRow(11).getCell(5).setCellValue("3333");
        /*int newRowIndex = 3;//起始行 从第4行开始
        //获取模板对应的数据表字段的值
        Row dataRow=sheet.getRow(newRowIndex++);
        //获得该行对应的字段的数量
        int columnNum=dataRow.getPhysicalNumberOfCells();

        //将结果集渲染到当前sheet当中
        for (Map<String,Object> pageData:printVoList) {
            sheet.shiftRows(newRowIndex, totalRows + 1, 1); //在startRow和endRow之间的行移动一行
            Row newRow = sheet.createRow(newRowIndex++);
            //创建需要插入的目标行,该值需要在每次完成一行记录值插入后重新归0
            int cellIndex = 0;

            //ic此处为cells数组的结果集的字段的位置
            for (int i = 1; i <= columnNum; i++) {
                //从pageData当中取出目标单元格需要的值
                String cellContent = pageData.get("COL"+i) != null ? String.valueOf(pageData.get("COL"+i)) : "";
                //设置目标单元格的位置和类型
                Cell cell = newRow.createCell(cellIndex++, Cell.CELL_TYPE_STRING);
                //设置目标单元格的值
                cell.setCellValue(cellContent);
            }
        }*/
        workbook.write(out);
        out.flush();
        out.close();

    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络实验二:Packet Tracer的简单使用

目录 实验二&#xff1a;Packet Tracer的简单使用 2.1 实验目的 2.2 实验步骤 2.2.1 构建网络拓扑 2.2.2 配置各网络设备 2.2.3 网络功能验证测试 2.3 实验总结 实验二&#xff1a;Packet Tracer的简单使用 2.1 实验目的 ①练习packet tracer仿真软件的安装&#xff1…

mc我的世界服务器多少钱一个月?

我的世界服务器多少钱一个月&#xff1f;低至7元一个月&#xff0c;阿里云和腾讯云均可以选择mc服务器&#xff0c;阿里云2核2G3M轻量服务器87元一年、腾讯云轻量2核2G3M服务器88元一年&#xff0c;阿里云ECS云服务器2核2G3M带宽99元一年&#xff0c;腾讯云2核4G5M带宽轻量应用…

活动回顾丨云原生技术实践营上海站「云原生 AI 大数据」专场(附 PPT)

AI 势不可挡&#xff0c;“智算”赋能未来。2024 年 1 月 5 日&#xff0c;云原生技术实践营「云原生 AI &大数据」专场在上海落幕。活动聚焦容器、可观测、微服务产品技术领域&#xff0c;以云原生 AI 工程化落地为主要方向&#xff0c;希望帮助企业和开发者更快、更高效地…

菜鸡后端的前端学习记录

前言 记录一下看视频学习前端的的一些笔记&#xff0c;以前对Html、Js、CSS有一定的基础&#xff08;都认得&#xff0c;没用过&#xff09;&#xff0c;现在不想从头再来了&#xff0c;学学Vue框架&#xff0c;不定时更新&#xff0c;指不定什么时候就鸽了。。。。 Vue2 01…

初识汇编指令

1. ARM汇编指令 目的 认识汇编, 从而更好的进行C语言编程 RAM指令格式: 了解 4字节宽度 地址4字节对齐 方便寻址 1.1 指令码组成部分 : condition: 高4bit[31:28] 条件码 0-15 &#xff08;16个值 &#xff09; 条件码: 用于指令的 条件执行 , ARM指定绝大部分 都可…

Linux之快速入门(CentOS 7)

文章目录 一、Linux目录结构二、常用命令2.1 切换用户2.2查看ip地址2.3 cd2.4 目录查看2.5 查看文件内容2.6 创建目录及文件2.7 复制和移动2.82.93.0 一、Linux目录结构 目录作用/bin是 Binaries (二进制文件) 的缩写,这个目录存放着最经常使用的命令/dev是 Device(设备) 的缩写…

【GitHub项目推荐--不错的Rust开源项目】【转载】

01 Rust 即时模式 GUI 库 egui 是一个简单、快速且高度可移植的 Rust 即时模式 GUI 库&#xff0c;可以轻松地将其集成到你选择的游戏引擎中&#xff0c;旨在成为最易于使用的 Rust GUI 库&#xff0c;以及在 Rust 中制作 Web 应用程序的最简单方法。 项目地址&#xff1a;ht…

go 依赖注入设计与实现

在现代的 web 框架里面&#xff0c;基本都有实现了依赖注入的功能&#xff0c;可以让我们很方便地对应用的依赖进行管理&#xff0c;同时免去在各个地方 new 对象的麻烦。比如 Laravel 里面的 Application&#xff0c;又或者 Java 的 Spring 框架也自带依赖注入功能。 今天我们…

【ASOC全解析(一)】ASOC架构简介和欲解决的问题

【ASOC全解析&#xff08;一&#xff09;】ASOC架构简介和欲解决的问题 一、什么是ASOC以及ASOC解决的三个问题二、ASOC的组成与功能解决第一个问题解决第二个问题解决第三个问题 三、ASOC基本工作原理 /********************************************************************…

Parade Series - Android Studio

硬件支持 CPU i7 RAM 16Gb -------------- ------- Java 3Gb Android 33GbJava Enviroment C:\ ├─ Java │ ├─ jdk1.8.0_181 │ ├─ jre1.8.0_181 │ ├─ maven-3.8.5 │ └─ gradle-6.5 └─ Cache├─ gr…

基于中文垃圾短信数据集的经典文本分类算法实现

垃圾短信的泛滥给人们的日常生活带来了严重干扰&#xff0c;其中诈骗短信更是威胁到人们的信息与财产安全。因此&#xff0c;研究如何构建一种自动拦截过滤垃圾短信的机制有较强的实际应用价值。本文基于中文垃圾短信数据集&#xff0c;分别对比了朴素贝叶斯、逻辑回归、随机森…

哈希--73. 矩阵置零/medium 理解度A

73. 矩阵置零 1、题目2、题目分析3、复杂度最优解代码示例4、适用场景 1、题目 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,…

Overleaf(LaTeX文档在线编写平台)使用学习记录

一、LaTeX简概[1] LaTeX&#xff0c;是一种基于TEX的排版系统&#xff0c;是一种可以处理排版和渲染的标记语言。由美国计算机科学家莱斯利兰伯特在20世纪80年代初期开发&#xff0c;利用这种格式系统的处理&#xff0c;即使用户没有排版和程序设计的知识也可以充分发挥由TEX所…

CACTER邮件安全网关独家安全解决方案——保障企业邮件系统安全

随着科技的不断发展&#xff0c;网络攻击技术也在不断演变&#xff0c;尤其是在电子邮件领域&#xff0c;各种高级变种威胁层出不穷&#xff0c;比如定制化的钓鱼邮件和带有高级恶意软件的邮件等。这些威胁邮件往往能够绕过传统的安全防护措施&#xff0c;包括反垃圾邮件、反钓…

软件安全测试的重要性简析,专业安全测试报告如何申请?

在当今数字化时代&#xff0c;软件在我们的日常生活中扮演着至关重要的角色&#xff0c;但也带来了各种潜在的安全威胁。为了保障用户的信息安全和维护软件的可靠性&#xff0c;软件安全测试显得尤为重要。 软件安全测试是指通过一系列的方法和技术&#xff0c;对软件系统中的…

pikachu_csrf通关攻略

csrf&#xff08;get&#xff09; 打开pikachu靶场&#xff1a; 1. 根据提示给的账户密码进行登录 2. 打开代理拦截数据包将拦截数据发送到已打开的burp中&#xff1a; 修改数据进行发包&#xff1a; 从上面的url可见&#xff0c;修改用户信息的时候&#xff0c;是不带任何不…

性能优化(CPU优化技术)-NEON指令介绍

「发表于知乎专栏《移动端算法优化》」 本文主要介绍了 NEON 指令相关的知识&#xff0c;首先通过讲解 arm 指令集的分类&#xff0c;NEON寄存器的类型&#xff0c;树立基本概念。然后进一步梳理了 NEON 汇编以及 intrinsics 指令的格式。最后结合指令的分类&#xff0c;使用例…

如何基于 ESP32 芯片测试 WiFi 连接距离、获取连接的 AP 信号强度(RSSI)以及 WiFi吞吐测试

测试说明&#xff1a; 测试 WiFi 连接距离&#xff0c;是将 ESP32 作为 WiFi Station 模式来连接路由器&#xff0c;通过在开阔环境下进行拉距来测试。另外&#xff0c;可以通过增大 WiFi TX Power 来增大连接距离。 获取连接的 AP 信号强度&#xff0c;一般可以通过 WiFi 扫描…

机器学习_从线性回归到逻辑回归原理和实战

文章目录 介绍分类问题用线性回归阶跃函数完成分类通过 Sigmiod 函数进行转换逻辑回归的假设函数逻辑回归的损失函数用逻辑回归解决二元分类问题 介绍分类问题 机器学习两个主要应用是回归和分类问题。 逻辑回归算法的本质其实仍然是回归。这个算法也是通过调整权重w和偏置b来…

GBASE南大通用提供给.NET 应用程序访问 GBase 数据库、获取数据、管理数据的一套完整的解决方案

GBase ADO.NET&#xff08;全称是 .NET Framework Data Provider For GBase&#xff09;提 供给.NET 应用程序访问 GBase 数据库、获取数据、管理数据的一套完整的解决 方案。 GBase ADO.NET 的四个核心类及若干功能类具有以下功能&#xff1a;  建立和管理与 GBase 数据库连…