在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; } }