热门标签 | 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;没有存储图片文件。不过估计也不难。


推荐阅读
  • 过去查询Mysql的时候,都见3306对所有端口开放着,感觉不安全。netstat&nbsp;-anlp&nbsp;|&nbsp;grep&nbsp;mysqltcp&nbsp;0&am ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • Ihavetwomethodsofgeneratingmdistinctrandomnumbersintherange[0..n-1]我有两种方法在范围[0.n-1]中生 ... [详细]
  • 零拷贝技术是提高I/O性能的重要手段,常用于Java NIO、Netty、Kafka等框架中。本文将详细解析零拷贝技术的原理及其应用。 ... [详细]
  • oracle c3p0 dword 60,web_day10 dbcp c3p0 dbutils
    createdatabasemydbcharactersetutf8;alertdatabasemydbcharactersetutf8;1.自定义连接池为了不去经常创建连接和释放 ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式
    大类|电阻器_使用Requests、Etree、BeautifulSoup、Pandas和Path库进行数据抓取与处理 | 将指定区域内容保存为HTML和Excel格式 ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 本项目通过Python编程实现了一个简单的汇率转换器v1.02。主要内容包括:1. Python的基本语法元素:(1)缩进:用于表示代码的层次结构,是Python中定义程序框架的唯一方式;(2)注释:提供开发者说明信息,不参与实际运行,通常每个代码块添加一个注释;(3)常量和变量:用于存储和操作数据,是程序执行过程中的重要组成部分。此外,项目还涉及了函数定义、用户输入处理和异常捕获等高级特性,以确保程序的健壮性和易用性。 ... [详细]
  • 本文详细解析了客户端与服务器之间的交互过程,重点介绍了Socket通信机制。IP地址由32位的4个8位二进制数组成,分为网络地址和主机地址两部分。通过使用 `ipconfig /all` 命令,用户可以查看详细的IP配置信息。此外,文章还介绍了如何使用 `ping` 命令测试网络连通性,例如 `ping 127.0.0.1` 可以检测本机网络是否正常。这些技术细节对于理解网络通信的基本原理具有重要意义。 ... [详细]
  • 本教程详细介绍了如何使用 Spring Boot 创建一个简单的 Hello World 应用程序。适合初学者快速上手。 ... [详细]
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社区 版权所有