在java中使用Apache POI导出Excel文档,基本的工具类与Annotation封装,可对任意简单对象直接使用
做了个导出Excel文档的需求
于是写了个泛用性挺高的工具,只要是简单对象都没问题。即对象Field的类型都为基本数据类型及其包装类、String、Date这些就可以。要是对象里边还有集合啊、对象啊啥的就不行了。
挺简单的,就懒得传到Github了,写篇博客记录一下。
既然要使用apache poi,,首先就得导入依赖
XML:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.8</version>
</dependency>
用Gradle的话就在dependencies中加入这个:
compile('org.apache.poi:poi:3.8')
这是我写的注解,使用在成员属性上。
name为Excel中该属性的列名,会在第一行并且加粗放大显示。num是列号,从0开始。
在某属性上写 @ExcelParam(name=”价格”,num=1) 这样的注解,则表示该属性会在 Excel表格 的第二列,第一行标题会显示加粗放大的”价格”
只有加了注解的属性会被下面我封装的工具所读取。没有加注解的不会,这样就实现了一个自由的定制。
并且随意指定列名和该属性处于哪一列,可以说实现了大部分简单的 Excel 生成需求了
package com.skypyb.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ExcelParam {
String name();
int num();
}
必要的注解加上后就可以直接使用了。
只需要调用 ExcelCreateUtil.toExcel() 方法,将对象集合传入进来就行了。他将返回 HSSFWorkbook 对象,即 Excel 对象(.xls为后缀格式的)
对象集合中的对象,那肯定需要某些属性加了 @ExcelParam 注解,不然他什么都不会做。只会返回一个空的 Excel 文档回来。
成功返回 HSSFWorkbook 对象后可使用它的 write() 方法将内容输出到输出流之中,之后的操作都随意了,可以输出到响应的流中返回给客户端让其下载,也可以输入到文件流中保存在本地。只要文件名是以.xls结尾就行。
package com.skypyb.util;
import com.rocket.annotations.ExcelParam;
import org.apache.poi.hssf.usermodel.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
public class ExcelCreateUtil {
/**
* 将一个对象集合变成 Excel 文档
* HSSFWorkbook 对象可使用 write() 方法将内容输出到输出流之中
*
* @param objList
* @return
*/
public static HSSFWorkbook toExcel(List objList) {
if (objList == null || objList.size() == 0) throw new NullPointerException();
HSSFWorkbook book = new HSSFWorkbook();
HSSFSheet sheet = book.createSheet("a");//sheet 名字
Class clazz = objList.get(0).getClass();//字节码
Field[] fields = clazz.getDeclaredFields();//属性
HSSFCellStyle dateStyle = getDateStyle(book);//日期样式
//内容初始化
for (int rowNum = 0; rowNum < objList.size(); rowNum++) {
HSSFRow row = sheet.createRow(rowNum + 1);//创建新行,行号从1开始
for (Field field : fields) {
ExcelParam param = field.getAnnotation(ExcelParam.class);
if (param == null) continue;
HSSFCell cell = row.createCell(param.num());//这是每一行中的单元格
Object invoke = getFieldValue(clazz, field, objList.get(rowNum));
if (invoke == null) continue;
//如果是日期类型的话,则需要使用上边的样式
if (invoke.getClass().getSimpleName().equals("Date")) {
cell.setCellValue((Date) invoke);
cell.setCellStyle(dateStyle);
} else cell.setCellValue(invoke.toString());
}
}
//标题行的初始化
HSSFRow row = sheet.createRow(0);//第一行
row.setHeightInPoints(30F);
HSSFCellStyle titleStyle = getTitleStyle(book);//标题样式
for (Field field : fields) {
ExcelParam param = field.getAnnotation(ExcelParam.class);
if (param == null) continue;
HSSFCell cell = row.createCell(param.num());
cell.setCellValue(param.name());
cell.setCellStyle(titleStyle);
sheet.autoSizeColumn(param.num());//设置单元格自动大小
}
return book;
}
/**
* 获取日期样式
* 在excel中会以格式化的日期进行显示
*
* @param book
* @return
*/
private static HSSFCellStyle getDateStyle(HSSFWorkbook book){
HSSFCellStyle style = book.createCellStyle();
HSSFCreationHelper creationHelper = book.getCreationHelper();
style.setDataFormat(creationHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
return style;
}
/**
* 获取标题样式
* 加粗+变大
*
* @param book
* @return
*/
private static HSSFCellStyle getTitleStyle(HSSFWorkbook book){
HSSFCellStyle style = book.createCellStyle();
HSSFFont font = book.createFont();
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗体显示
font.setFontHeightInPoints((short) 16);//字体大小
style.setFont(font);
return style;
}
/**
* 获取某个属性中的值
* 需要 字节码、属性对象、调用者
*
* @return
*/
private static Object getFieldValue(Class clazz, Field field, Object obj) {
//得到属性的 getter 方法
String filedName = field.getName();
String get = new StringBuffer("get").append(filedName.substring(0, 1)
.toUpperCase()).append(filedName.substring(1)).toString();
try {
Method method = clazz.getMethod(get);
Object invoke = method.invoke(obj);
//设置value值,如果是date类型则会设置date的样式
return invoke;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
