java导出Excel文件的步骤全纪录

作者:烦嚣的人 时间:2021-10-04 11:18:38 

一、背景

当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统、银行系统)。或者是:我们已经习惯用Excel打印。这样在我们实际的开发中,很多时候需要实现导入、导出Excel的应用。

最近在java上做了一个EXCEL的导出功能,写了一个通用类,在这里分享分享,该类支持多sheet,且无需手动进行复杂的类型转换,只需提供三个参数即可:

1、fileName

excel文件名

2、HasMap<String,List<?>> data

具体的数据,每个List代表一张表的数据,?表示可为任意的自定义对象

3、LinkedHashMap<String,String[][]> headers

Stirng代表sheet名。每个String[][]代表一个sheet的定义,举个例子如下:


String[][] header = {
{"field1","参数1"}
,{"field2","参数2"}
,{"field3","参数3"}
}

其中的field1,field2,field3为对象中的属性名,参数1,参数2,参数3为列名,实际上这个指定了列的名称和这个列用到数据对象的哪个属性。

二、怎么用

以一个例子来说明怎么用,假设有两个类A和B定义如下:


public class A{
private String name;
private String address;
}
public class B{
private int id;
private double sum;
private String cat;
}

现在我们通过查询数据库获得了A和B的两个列表:

List<A> dataA = .....;
List<B> dataB = .....;

我们将这两个导出到excel中,首先需要定义sheet:


String[][] sheetA = {
{"name","姓名"}
,{"address","住址"}
}
String[][] sheetB = {
{"id","ID"}
,{"sum","余额"}
,{"cat","猫的名字"}
}

然后将数据汇总构造一个ExcelUtil:


String fileName = "测试Excel";
HashMap<String,List<?>> data = new HashMap<>();
//ASheet为表名,后面headers里的key要跟这里一致
data.put("ASheet",dataA);
data.put("BSheet",dataB);
LinkedHashMap<String,String[][]> headers = new LinkedHashMap<>();
headers.put("ASheet",sheetA);
headers.put("BSheet",sheetB);
ExcelUtil excelUtil = new ExcelUtil(fileName,data,headers);
//获取表格对象
HSSFWorkbook workbook = excelUtil.createExcel();
//这里内置了一个写到response的方法(判断浏览器类型设置合适的参数),如果想写到文件也是类似的
workbook.writeToResponse(workbook,request,response);

当然通常数据是通过数据库查询的,这里为了演示方便没有从数据库查找。

三、实现原理

这里简单说明下实现过程,从调用createExcel()这里开始

1、遍历headers创建sheet


public HSSFWorkbook createExcel() throws Exception {
 try {
  HSSFWorkbook workbook = new HSSFWorkbook();
  //遍历headers创建表格
  for (String key : headers.keySet()) {
   this.createSheet(workbook, key, headers.get(key), this.data.get(key));
  }
  return workbook;
 } catch (Exception e) {
  log.error("创建表格失败:{}", e.getMessage());
  throw e;
 }
}

将workbook,sheet名,表头数据,行数据传入crateSheet方法中创建sheet。

2、创建表头

表头也就是一个表格的第一行,通常用来对列进行说明


 HSSFSheet sheet = workbook.createSheet(sheetName);
 // 列数
 int cellNum = header.length;
 // 单元行,单元格
 HSSFRow row;
 HSSFCell cell;
 // 表头单元格样式
 HSSFCellStyle columnTopStyle = this.getColumnTopStyle(workbook);
 // 设置表头
 row = sheet.createRow(0);
 for (int i = 0; i < cellNum; i++) {
  cell = row.createCell(i);
  cell.setCellStyle(columnTopStyle);
  String str = header[i][1];
  cell.setCellValue(str);
  // 设置列宽为表头的文字宽度+6个半角符号宽度
  sheet.setColumnWidth(i, (str.getBytes("utf-8").length + 6) * 256);
 }

3、插入行数据

这里是最重要的部分,首先通过数据的类对象获取它的反射属性Field类,然后将属性名和Field做一个hash映射,避免循环查找,提高插入速度,接着通过一个switch语句,根据属性类别设值,主要代码如下:


/**
* 设置单元格,根据fieldName获取对应的Field类,使用反射得到值
*
* @param cell 单元格实例
* @param obj 存有属性的对象实例
* @param fieldMap 属性名与Field的映射
* @param fieldName 属性名
*/
private void setCell(HSSFCell cell, Object obj, Map<String, Field> fieldMap, String fieldName) throws Exception {
//获取该属性的Field对象
Field field = fieldMap.get(fieldName);
//通过反射获取属性的值,由于不能确定该值的类型,用下面的判断语句进行合适的转型
Object value = field.get(obj);
if (value == null) {
 cell.setCellValue("");
} else {
 switch (field.getGenericType().getTypeName()) {
 case "java.lang.String":
  cell.setCellValue((String) value);
  break;
 case "java.lang.Integer":
 case "int":
  cell.setCellValue((int) value);
  break;
 case "java.lang.Double":
 case "double":
  cell.setCellValue((double) value);
  break;
 case "java.util.Date":
  cell.setCellValue(this.dateFormat.format((Date) value));
  break;
 default:
  cell.setCellValue(obj.toString());
 }
}
}

完整代码可以到github上查看下载,这里就不列出来了。

github地址:点击跳转

来源:https://www.cnblogs.com/wuyoucao/p/9526620.html

标签:java,导出,excel
0
投稿

猜你喜欢

  • Genymotion模拟器常见问题整理与相应解决方法

    2021-11-11 20:36:15
  • 5步学会使用VideoView播放视频

    2023-09-12 05:51:07
  • SWT(JFace)体验之复制粘贴

    2022-11-18 13:47:46
  • Java数据结构之图的基础概念和数据模型详解

    2022-03-25 11:27:04
  • C#资源释放方法实例分析

    2022-03-22 04:46:20
  • 基于Java数组实现循环队列的两种方法小结

    2023-06-30 16:09:01
  • 浅谈Maven镜像更换为阿里云中央仓库(精)

    2022-08-06 04:48:17
  • 深入解析Java多态进阶学习

    2022-05-16 16:06:55
  • mybatisPlus实现倒序拼接字符串

    2021-11-16 08:50:29
  • 使用@符号让C#中的保留字做变量名的方法详解

    2022-06-07 20:22:48
  • java 值Document解析xml详细介绍

    2021-11-13 15:59:00
  • C#处理猜拳问题的简单实例(非窗体)

    2021-08-01 18:58:22
  • java实现简单的webservice方式

    2023-11-25 03:59:58
  • Java异常处理try catch的基本使用

    2023-11-24 05:04:38
  • 使用WebSocket实现即时通讯(一个群聊的聊天室)

    2023-11-29 03:00:46
  • Android中将View的内容保存为图像的简单实例

    2023-11-01 12:45:41
  • java list,set,map,数组间的相互转换详解

    2023-04-11 13:02:04
  • C#语言中字符类char的使用方法(总结)

    2022-09-04 17:25:43
  • C#实现读取txt文件生成Word文档

    2022-08-06 19:03:22
  • c#获取gridview的值代码分享

    2023-06-27 22:23:50
  • asp之家 软件编程 m.aspxhome.com