服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|JavaScript|易语言|

服务器之家 - 编程语言 - Java教程 - java导出Excel文件的步骤全纪录

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

2021-05-30 16:04烦嚣的人 Java教程

这篇文章主要给大家介绍了关于java导出Excel文件的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、背景

当前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的定义,举个例子如下:

?
1
2
3
4
5
string[][] header = {
 {"field1","参数1"}
 ,{"field2","参数2"}
 ,{"field3","参数3"}
}

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

二、怎么用

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

?
1
2
3
4
5
6
7
8
9
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:

?
1
2
3
4
5
6
7
8
9
string[][] sheeta = {
 {"name","姓名"}
 ,{"address","住址"}
}
string[][] sheetb = {
 {"id","id"}
 ,{"sum","余额"}
 ,{"cat","猫的名字"}
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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、创建表头

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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语句,根据属性类别设值,主要代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * 设置单元格,根据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教程如何在Mac下配置多个Java版本

    如何在Mac下配置多个Java版本

    这篇文章主要介绍了如何在Mac下配置多个Java版本以及需要注意的点详细说明,需要的朋友参考下步骤吧。...

    Java教程网11712021-03-31
  • Java教程IDEA开启Run Dashboard的配置详解

    IDEA开启Run Dashboard的配置详解

    这篇文章主要介绍了IDEA开启Run Dashboard的配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    脚印5432020-06-15
  • Java教程详谈Java静态动态的问题

    详谈Java静态动态的问题

    下面小编就为大家带来一篇详谈Java静态动态的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    anqiang19957632021-01-04
  • Java教程Java与C++实现相同的MD5加密算法简单实例

    Java与C++实现相同的MD5加密算法简单实例

    下面小编就为大家带来一篇Java与C++实现相同的MD5加密算法简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    jingxian3852020-06-18
  • Java教程浅谈java 增强型的for循环 for each

    浅谈java 增强型的for循环 for each

    下面小编就为大家带来一篇浅谈java 增强型的for循环 for each。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...

    java教程网1972020-06-20
  • Java教程15个高级Java多线程面试题及回答

    15个高级Java多线程面试题及回答

    这篇文章主要介绍了15个高级Java多线程面试题及回答,翻译自国外的一篇文章,这些面试题容易混淆、较难回答,需要的朋友可以参考下吧 ...

    Java教程网2152019-11-23
  • Java教程java 基础知识之IO总结

    java 基础知识之IO总结

    这篇文章主要介绍了java 基础知识之IO总结的相关资料,Java中的I/O分为两种类型,一种是顺序读取,一种是随机读取,需要的朋友可以参考下...

    Java之家4462020-08-25
  • Java教程Java的字符串中对子字符串的查找方法总结

    Java的字符串中对子字符串的查找方法总结

    这篇文章主要介绍了Java的字符串中对子字符串的查找方法总结,是Java入门学习中的基础知识,需要的朋友可以参考下 ...

    iceFin4962020-01-13