热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java导出数据到Excel文件

Java导出数据到Excel文件前言如何导出导出的基本流程测试结果测试数据及结果测试代码ExcelExportUtil.class遇到的问题lombok的问题解决Cell.setC

Java导出数据到Excel文件

  • 前言
  • 如何导出
    • 导出的基本流程
  • 测试结果
    • 测试数据及结果
    • 测试代码
  • ExcelExportUtil.class
  • 遇到的问题
    • lombok的问题
      • 解决
    • Cell.setCellValue()的参数需要具体的类型
      • 解决方法
  • 总结


前言

通过上一篇文章: Java导入Excel文档到数据库
我们了解到了有关使用Java操作Excel文件的基本流程及相关的类
那么现在我们就要做一下将相关的数据导出成Excel文件给用户了。

如何导出

导入的流程我们已经清楚了:
读取Excel文件生成工作簿(Workbook)对象
获取表(Sheet)对象
遍历行所有的单元格(Cell)

获取一行数据(Row)
生成一个相应的对象
数据库存储

重复上述操作,直至遍历完所有的行
大致可以理解为将表里的所有Row变为一个List

那么导出的逻辑就很简单了,反过来就行了:
List变为表里面所有Row

导出的基本流程

1、数据库操作获取一个List
2、创建一个Workbook对象
3、由Workbook获取一个Sheet对象
4、遍历List集合

为每一个对象创建一个Row对象遍历属性集合,为每一个属性值创建一个Cell将对象里的值设置进Cell中

测试结果

这里就不对使用到类再进行赘述了,前言里提到的Java导入Excel文档到数据库一文中,已经说过了。相关的类也在里面,代码部分我只放测试与工具类,其他的在导入里面。

测试数据及结果

在这里插入图片描述
导出结果 - 默认排序
在这里插入图片描述

指定顺序
在这里插入图片描述

测试代码

import org.apache.poi.ss.usermodel.*;import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.*;/*** @author 三文鱼先生* @title* @description* @date 2022/8/11**/
public class TestForParseExcel {public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException, IOException {Map<String , String> map &#61; new HashMap<>();//表头与键值对的映射关系map.put("学号", "id");map.put("姓名" , "name");map.put("科目" , "subject");map.put("分数" , "grade");map.put("班级" , "className");map.put("任课教师" , "teacher");map.put("是否缺课" , "cutClass");List<Student> list &#61; null;try(//这里面的对象会自动关闭InputStream in &#61; new FileInputStream(new File("F:\\学习记录\\测试数据\\Student.xlsx"));//用流来构建工作簿对象Workbook workbook &#61; ExcelImportSheet.getTypeFromExtends(in , "Student.xlsx")) {//根据名称获取单张表对象 也可以使用getSheetAt(int index)获取单张表的对象 获取第一张表Sheet sheet &#61; workbook.getSheetAt(0);list &#61; ExcelImportSheet.getListFromExcel(sheet , Student.class , map);for (Student student : list) {//底层数据库操作 insert什么的System.out.println(student.toString());}}catch(IOException exception) {exception.printStackTrace();} catch (Exception e) {e.printStackTrace();}finally {//写着好看的}Map<String , String> map1 &#61; new HashMap<>();//表头与键值对的映射关系map1.put("id", "学号");map1.put("name" , "姓名");map1.put("subject" , "科目");map1.put("grade" , "分数");map1.put("className" , "班级");map1.put("teacher" , "任课老师");map1.put("cutClass" , "是否缺课");//这里是指定表头顺序 记得把方法参数的null改为orderList
// List orderList &#61; new ArrayList<>();
// orderList.add("id");
// orderList.add("name");
// orderList.add("subject");
// orderList.add("grade");
// orderList.add("className");
// orderList.add("teacher");
// orderList.add("cutClass");//导出逻辑 这里的list是从导入里面哪来的 map1与map不一样 orderList这里为空Workbook workbook &#61; ExcelExportUtil.createWorkbook(list , map1 , 1 , "学生信息表" , null);System.out.println("导出文件位置为&#xff1a;" &#43; ExcelExportUtil.store("F:\\学习记录\\测试数据\\导出excel测试" , workbook , 1));}}

ExcelExportUtil.class

导出工具类&#xff0c;这里值得注意的是:
Map的映射方式是 属性-表头名称
&#xff0c;而导入的映射方式是&#xff1a;表头名称 - 属性
Map中的Key是不一样的。

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.*;/*** &#64;author 三文鱼先生* &#64;title* &#64;description 用于导出数据* &#64;date 2022/8/23**/
public class ExcelExportUtil {/*** &#64;description 考虑到下载方式的不同 这里细化成只获取一个workBook 格式为默认 无格式* &#64;author 三文鱼先生* &#64;date 10:47 2022/8/26* &#64;param list 需要存储为excel的对象集合* &#64;param map 键值对映射 属性 - 表头字段 类似于: name - 姓名* &#64;param type 生成workbook的类型* &#64;param tableName 生成Sheet的名称* &#64;param orderList 表头顺序对应的属性list* &#64;return org.apache.poi.ss.usermodel.Workbook**/public static <T>Workbook createWorkbook(List<T> list , //数据库查询的返回ListMap<String , String> map , //表头映射Integer type , //生成workbook的类型 0 - xls 其他-xlsxString tableName , //表名List<String> orderList //排序的List 为空 则使用默认的顺序) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {//工作簿Workbook workbook &#61; getWorkbookByType(type);//单个表Sheet sheet &#61; workbook.createSheet(tableName);//orderList 表头顺序&#xff0c;可以为空if(orderList &#61;&#61; null || orderList.size() &#61;&#61; 0) {orderList &#61; new ArrayList<>();//获取map映射的顺序for (Map.Entry<String, String> mapEntry : map.entrySet()) {orderList.add(mapEntry.getKey());}}//每列对应的属性参数List<Class> typeClassList &#61; getParamsType(list.get(0).getClass(), orderList);//设置表头的值Row headRow &#61; sheet.createRow(0);for (int i &#61; 0; i < orderList.size(); i&#43;&#43;) {Cell cell &#61; headRow.createCell(i);//设置单元格的属性cell.setCellType(CellType.STRING);cell.setCellValue(map.get(orderList.get(i)));}int index &#61; 1;//单元行Row dataRow &#61; null;//单元格Cell dataCell &#61; null;//遍历Listfor (T t : list) {//获取一行dataRow &#61; sheet.createRow(index);//遍历表头对应属性&#xff0c;给一行数据设置值for (int j &#61; 0; j < orderList.size(); j&#43;&#43;) {//获取一个单元格dataCell &#61; dataRow.createCell(j);//根据对应列的属性 设置对应的值类型及值setCellValueTypeAndValue(dataCell , typeClassList.get(j) ,t.getClass().getMethod(getGetterMethodName(orderList.get(j)) , new Class[]{}).invoke(t , new Class[]{}));}//行下标后移index&#43;&#43;;}//设置值return workbook;}/*** &#64;description 存储到对应的文件夹下* &#64;author 三文鱼先生* &#64;date 10:44 2022/8/26* &#64;param path 文件夹路径* &#64;param workbook 存储的工作簿对象* &#64;param type 存储的类型* &#64;return void**/public static String store(String path , Workbook workbook , Integer type) throws IOException {path &#61; path &#43;File.separator &#43;getNowDate()&#43; workbook.getSheetName(0) &#43; getExtensionByType(type);try(OutputStream outputStream &#61; new FileOutputStream(new File(path))){workbook.write(outputStream);} catch (FileNotFoundException e) {e.printStackTrace();}catch (Exception e) {e.printStackTrace();} finally {workbook.close();}return path;}/*** &#64;description 根据type获取对应文件后缀 0-xls 其他xlsx 默认为xls* &#64;author 三文鱼先生* &#64;date 10:43 2022/8/26* &#64;param type 类型* &#64;return java.lang.String**/public static String getExtensionByType(Integer type) {if(type &#61;&#61; null || type &#61;&#61; 0)return ".xls";elsereturn ".xlsx";}/*** &#64;description 根据所给的type获取对应的工作簿 0-HSSFWorkbook 其他-XSSFWorkbook* &#64;author 三文鱼先生* &#64;date 10:41 2022/8/26* &#64;param type 类型* &#64;return org.apache.poi.ss.usermodel.Workbook**/public static Workbook getWorkbookByType(Integer type) {if(type &#61;&#61; null || type &#61;&#61; 0)return new HSSFWorkbook();elsereturn new XSSFWorkbook();}/*** &#64;description 根据属性名称获取对应的get方法* &#64;author 三文鱼先生* &#64;date 10:38 2022/8/26* &#64;param param 属性名称* &#64;return java.lang.String**/public static String getGetterMethodName(String param) {char[] chars &#61; param.toCharArray();//首字母大写if(Character.isLowerCase(chars[0])) {chars[0] -&#61; 32;}//拼接get方法return "get" &#43; new String(chars);}/*** &#64;description 根据属性的List获取对应的类型List* &#64;author 三文鱼先生* &#64;date 10:37 2022/8/26* &#64;param cs 对应的类* &#64;param paramsList 对应的属性list* &#64;return java.util.List**/public static List<Class> getParamsType(Class cs , List<String> paramsList) {List<Class> typeClass &#61; new ArrayList<>();//对象的所有属性Field[] fields &#61; cs.getDeclaredFields();//临时的属性 - 类型映射Map<String , Class> map &#61; new HashMap();//获取属性名称及类型for (Field field : fields) {map.put(field.getName(), field.getType());}//遍历属性List获取对应的类型Listfor (String s : paramsList) {typeClass.add(map.get(s));}return typeClass;}/*** &#64;description 根据对应的类型 给单元格设置类型和值* &#64;author 三文鱼先生* &#64;date 10:32 2022/8/26* &#64;param cell 单元格* &#64;param cs 属性的类型* &#64;param o get方法获取到的对象* &#64;return void**/public static void setCellValueTypeAndValue(Cell cell , Class cs , Object o) {//这里没有日期类型 需要的自己加就行了if(Boolean.class.equals(cs) || boolean.class.equals(cs)) {//boolean类型cell.setCellType(CellType.BOOLEAN);cell.setCellValue((Boolean) o);} else if (int.class.equals(cs) ||Integer.class.equals(cs)) {//int类型cell.setCellType(CellType.NUMERIC);cell.setCellValue((Integer) o);} else if(double.class.equals(cs)||Double.class.equals(cs)) {//浮点数类型 也可以是float类型什么的cell.setCellType(CellType.NUMERIC);cell.setCellValue((Double) o);} else {//默认为字符串类型cell.setCellType(CellType.STRING);cell.setCellValue((String) o);}}/*** &#64;description 获取当前时间的字符串* &#64;author 三文鱼先生* &#64;date 17:06 2022/8/26* &#64;return java.lang.String**/public static String getNowDate() {SimpleDateFormat simpleDateFormat &#61; new SimpleDateFormat("yyyyMMdd-HHmmss");return simpleDateFormat.format(new Date());}
}

遇到的问题

lombok的问题

boolean属性自动生成的get方法问题。自动生成的方法为&#xff1a;getIs属性名&#xff0c;而不是我以为的get属性名称

解决

自己写一个该属性的get方法即可
在这里插入图片描述

Cell.setCellValue()的参数需要具体的类型

cell.setCellValue()的方法是需要具体的类型的
没有cell.setCellValue(Object o)方法&#xff0c;而是需要具体的类型。
在这里插入图片描述
我没找到使用Class和Object&#xff0c;将一个对象强转为指定Class对象的方法

解决方法

将强转和设置单元格类型&#xff0c;放到一起。也就是这样
在这里插入图片描述

总结

也是不难&#xff0c;不过需要时间。上述需要最应该优化的地方应该是在&#xff0c;
设置单元格的风格&#xff1a;
表头字体可能需要加粗&#xff0c;
字符串包括什么敏感字符&#xff0c;单元格需要标红&#xff0c;
又或者是数字类型的数据超过什么值&#xff0c;需要显示黄色等等
但是由于每个人风格不一样&#xff0c;
所以还是读取完数据&#xff0c;生成了workbook,再拿workbook对象来设置好了。

另一个点就是&#xff0c;没有存储图片文件。不过估计也不难。


推荐阅读
  • 本文探讨了如何利用 Android 的 Movie 类来展示 GIF 动画,并详细介绍了调整 GIF 尺寸以适应不同布局的方法。同时,提供了相关的代码示例和注意事项。 ... [详细]
  • 一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ... [详细]
  • 本文基于Java官方文档进行了适当修改,旨在介绍如何实现一个能够同时处理多个客户端请求的服务端程序。在前文中,我们探讨了单客户端访问的服务端实现,而本篇将深入讲解多客户端环境下的服务端设计与实现。 ... [详细]
  • 小编给大家分享一下Vue3中如何提高开发效率,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获, ... [详细]
  • Hadoop MapReduce 实战案例:手机流量使用统计分析
    本文通过一个具体的Hadoop MapReduce案例,详细介绍了如何利用MapReduce框架来统计和分析手机用户的流量使用情况,包括上行和下行流量的计算以及总流量的汇总。 ... [详细]
  • 本文详细介绍如何在SSM(Spring + Spring MVC + MyBatis)框架中实现分页功能。包括分页的基本概念、数据准备、前端分页栏的设计与实现、后端分页逻辑的编写以及最终的测试步骤。 ... [详细]
  • Python3爬虫入门:pyspider的基本使用[python爬虫入门]
    Python学习网有大量免费的Python入门教程,欢迎大家来学习。本文主要通过爬取去哪儿网的旅游攻略来给大家介绍pyspid ... [详细]
  • 本文将详细探讨 Python 编程语言中 sys.argv 的使用方法及其重要性。通过实际案例,我们将了解如何在命令行环境中传递参数给 Python 脚本,并分析这些参数是如何被处理和使用的。 ... [详细]
  • Kafka入门指南
    本文将详细介绍如何在CentOS 7上安装和配置Kafka,包括必要的环境准备、JDK和Zookeeper的配置步骤。 ... [详细]
  • 本文介绍了如何通过安装和配置php_uploadprogress扩展来实现文件上传时的进度条显示功能。通过一个简单的示例,详细解释了从安装扩展到编写具体代码的全过程。 ... [详细]
  • 在使用mybatis进行mapper.xml测试的时候发生必须为元素类型“mapper”声明属性“namespace”的错误项目目录结构UserMapper和UserMappe ... [详细]
  • Python网络编程:深入探讨TCP粘包问题及解决方案
    本文详细探讨了TCP协议下的粘包现象及其产生的原因,并提供了通过自定义报头解决粘包问题的具体实现方案。同时,对比了TCP与UDP协议在数据传输上的不同特性。 ... [详细]
  • 本文介绍了如何使用 Python 的 Pyglet 库加载并显示图像。Pyglet 是一个用于开发图形用户界面应用的强大工具,特别适用于游戏和多媒体项目。 ... [详细]
  • 函子(Functor)是函数式编程中的一个重要概念,它不仅是一个特殊的容器,还提供了一种优雅的方式来处理值和函数。本文将详细介绍函子的基本概念及其在函数式编程中的应用,包括如何通过函子控制副作用、处理异常以及进行异步操作。 ... [详细]
  • CentOS7通过RealVNC实现多人使用服务器桌面
    背景:公司研发团队通过VNC登录到CentOS服务器的桌面实现软件开发工作为防止数据外泄,需要在RealVNC设置禁止传输文件、访问粘贴板等策略过程&# ... [详细]
author-avatar
只喝大瓶的雪碧
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有