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


推荐阅读
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 如何用JNI技术调用Java接口以及提高Java性能的详解
    本文介绍了如何使用JNI技术调用Java接口,并详细解析了如何通过JNI技术提高Java的性能。同时还讨论了JNI调用Java的private方法、Java开发中使用JNI技术的情况以及使用Java的JNI技术调用C++时的运行效率问题。文章还介绍了JNIEnv类型的使用方法,包括创建Java对象、调用Java对象的方法、获取Java对象的属性等操作。 ... [详细]
  • GreenDAO快速入门
    前言之前在自己做项目的时候,用到了GreenDAO数据库,其实对于数据库辅助工具库从OrmLite,到litePal再到GreenDAO,总是在不停的切换,但是没有真正去了解他们的 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • PHP反射API的功能和用途详解
    本文详细介绍了PHP反射API的功能和用途,包括动态获取信息和调用对象方法的功能,以及自动加载插件、生成文档、扩充PHP语言等用途。通过反射API,可以获取类的元数据,创建类的实例,调用方法,传递参数,动态调用类的静态方法等。PHP反射API是一种内建的OOP技术扩展,通过使用Reflection、ReflectionClass和ReflectionMethod等类,可以帮助我们分析其他类、接口、方法、属性和扩展。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • 本文介绍了解决java开源项目apache commons email简单使用报错的方法,包括使用正确的JAR包和正确的代码配置,以及相关参数的设置。详细介绍了如何使用apache commons email发送邮件。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 本文介绍了在C#中SByte类型的GetHashCode方法,该方法用于获取当前SByte实例的HashCode。给出了该方法的语法和返回值,并提供了一个示例程序演示了该方法的使用。 ... [详细]
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社区 版权所有