封装类实现
public class GenerateExcelService<O> {
private static final int CELL_WIDTH_DEFAULT = 20;
private XSSFWorkbook workbook;
/**
* 初始化操作
*/
public GenerateExcelService() {
workbook = new XSSFWorkbook();
}
/**
* 创建sheet页
*
* @return sheet页 对象
*/
public XSSFSheet createSheet() {
return workbook.createSheet();
}
public void write(OutputStream out) throws IOException {
workbook.write(out);
}
/**
* 创建sheet页
*
* @param sheetName sheet页名
* @return sheet页 对象
*/
public XSSFSheet createSheet(String sheetName) {
return workbook.createSheet(sheetName);
}
/**
* 创建标题样式
*
* @return 样式
*/
public XSSFCellStyle createTitleStyle() {
return createTitleStyle(250);
}
/**
* 创建标题样式
*
* @param height 字高
* @return 样式
*/
public XSSFCellStyle createTitleStyle(int height) {
XSSFFont boldFont = workbook.createFont();
boldFont.setFontHeight((short) height);
XSSFCellStyle style = workbook.createCellStyle();
style.setFont(boldFont);
style.setDataFormat(HSSFDataFormat.getBuiltinFormat("###,##0.00"));
style.setAlignment(HorizontalAlignment.CENTER_SELECTION);
return style;
}
/**
* 表头对象
*
* @param sheet sheet页
* @return 表头对象
*/
public XSSFRow createTitleRow(XSSFSheet sheet) {
return sheet.createRow(0);
}
/**
* 插入一个单元格数据
*
* @param row 行对象
* @param sheet sheet对象
* @param style 样式对象
* @param columnNum 列号
* @param columnValue 单元格内容
* @param width 宽度
*/
public void insertCell(XSSFSheet sheet, XSSFRow row, XSSFCellStyle style, int columnNum, String columnValue, int width) {
Cell cell = row.createCell(columnNum);
cell.setCellValue(columnValue);
cell.setCellStyle(style);
sheet.setColumnWidth(columnNum, (width * 256)); //设置列宽,50个字符宽
}
/**
* 插入一个单元格数据
*
* @param row 行对象
* @param sheet sheet对象
* @param columnNum 列号
* @param columnValue 单元格内容
* @param width 宽度
*/
public void insertCell(XSSFSheet sheet, XSSFRow row, int columnNum, String columnValue, int width) {
Cell cell = row.createCell(columnNum);
cell.setCellValue(columnValue);
sheet.setColumnWidth(columnNum, (width * 256)); //设置列宽,50个字符宽
}
/**
* 插入一个单元格数据
*
* @param row 行对象
* @param sheet sheet对象
* @param columnNum 列号
* @param columnValue 单元格内容
*/
public void insertCell(XSSFSheet sheet, XSSFRow row, int columnNum, String columnValue) {
insertCell(sheet, row, columnNum, columnValue, 10);
}
/**
* 插入一个单元格数据,默认宽度为10
*
* @param row 行对象
* @param sheet sheet对象
* @param style 样式对象
* @param columnNum 列号
* @param columnValue 单元格内容
*/
public void insertCell(XSSFSheet sheet, XSSFRow row, XSSFCellStyle style, int columnNum, String columnValue) {
insertCell(sheet, row, style, columnNum, columnValue, 10);
}
/**
* 插入单元格数据
*
* @param sheet sheet对象
* @param objList 数据集合
*/
public void insertRow(XSSFSheet sheet, List<O> objList) {
if (objList != null && !objList.isEmpty()) {
AtomicInteger rowNum = new AtomicInteger(1);
objList.forEach(obj -> {
XSSFRow row = sheet.createRow(rowNum.get());
// 获取实体类所有属性,返回Filed数组
obj2Cell(obj, row);
rowNum.getAndIncrement();
});
}
}
/**
* 对象数据转为某一个单元格数据
*
* @param obj 数据对象
* @param row 行数据
*/
private void obj2Cell(O obj, XSSFRow row) {
Class<?> clazz = obj.getClass();
Field[] field = clazz.getDeclaredFields();
int columnIndex = 0;
for (Field item : field) {
// 属性名,此字段一定不为空
String name = item.getName();
// 将属性名的首字母大写,用于构造set/get函数
name = name.substring(0, 1).toUpperCase() + name.substring(1);
// 获取属性的类型
String type = item.getGenericType().toString();
try {
Method m = clazz.getMethod("get" + name);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
switch (type) {
case "class java.lang.String":
//调用getter方法获取属性值
String valueStr = (String) m.invoke(obj);
row.createCell(columnIndex, CellType.STRING).setCellValue(valueStr == null ? "" : valueStr);
break;
case "class java.lang.Integer":
//调用getter方法获取属性值
Integer valueInt = (Integer) m.invoke(obj);
row.createCell(columnIndex, CellType.STRING).setCellValue(valueInt == null ? 0 : valueInt);
break;
case "class java.lang.Short":
//调用getter方法获取属性值
Short valueShort = (Short) m.invoke(obj);
row.createCell(columnIndex, CellType.STRING).setCellValue(valueShort == null ? 0 : valueShort);
break;
case "class java.lang.Double":
//调用getter方法获取属性值
Double valueDouble = (Double) m.invoke(obj);
row.createCell(columnIndex, CellType.STRING).setCellValue(valueDouble == null ? 0.00 : valueDouble);
break;
case "class java.lang.Boolean":
//调用getter方法获取属性值
Boolean valueBoolean = (Boolean) m.invoke(obj);
row.createCell(columnIndex, CellType.STRING).setCellValue(valueBoolean == null ? false : valueBoolean);
break;
case "class java.util.Date":
//调用getter方法获取属性值
Date valueDate = (Date) m.invoke(obj);
String dateStr = "";
if (valueDate != null) {
dateStr = sdf.format(valueDate);
}
row.createCell(columnIndex, CellType.STRING).setCellValue(dateStr);
break;
default:
break;
}
columnIndex++;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new IllegalArgumentException("没有定义get函数");
}
}
}
public void insertTitle(XSSFSheet sheet, XSSFRow row, XSSFCellStyle titleStyle, String[] titles, int[] widths) {
if (titles.length > 0) {
for (int i = 0; i < titles.length; i++) {
if (widths.length >= i + 1) {
insertCell(sheet, row, titleStyle, i, titles[i], widths[i]);
} else {
insertCell(sheet, row, titleStyle, i, titles[i], CELL_WIDTH_DEFAULT);
}
}
}
}
}
使用
List<Share> shareList = orderService.listOrders();
String filedisplay = "清分查询.xlsx";
filedisplay = URLEncoder.encode(filedisplay, "UTF-8");
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/x-download");
response.addHeader("Content-Disposition", "attachment;filename=" + filedisplay);
GenerateExcelService<Share> excelService = new GenerateExcelService<>();
XSSFSheet sheet = excelService.createSheet("清分查询统计表(1)");
XSSFCellStyle titleStyle = excelService.createTitleStyle();
XSSFRow row = excelService.createTitleRow(sheet);
String[] titles = new String[]{"订单编号", "下单家庭", "支付金额", "扣点", "清分金额", "是否清分", "支付时间", "清分时间"};
int[] widths = new int[]{30, 25, 10, 10, 10, 10, 20, 20};
excelService.insertTitle(sheet, row, titleStyle, titles, widths);
excelService.insertRow(sheet, shareList);
OutputStream out = response.getOutputStream();
excelService.write(out);
out.close();
- 首先根据自己的业务查询出数据集合
- 设置请求头信息,设置Excel名称、contentType、header等信息
- 生成Excel,首先实例化GenerateExcelService,此处将Share可以换成任意需要转换成Excel的对象结构
- 创建sheet页,指定sheet的名称
- 创建表格第一行(表头)的样式(也可以不创建,这样的话表头就与列表数据格式是一样的)
- 获取第一行(表头)对象
- 设置表头显示的字段名称,封装成数组
- 设置表头每个单元格的宽度,如果不设置默认为20。widths数组最好和titles数组长度一致,不一致也没有问题,只不过格式可能不是自己期望的
- 插入表头
- 将自己查询出来的集合转为Excel中的列表
- 输出数据,下载文件
Share的数据结构为:
public class Share implements Serializable {
private String orderNo;
private String familyName;
private Double payAmount;
private Integer channelShare;
private Double shareAmount;
private Integer beShare;
private Date payTime;
private Date shareTime;
// setter... getter 省略
}
在insertRow方法中,本类自动将任意格式的pojo转换为Excel的列表数据,使用反射完成,不需要针对每种不同对象做单独处理