①需求背景:企业实际项目中,一般都会少不了数据导出Excel表!今天亲自尝试了一下,记录如下。
②材料准备:
《1》POI的jar包(我是在maven项目中直接导入的POI3.7版本,小伙伴们可以自己搜一下导入,一大把,这里就不贴了)
<dependencies>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>servlet</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
《2》建了一个pojo实体类
package pojo;
public class Information {
private String name;
private Integer age;
private Integer score;
public Information() {
}
public Information(String name, Integer age, Integer score) {
this.name = name;
this.age = age;
this.score = score;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getScore() {
return score;
}
public void setScore(Integer score) {
this.score = score;
}
}
③实现代码如下
熟悉Excel的都知道大致结构,我先理一下思路:
<1>先有工作簿(WorkBook)--->再有工作表(Sheet)--->再有行(Row)--->再有单元格(Cell)
<2>Cell单元格格式主要分字体格式(Font)和单元格格式(CellStyle),其中CellStyle包含Font
<3>一般会设置两套单元格格式,一套为首行使用(一般是列字段信息,为了突出表格包含内容重点什么的,也为了区分和表中数据的不同,因为测试嘛,我这里就没有写了),一套为表格中数据使用
package basetest.projecttest.poitest;
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import pojo.Information;
import java.io.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class POITest {
public static void main(String[] args) throws FileNotFoundException {
//准备单元格数据
List<Information> data = new ArrayList<Information>();
data.add(new Information("zhangsan",22,99));
data.add(new Information("lisi",25,100));
data.add(new Information("wangwu",20,89));
data.add(new Information("xialijun",24,90));
//准备表头字段
String names[] = {"姓名", "年龄", "分数"};
//创建工作簿
Workbook wk = new HSSFWorkbook();
Sheet sheet = wk.createSheet("2019年度成绩报告");
sheet.setDefaultColumnWidth(10);
//创建行
Row row = sheet.createRow(0);
for (int i = 0; i < 3; i++) {
//创建单元格
Cell cell = row.createCell(i);
//设置单元格内容
HSSFRichTextString text = new HSSFRichTextString(names[i]);
cell.setCellValue(text);
//设置单元格样式(基于工作簿)
CellStyle cs = wk.createCellStyle();
//设置单元格字体
Font font = wk.createFont();
font.setBoldweight((short)15);
font.setFontHeight((short)14);
cs.setBorderBottom((short) 1);
cs.setBorderLeft((short) 1);
cs.setBorderRight((short) 1);
cs.setFont(font);
}
//填写sheet数据(使用reflect方式)
for (int i = 0; i < data.size(); i++) {
Row row1 = sheet.createRow(i + 1);
//获取每一个对象
Information info1 = data.get(i);
//根据实例对象拿到字节码文件对象
Class<? extends Information> infoClass = info1.getClass();
//真实中需要传入封装导出类文件的字段组成的String[]
String[] filedNames = {"name", "age", "score"};
//遍历属性填充数据
for (int i1 = 0; i1 < filedNames.length; i1++) {
String filedName = filedNames[i1].substring(0, 1).toUpperCase() + filedNames[i1].substring(1);
try {
Method method = infoClass.getMethod("get" + filedName);
Object o = method.invoke(info1);
if (o != null) {
row1.createCell(i1).setCellValue(o.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/*for (int i1 = 0; i1 < names.length; i1++) {
Cell cell = row1.createCell(0);
cell.setCellValue(data.get(i).getName());
Cell cell1 = row1.createCell(1);
cell1.setCellValue(data.get(i).getAge());
Cell cell2 = row1.createCell(2);
cell2.setCellValue(data.get(i).getScore());
}*/
}
//流形式写出excel
FileOutputStream fos=new FileOutputStream(new File("d:\\a.xls"));
try {
wk.write(fos);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
重点:表中数据基本根据Javabean来对应映射,所以我这里填充表中数据(上面代码标红地方)的是使用反射机制来写的,思路是这样:
先遍历整体数据组成的List集合(代码中的List<Information> data)--->获取一个个Information,拿到字节码文件对象--->Information类中的成员变量名称组成字符串数组(String[ ] fileNames)--->处理每一个元素,然后得到相应的方法对象(Method method)--->反射调用(method.invoke(Object obj))得到具体值填充进Excel中去。最后用输出流写出
④结果检验
⑤本来想自己封装一下
String[] filedNames = {"name", "age", "score"}; 这句代码提高可用性,但是看了反射底层代码,不是很明白,还是后面再想想吧!
欢迎小伙伴交流讨论(夏李逸笙:XLYS_000@126.com)