1.场景描述
使用java实现导出excel报表。使用Apache POI。
Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。
2.Maven依赖
-
<dependency>
-
<groupId>org.apache.poi
</groupId>
-
<artifactId>poi
</artifactId>
-
<version>3.9
</version>
-
</dependency>
-
<dependency>
-
<groupId>org.apache.poi
</groupId>
-
<artifactId>poi-ooxml
</artifactId>
-
<version>3.9
</version>
-
</dependency>
-
<dependency>
-
<groupId>commons-lang
</groupId>
-
<artifactId>commons-lang
</artifactId>
-
<version>2.3
</version>
-
</dependency>
3.代码编写
3.1导出报表类
import com.nnkc.util.ExcelUtil; import org.apache.commons.lang.StringUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.util.List; /** *功能描述:导出报表 */ public class ReportExcel { /** * 功能: Excel导出公共方法 * 记录条数大于50000时 导出.xlsx文件(excel07+) 小于等于50000时导出 .xls文件(excel97-03) * 开发:wangkecheng * @param list 需要导出的列表数据 * @param title 导出文件的标题 * @param className 导出对象的类名 * @param exportType 针对同一个pojo可能有多个不同的导出模板时,可以通过此属性来决定导出哪一套模板,默认第一套 * @param response 用来获取输出流 * @param request 针对火狐浏览器导出时文件名乱码的问题,也可以不传入此值 * @throws IOException */ public void excelExport(List list, String title, Class className, Integer exportType, HttpServletResponse response, HttpServletRequest request) throws IOException { OutputStream out = response.getOutputStream(); try { ExcelUtil excel = new ExcelUtil(); if(list!=null && list.size()>ExcelUtil.EXPORT_07_LEAST_SIZE){ dealBigNumber(list, title, className, exportType, response, request, out, excel); }else{ HSSFWorkbook hss = new HSSFWorkbook(); if(exportType==null){ hss = excel.exportExcel(list,title,className,0); }else{ hss = excel.exportExcel(list, title, className, exportType); } String disposition = "attachment;filename="; if(request!=null&&request.getHeader("USER-AGENT")!=null&& StringUtils.contains(request.getHeader("USER-AGENT"), "Firefox")){ disposition += new String((title+".xls").getBytes(),"ISO8859-1"); }else{ disposition += URLEncoder.encode(title+".xls", "UTF-8"); } response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setHeader("Content-disposition", disposition); hss.write(out); } } catch (Exception e) { System.out.println(e.getMessage()); } finally { out.close(); } } private void dealBigNumber(List list, String title, Class className, Integer exportType, HttpServletResponse response, HttpServletRequest request, OutputStream out, ExcelUtil excel) throws Exception{ SXSSFWorkbook hss; if(exportType==null){ hss = excel.exportExcel07S(list,title,className,0); }else{ hss = excel.exportExcel07S(list, title, className, exportType); } String disposition = "attachment;filename="; if(request!=null && request.getHeader("USER-AGENT") != null && StringUtils.contains(request.getHeader("USER-AGENT"), "Firefox")){ disposition += new String((title+".xlsx").getBytes(),"ISO8859-1"); }else{ disposition += URLEncoder.encode(title+".xlsx", "UTF-8"); } response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); response.setHeader("Content-disposition", disposition); hss.write(out); } }
3.2工具类
-
import org.apache.poi.hssf.usermodel.*;
-
import org.apache.poi.hssf.util.HSSFColor;
-
import org.apache.poi.ss.usermodel.*;
-
import org.apache.poi.ss.util.CellRangeAddress;
-
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
-
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-
-
import java.lang.reflect.Field;
-
import java.lang.reflect.InvocationTargetException;
-
import java.lang.reflect.Method;
-
import java.text.SimpleDateFormat;
-
import java.util.*;
-
-
-
/**
-
* excel工具类
-
* @author wangkecheng
-
* @param
<T>
-
*/
-
public class ExcelUtil
<T> {
-
-
public static final int EXPORT_07_LEAST_SIZE = 50000;
-
/**
-
* 功能 :获取表单导出数据
-
* 开发:wangkecheng
-
* @param list 数据列表
-
* @param title 首行标题
-
* @param className 实体对象class
-
* @param exportType 模板标号
-
* @return
-
* @throws Exception
-
*/
-
public HSSFWorkbook exportExcel(List
<T> list, String title, Class className,Integer exportType) throws Exception {
-
// 获取属性
-
Field[] fields = className.getDeclaredFields();
-
List
<Field> fieldList = new ArrayList
<Field>();
-
for (Field fie : fields) {
-
if (fie.isAnnotationPresent(ExcelAnnotation.class)) {
-
fieldList.add(fie);
-
}
-
}
-
// 按照id进行排序
-
Collections.sort(fieldList, new Comparator
<Field>() {
-
public int compare(Field f1, Field f2) {
-
return f1.getAnnotation(ExcelAnnotation.class).id() - f2.getAnnotation(ExcelAnnotation.class).id();
-
}
-
});
-
int columnsize = fieldList.size(), rowindex = 0;
-
// 创建一个HSSFWorbook对象(excel的文档对象)
-
HSSFWorkbook hWorkbook = new HSSFWorkbook();
-
// 创建一个HSSFSheet对象(excll的表单)
-
HSSFSheet hSheet = hWorkbook.createSheet();
-
// 创建行(excel的行)
-
HSSFRow hRow = hSheet.createRow(rowindex++);
-
//设置行高度
-
hRow.setHeight((short)380);
-
// 创建单元格(从0开始)
-
HSSFCell hCell = hRow.createCell((short) 0);
-
//样式对象
-
HSSFCellStyle cellStyle = getCellStyle(hWorkbook, (short) 300, (short) 500);
-
// 将上面获得的样式对象给对应单元格
-
hCell.setCellStyle(cellStyle);
-
//设置标题行
-
hCell.setCellValue(title);
-
-
if (getHuoResult(fieldList.isEmpty(),list == null,list.isEmpty())) {
-
return hWorkbook;
-
}
-
-
//创建第二行,代表列名
-
hRow = hSheet.createRow(rowindex++);
-
cellStyle = getCellStyle(hWorkbook, (short) 270, (short) 500);
-
generateTitle(exportType, fieldList, columnsize, hSheet, hRow, cellStyle);
-
-
//组装excel的数据
-
cellStyle = getCellStyle(hWorkbook, (short) 220, (short) 500);// 设置单元格格式
-
generateData(list, fieldList, columnsize, rowindex, hSheet, cellStyle);
-
-
/**
-
* 第1个参数:从哪一行开始
-
* 第2个参数:到哪一行结束
-
* 第3个参数:从哪一列开始
-
* 第4个参数:到哪一列结束
-
*/
-
hSheet.addMergedRegion(new CellRangeAddress(0,0,0,columnsize-1));
-
-
// 固定表头(前一个参数代表列,后一个参数单表行)
-
hSheet.createFreezePane(0, 1);
-
return hWorkbook;
-
}
-
-
/**
-
* 功能:組裝列明
-
* @param exportType 模板编号
-
* @param fieldList 列名
-
* @param columnsize 列数
-
* @param hSheet sheet页
-
* @param hRow 行
-
* @param cellStyle 样式
-
*/
-
private void generateTitle(Integer exportType, List
<Field> fieldList, int columnsize, HSSFSheet hSheet, HSSFRow hRow,
-
HSSFCellStyle cellStyle) {
-
HSSFCell hCell;
-
for (int i = 0; i
< columnsize; i++) {
-
Field field = fieldList.get(i);
-
if (field.isAnnotationPresent(ExcelAnnotation.class)) {
-
// 获取该字段的注解对象
-
ExcelAnnotation anno = field.getAnnotation(ExcelAnnotation.class);
-
hCell = hRow.createCell((short) i);
-
String colName = field.getAnnotation(ExcelAnnotation.class).name().length>exportType
-
?field.getAnnotation(ExcelAnnotation.class).name()[exportType]
-
:field.getAnnotation(ExcelAnnotation.class).name()[0];
-
hCell.setCellValue(colName);
-
hCell.setCellStyle(cellStyle);
-
hSheet.setColumnWidth((short) i, (short) anno.width());
-
}
-
}
-
}
-
-
/**
-
* 组装excel的数据
-
* @param list 具体数据
-
* @param fieldList 列名
-
* @param columnsize 列数
-
* @param rowindex 行数计数
-
* @param hSheet sheet页
-
* @param cellStyle 样式
-
* @return
-
* @throws NoSuchMethodException
-
* @throws IllegalAccessException
-
* @throws InvocationTargetException
-
*/
-
private int generateData(List
<T> list, List
<Field> fieldList, int columnsize, int rowindex, HSSFSheet hSheet,
-
HSSFCellStyle cellStyle) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
-
HSSFRow hRow;
-
HSSFCell hCell;
-
for (Object model : list) {
-
hRow = hSheet.createRow(rowindex++);
-
//获取该类
-
Class clazz = model.getClass();
-
for (int i = 0; i
< columnsize; i++) {
-
Field field =fieldList.get(i);
-
//获取方法名
-
String methodName = "get" + field.getName().substring(0, 1).toUpperCase()+field.getName().substring(1);
-
Method method = clazz.getMethod(methodName);
-
try {
-
// 获取该字段的注解对象
-
Object result = method.invoke(model);
-
hCell = hRow.createCell((short) i);
-
if (result != null) {
-
if (result.getClass().isAssignableFrom(Date.class)) {
-
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
-
result = format.format(result);
-
}
-
hCell.setCellValue(new HSSFRichTextString(result.toString()));
-
} else {
-
hCell.setCellValue(new HSSFRichTextString("-"));
-
}
-
hCell.setCellStyle(cellStyle);
-
} catch (IllegalArgumentException e) {
-
System.out.println(e.getMessage());
-
}
-
}
-
}
-
return rowindex;
-
}
-
/**
-
* 生成07格式的excel对象 使用流方式防止内存溢出
-
* @param list
-
* @param title
-
* @param className
-
* @param exportType
-
* @return
-
* @throws Exception
-
*/
-
public SXSSFWorkbook exportExcel07S(List<T> list, String title, Class className,Integer exportType) throws Exception {
-
// 获取属性
-
Field[] fields = className.getDeclaredFields();
-
List
<Field> fieldList = new ArrayList
<Field>();
-
for (Field fie : fields) {
-
if (fie.isAnnotationPresent(ExcelAnnotation.class)){
-
fieldList.add(fie);
-
}
-
}
-
// 按照id进行排序
-
Collections.sort(fieldList, new Comparator
<Field>() {
-
public int compare(Field f1, Field f2) {
-
return f1.getAnnotation(ExcelAnnotation.class).id() - f2.getAnnotation(ExcelAnnotation.class).id();
-
}
-
});
-
-
int columnsize = fieldList.size(), rowindex = 0;
-
// 创建一个HSSFWorbook对象s
-
SXSSFWorkbook hWorkbook = new SXSSFWorkbook();
-
// 创建一个HSSFSheet对象(sheet页)
-
Sheet hSheet = hWorkbook.createSheet();
-
// 创建第一行(此行作为头)
-
Row hRow = hSheet.createRow(rowindex++);
-
hRow.setHeight((short)380);
-
// 创建单元格(第一(0)个)
-
Cell hCell = hRow.createCell((short) 0);
-
// 设置样式
-
CellStyle cellStyle = getCellStyle07S(hWorkbook, (short) 300, (short) 500);
-
// 将上面获得的样式对象给对应单元格
-
hCell.setCellStyle(cellStyle);
-
//设置标题行
-
hCell.setCellValue(title);
-
-
if (getHuoResult(fieldList.isEmpty(),list == null,list.isEmpty())) {
-
return hWorkbook;
-
}
-
-
// 创建第二列,列名
-
hRow = hSheet.createRow(rowindex++);
-
cellStyle = getCellStyle07S(hWorkbook, (short) 270, (short) 500);
-
createTitle07S(exportType, fieldList, columnsize, hSheet, hRow, cellStyle);
-
-
//生成数据
-
cellStyle = getCellStyle07S(hWorkbook, (short) 220, (short) 500);// 设置单元格格式
-
dealCreateRow07S(list, fieldList, columnsize, rowindex, hSheet, cellStyle);
-
-
/**
-
* 第1个参数:从哪一行开始
-
* 第2个参数:到哪一行结束
-
* 第3个参数:从哪一列开始
-
* 第4个参数:到哪一列结束
-
*/
-
hSheet.addMergedRegion(new CellRangeAddress(0,0,0,columnsize-1));
-
-
// 固定表头(前一个参数代表列,后一个参数单表行)
-
hSheet.createFreezePane(0, 1);
-
return hWorkbook;
-
}
-
-
private int dealCreateRow07S(List
<T> list, List
<Field> fieldList, int columnsize, int rowindex, Sheet hSheet,
-
CellStyle cellStyle) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
-
Row hRow;
-
Cell hCell;
-
for (Object model : list) {
-
hRow = hSheet.createRow(rowindex++);
-
// 获取该类 并获取自身方法
-
Class clazz = model.getClass();
-
for (int i = 0; i
< columnsize; i++) {
-
Field field = fieldList.get(i);
-
String methodName = "get" + field.getName().substring(0, 1).toUpperCase()
-
+ field.getName().substring(1);
-
Method method = clazz.getMethod(methodName);
-
try {
-
// 获取该字段的注解对象
-
Object result = method.invoke(model);
-
hCell = hRow.createCell((short) i);
-
if (result != null) {
-
if (result.getClass().isAssignableFrom(Date.class)) {
-
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
-
result = format.format(result);
-
}
-
hCell.setCellValue(new XSSFRichTextString(result.toString()));
-
} else {
-
hCell.setCellValue(new XSSFRichTextString("-"));
-
}
-
hCell.setCellStyle(cellStyle);
-
} catch (IllegalArgumentException e) {
-
System.out.println(e.getMessage());
-
}
-
}
-
}
-
return rowindex;
-
}
-
-
/**
-
* 生成列名
-
* @param exportType 模板编号
-
* @param fieldList 列名
-
* @param columnsize 列数
-
* @param hSheet
-
* @param hRow
-
* @param cellStyle
-
*/
-
private void createTitle07S(Integer exportType, List<Field> fieldList, int columnsize, Sheet hSheet, Row hRow,
-
CellStyle cellStyle) {
-
Cell hCell;
-
for (int i = 0; i
< columnsize; i++) {
-
Field field = (Field) fieldList.get(i);
-
if (field.isAnnotationPresent(ExcelAnnotation.class)) {
-
// 获取该字段的注解对象
-
ExcelAnnotation anno = field.getAnnotation(ExcelAnnotation.class);
-
hCell = hRow.createCell((short) i);
-
String colName = field.getAnnotation(ExcelAnnotation.class).name().length>exportType
-
?field.getAnnotation(ExcelAnnotation.class).name()[exportType]
-
:field.getAnnotation(ExcelAnnotation.class).name()[0];
-
hCell.setCellValue(colName);
-
hCell.setCellStyle(cellStyle);
-
hSheet.setColumnWidth((short) i, (short) anno.width());
-
}
-
}
-
}
-
-
/**
-
* 功能 :设置excel表格默认样式
-
* @param hWorkbook 需导出Excel数据
-
* @param fontHeight 字体粗度
-
* @param boldWeight 表格线的粗度
-
* @return
-
*/
-
public HSSFCellStyle getCellStyle(HSSFWorkbook hWorkbook, short fontHeight, short boldWeight) {
-
HSSFCellStyle cellStyle;
-
HSSFFont font;
-
cellStyle = hWorkbook.createCellStyle();
-
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
-
cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
-
cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
-
cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
-
font = hWorkbook.createFont();
-
font.setFontHeight(fontHeight);
-
font.setBoldweight(boldWeight);
-
font.setFontName("宋体");
-
cellStyle.setFont(font);
-
cellStyle.setWrapText(true);
-
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
-
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
-
return cellStyle;
-
}
-
-
/**
-
* 功能 :设置excel 07表格默认样式
-
* @param hWorkbook 需导出Excel数据
-
* @param fontHeight 字体粗度
-
* @param boldWeight 表格线的粗度
-
* @return
-
*/
-
public CellStyle getCellStyle07S(SXSSFWorkbook hWorkbook, short fontHeight, short boldWeight) {
-
CellStyle cellStyle;
-
Font font;
-
cellStyle = hWorkbook.createCellStyle();
-
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);
-
cellStyle.setTopBorderColor(HSSFColor.BLACK.index);
-
cellStyle.setLeftBorderColor(HSSFColor.BLACK.index);
-
cellStyle.setRightBorderColor(HSSFColor.BLACK.index);
-
cellStyle.setBottomBorderColor(HSSFColor.BLACK.index);
-
font = hWorkbook.createFont();
-
font.setFontHeight(fontHeight);
-
font.setBoldweight(boldWeight);
-
font.setFontName("宋体");
-
cellStyle.setFont(font);
-
cellStyle.setWrapText(true);
-
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
-
cellStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
-
return cellStyle;
-
}
-
-
/*
-
* 获取或运算结果
-
*/
-
private static boolean getHuoResult(Boolean... bs){
-
for(boolean b:bs){
-
if(b){
-
return b;
-
}
-
}
-
return false;
-
}
-
}
3.3注解类
-
import java.lang.annotation.*;
-
-
-
/**
-
*
<p>
-
* 功能:excel模板设置
-
*
</p>
-
*/
-
@Documented
-
@Retention(RetentionPolicy.RUNTIME)
-
@Target(ElementType.FIELD)
-
public @interface ExcelAnnotation {
-
//Excel列ID(Excel列排序序号)
-
int id();
-
//Excel列名
-
String[] name();
-
//Excel列宽
-
int width() default 5000;
-
}
3.4pojo对象
import com.nnkc.util.ExcelAnnotation; import java.util.Date; /** * Created by chengcheng on 2017/12/5. */ public class Product { @ExcelAnnotation(id=1,name={"产品名称","商品名称"},width = 5000) private String name; @ExcelAnnotation(id=2,name={"产品价格","商品价格"},width = 5000) private double price; @ExcelAnnotation(id=3,name={"生产日期"},width = 5000) private Date date; public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
3.5测试类
-
import com.nnkc.pojo.Product;
-
-
import javax.servlet.ServletException;
-
import javax.servlet.http.HttpServlet;
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
import java.io.IOException;
-
import java.util.ArrayList;
-
import java.util.Date;
-
import java.util.List;
-
-
/**
-
* Created by chengcheng on 2017/12/5.
-
*/
-
public class ReportExcelTest extends HttpServlet {
-
-
@Override
-
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-
System.out.println("调用成功");
-
}
-
-
@Override
-
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
-
List
<Product> list = new ArrayList
<Product>();
-
-
for (int i = 0 ; i
<60000 ; i++) {
-
//组装测试数据
-
Product product = new Product();
-
product.setName("爱奇艺会员"+i);
-
product.setPrice(9.99);
-
product.setDate(new Date());
-
list.add(product);
-
}
-
-
ReportExcel reportExcel = new ReportExcel();
-
reportExcel.excelExport(list,"测试",Product.class,1,resp,req);
-
}
-
}
3.5测试结果