Java 超详细实现导入导出 (包含时间转换问题和样式)

news2024/11/24 9:34:58

序言

工作中遇到了导入导出问题,并且出现了导入或导出Excel时间格式变为数字的问题。通过学习解决实现了这些功能,记录总结分享给大家。本文将详细介绍如何使用 Java 编程语言和 Apache POI 库来实现这些功能。我们将通过一个示例项目演示如何从数据库中读取数据并将其导出为 Excel 文件,然后再从 Excel 文件中读取数据并导入回数据库。 

问题

导入或导出 Excel 时,时间格式变为数字的问题通常是由于 Excel 在处理日期时间时的内部表示方式所致。Excel会将日期时间数据存储为一个数字,该数字代表自 1900 年 1 月 1 日以来的天数(对于日期部分)或天数加上小数表示的时间部分。因此,如果不正确处理这些日期时间数据,Excel 可能会显示为日期时间的数字格式,而不是人类可读的日期时间格式。 

例:这是数据库时间 

 

导入之后

 

准备工作

在开始之前,确保你已经准备好以下环境和工具:

  • Java 开发环境(JDK11)
  • Maven 项目管理工具 (3.6.1)
  • IDE(例如 IntelliJ IDEA 或 Eclipse)
  • Apache POI 库
  • Mybatis-Plus / Mybatis 

1. 创建 Maven 项目并导入依赖

首先,创建一个 Maven 项目并在 pom.xml 文件中添加 Apache POI 的依赖:

        <!-- Apache POI -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.3</version> <!-- 版本号根据实际情况调整 -->
        </dependency>

2.实体类和数据库如下

@Data
@TableName("excel")
public class DataEntity {
    private Long id;
    private String name;
    private int age;
    private String email;
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    @TableField(value = "birthday")
    private LocalDate birthday;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(value = "currenttime")
    private LocalDateTime currentTime;
}

 3.yml配置连接数据库,用Mybatis-Plus / Mybatis 写Mapper,Service,Impl此处不再赘述

导出功能实现

1.编写导出功能的 Controller

创建一个 Spring MVC 的 Controller 类,实现数据导出到 Excel 的功能:

@RestController
@RequestMapping("/execl")
public class ExeclController {
    @Resource
    private DataService dataService;

    @GetMapping("/export")
    public ResponseEntity<byte[]> exportDataToExcel() throws IOException {

        //读取数据库全部数据
        List<DataEntity> dataList = dataService.list();

        // 创建一个工作簿
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("Data");

        // 创建表头
        Row headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("ID");
        headerRow.createCell(1).setCellValue("Name");
        headerRow.createCell(2).setCellValue("Age");
        headerRow.createCell(3).setCellValue("Email");
        headerRow.createCell(4).setCellValue("Birthday");
        headerRow.createCell(5).setCellValue("CurrentTime");

        // 日期和时间格式化器
        // 将 LocalDate 和 LocalDateTime 转换为字符串格式
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");


        // 创建日期单元格样式
        //CreationHelper 是 Apache POI 提供的一个帮助类,用于创建各种格式和样式。
        CreationHelper creationHelper = workbook.getCreationHelper();
        //CellStyle 是用于定义单元格样式的类。
        //workbook.createCellStyle() 方法用于创建一个新的单元格样式对象。
        //dateStyle.setDataFormat(...) 方法用于设置单元格的数据格式。
        //creationHelper.createDataFormat().getFormat("yyyy-MM-dd") 方法用于获取日期格式的代码,"yyyy-MM-dd" 是我们想要的日期格式。
        CellStyle dateStyle = workbook.createCellStyle();
        dateStyle.setDataFormat(creationHelper.createDataFormat().getFormat("yyyy-MM-dd"));
        CellStyle dateTimeStyle = workbook.createCellStyle();
        dateTimeStyle.setDataFormat(creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));

        // 填充数据行
        int rowNum = 1;
        for (DataEntity data : dataList) {
            Row row = sheet.createRow(rowNum++);
            row.createCell(0).setCellValue(data.getId());
            row.createCell(1).setCellValue(data.getName());
            row.createCell(2).setCellValue(data.getAge());
            row.createCell(3).setCellValue(data.getEmail());
            // 格式化并设置日期,单元格样式
            Cell birthdayCell = row.createCell(4);
            birthdayCell.setCellValue(data.getBirthday().format(dateFormatter));
            birthdayCell.setCellStyle(dateStyle);

            // 格式化并设置日期,单元格样式
            Cell currentTimeCell = row.createCell(5);
            currentTimeCell.setCellValue(data.getCurrentTime().format(dateTimeFormatter));
            currentTimeCell.setCellStyle(dateTimeStyle);
        }

        // 调整列宽以适应内容
        for (int i = 0; i < 6; i++) {
            sheet.autoSizeColumn(i);
        }

        // 将工作簿写入字节数组输出流
        ByteArrayOutputStream
                outputStream = new ByteArrayOutputStream();
        //这个方法用于将工作簿(通常是Excel文件)的内容写入到一个OutputStream中
        workbook.write(outputStream);
        workbook.close();

        // 将字节数组输出流转换为字节数组
        byte[] bytes = outputStream.toByteArray();

        // 设置响应头
        //HttpHeaders 类:这个类是 Spring 提供的一个方便的 HTTP 头部管理工具类,可以用来设置各种 HTTP 头部字段。
        HttpHeaders headers = new HttpHeaders();
        //设置响应的内容类型(Content-Type)
        //application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 是 Excel 文件的 MIME 类型,表示返回的是一个 Excel 文件。
        //MediaType.parseMediaType 方法:这个方法用来解析 MIME 类型字符串并返回一个 MediaType 对象。
        headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        //设置响应的内容处置方式(Content-Disposition),告诉浏览器如何处理响应的内容。
        //Content-Disposition 头部:这个头部字段有助于控制浏览器对于响应内容的处理方式。它常用于提示浏览器下载文件,而不是直接在浏览器中显示内容。
        //attachment:表示响应的内容是一个附件,应该提示用户下载
        //data.xlsx":表示下载文件的默认名称为 data.xlsx
        headers.setContentDispositionFormData("attachment", "data.xlsx");

        // 返回 Excel 文件作为 ResponseEntity
        return ResponseEntity.ok()
                .headers(headers)
                .body(bytes);
    }

2.浏览器测试,输入http://localhost:你的端口号/execl/export即可下载

 

 

导入功能实现

1. 实现数据导入的 Controller

创建另一个 Controller 类,实现从 Excel 文件导入数据并存入数据库的功能:

@PostMapping("/import")
    public ResponseEntity<String> importDataFromExcel(@RequestParam("file") MultipartFile file) throws IOException {
        // 检查文件是否为空
        if (file.isEmpty()) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("文件为空");
        }

        // 用于存储解析后的数据
        List<DataEntity> dataList = new ArrayList<>();

        // 使用try-with-resources自动关闭资源
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = new XSSFWorkbook(inputStream)) {

            // 获取第一个工作表
            Sheet sheet = workbook.getSheetAt(0);
            int rowNum = 1; // 行号计数器
            for (Row row : sheet) {
                // 跳过表头行
                if (rowNum == 1) {
                    rowNum++;
                    continue;
                }

                // 创建并填充数据实体
                DataEntity data = new DataEntity();
                data.setId((long) row.getCell(0).getNumericCellValue());
                data.setName(row.getCell(1).getStringCellValue());
                data.setAge((int) row.getCell(2).getNumericCellValue());
                data.setEmail(row.getCell(3).getStringCellValue());

                //将字符串转换回 LocalDate 类型
                String birthdayString = row.getCell(4).getStringCellValue();
                LocalDate birthday = LocalDate.parse(birthdayString, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                data.setBirthday(birthday);

                //将字符串转换为 LocalDateTime 类型
                String currentTimeString = row.getCell(5).getStringCellValue();
                LocalDateTime currentTime = LocalDateTime.parse(currentTimeString, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                data.setCurrentTime(currentTime);


                // 添加到数据列表
                dataList.add(data);
            }
        }

        // 将数据保存到数据库
        dataService.saveBatch(dataList);

        // 返回成功响应
        return ResponseEntity.ok("数据导入成功");
    }

2.Postman测试

Excel数据 

 

数据库导入成功

 

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

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

相关文章

STM32学习笔记(十)--I2C、IIC总线协议详解

概述&#xff1a;Inter Integrated Circuit&#xff0c;一组多从 多组多从 有应答 是一种同步&#xff08;具有时钟线需要同步时钟SCL&#xff09;、串行&#xff08;一位一位的往一个方向发送&#xff09;、半双工&#xff08;发送接收存在一种&#xff09;通信总线。 &…

代码随想录算法训练营第六十七天 | 字符串接龙、有向图的完全可达性、岛屿的周长

字符串接龙 文字讲解&#xff1a;110. 字符串接龙 | 代码随想录 解题思路 本题只需要求出最短路径的长度就可以了&#xff08;想到广搜&#xff09;&#xff0c;不用找出具体路径。 所以这道题要解决两个问题&#xff1a; 图中的线是如何连在一起的起点和终点的最短路径长…

Stable Diffusion AI绘画助力建筑设计艺术创新——城市建筑设计大模型分享

大家好&#xff0c;我是向阳 今天我将针对建筑设计方面的AI大模型进行简单介绍&#xff0c;我们将通过富有想象力的关键词或结合Stable Diffusion 的ControlNet 给原本只有黑白线条的线稿变成彩色的效果图&#xff0c;可能你只需要短短几分钟就可以让黑白线稿变成几种甚至十几种…

临时关闭Windows安全中心

在使用WindowsOS是&#xff0c;微软安全中心是我们必不可少的安全防护&#xff0c;但有时我们也会产生想要将其关闭的需求&#xff0c;下面将要介绍如何临时关闭Windows的安全中心 一、打开安全中心、选择“病毒与威胁防护”&#xff0c;点击“管理设置” 之后将其实时保护关闭…

材料科学SCI期刊,中科院3区,收稿范围广,易录用

一、期刊名称 International Journal of Material Forming 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;材料科学 影响因子&#xff1a;2.4 中科院分区&#xff1a;3区 三、期刊征稿范围 该杂志发表和传播材料成型领域的原创研究。该研究应构成对材料…

multiprocessing多进程计算及与rabbitmq消息通讯实践

1. 需求与设计 我所设计的计算服务旨在满足多个客户对复杂计算任务的需求。由于这些计算任务通常耗时较长且资源消耗较大&#xff0c;为了优化客户体验并减少等待时间&#xff0c;我采取了并行计算的策略来显著提升计算效率。 为实现这一目标&#xff0c;我计划利用Python的m…

展讯-源码编译

1.硬件要求 编译主机要求&#xff0c;注意尽量不要使用虚拟机 CPU&#xff1a;Intel(R) Core(TM) i7-4790 CPU 3.60 GHz 内存&#xff1a;8G 硬盘&#xff1a;500G SSD Ubuntu 版本&#xff1a;Ubuntu 64-bit 14.04.5 LTS 这是最低版本要求&#xff0c;实际性能越高越好 2…

尽管担任社长 宫崎英高95%时间还是在做游戏

宫崎英高表示&#xff0c;虽然他是 FromSoftware 工作室的社长&#xff0c;但他日常工作的绝大部分时间都是在指导游戏开发。因魂系列大获成功而成为 FromSoftware 社长的宫崎英高在接受《卫报》采访时表示&#xff0c;企业高管生活并不是他的兴趣所在。 “我喜欢帮助年轻的监督…

数据库精选题(一)(关系数据库设计)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;数据库 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 前言 练习题 题型一&#xff1a;判断关系…

在scrapy中使用Selector提取数据

经院吉吉&#xff1a; 首先说明一下&#xff0c;在scrapy中使用选择器是基于Selector这个对象滴&#xff0c;selector对象在scrapy中通过XPATH或是CSS来提取数据的&#xff0c;我们可以自己创建selector对象&#xff0c;但在实际开发中我们不需要这样做&#xff0c;因为respons…

DAY10-力扣刷题

1.最后一个单词的长度(简单) 58. 最后一个单词的长度 - 力扣&#xff08;LeetCode&#xff09; 给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子…

8.华为两台交换机的三种连接方式access 、trunk、undo portswitch

目的&#xff1a;两台三层交换机的三种连接方式 1.access 2.trunk 3.undo portswitch 模拟机不支持此配置&#xff0c;实体机支持 第一种access CE1配置 [~HUAWEI]vlan batch 10 [~HUAWEI]int Vlanif 10 [~HUAWEI-Vlanif10]ip add 10.10.10.1 24 [~HUAWEI]int g1/0/0 [~HUAWE…

空间复杂度 线性表,顺序表尾插。

各位少年&#xff0c;大家好&#xff0c;我是那一脸阳光&#xff0c;本次分享的主题是时间复杂度和空间复杂度 还有顺序表文章讲解和分享&#xff0c;如有不对可以评论区指导。 时间复杂度例题 // 计算斐波那契递归Fib的时间复杂度&#xff1f; long long Fib(size_t N){if(N…

用友U9-UBF自定义报表-打印模板开发学习笔记

自定义报表、打印模板开发学习笔记 一、基础了解 1、UBF开发工具的了解 Ideconfig.xml配置 True&#xff1a;打印、报表设计模式 False&#xff1a;单据设计模式 2、开发环境试用 BE&#xff1a;实体项目 BF&#xff1a;操作项目 SV&#xff1a;服务项目 分析项目&am…

昨天gitee网站访问不了,开始以为电脑哪里有问题了

昨天gitee网站下午访问不了&#xff0c;开始以为是什么毛病。 结果同样的网络&#xff0c;手机是可以访问的。 当然就ping www.gitee.com 结果也下面那样是正常的 以为是好的&#xff0c;但就是访问www.gitee.com也是不行&#xff0c;后来用阿里云的服务器curl访问是下面情况&…

当flex-direction: column时,设置flex:1不生效解决办法

当需求是: 页面纵向排列,且最后一个元素撑满剩余高度 flex:1在横向排列时是可以的,但是纵向排列会失效,此时需要给最后一个子元素设置align-self: stretch;即可撑满剩余高度 <div class"father"><div class"child child1"></div><div…

2021数学建模C题目– 生产企业原材料的订购与运输

C 题——生产企业原材料的订购与运输 思路&#xff1a;该题主要是通过对供应商的供货能力和运送商的运货能力进行估计&#xff0c;给出合适的材料订购方案 程序获取 第一题问题思路与结果&#xff1a; 对 402 家供应商的供货特征进行量化分析&#xff0c;建立反映保障企业生…

配置 python 脚本操作Excel 环境

在已装python的前提下 一、安装依赖库 pip install pandas pip install openpyxl安装完后&#xff0c;可以在 Python 中运行以下命令来查看 pandas 或 openpyxl 的安装路径&#xff1a; import pandas as pd print(pd.__path__)import openpyxl print(openpyxl.__path__)二、测…

Redis数据过期、淘汰策略

数据过期策略&#xff1a; 惰性删除&#xff1a; 设置该key过期时间后&#xff0c;我们不去管它&#xff0c;当需要该key时&#xff0c;我们在检查其是否过期&#xff0c;如果过期&#xff0c;我们就删掉它&#xff0c;反之返回该key。 这种方式对cpu友好&#xff08;只在用…

lambdastreammaven

1.Lambda &#xff08;1&#xff09;Java 8 Lambda 表达式 在 Java 8 以前&#xff0c;若我们想要把某些功能传递给某个方法&#xff0c;总要去写内部类 或匿名内部类类。代码示例&#xff1a; list.sort(new Comparator<User>() { Override public int compare(User …