前端时间做了一个导出excel功能,做个小记录。具体的步骤
- 从数据库查询需要导出的数据,组装成list返回
- 将返回的数据转换 excel 格式的数据
- 将数据输出到浏览器[客户端]
总体上看大致的步骤如上,下面具体讲一下步骤,第一步就不细讲了,就是个简单的查询功能。当我们拿到一个list之后,需要将其转化成对应格式的excel 。我用到的是 HSSFWorkBook 这个类,这里有个需要注意的地方是可能跟excel 班版本有关系,如果出现类似文件被损坏的情况下,可以首先检查一下这个类支不支持该版本的excel ,比如
HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,扩展名是.xls;XSSFWorkbook:是操作Excel2007后的版本,扩展名是.xlsx;SXSSFWorkbook:是操作Excel2007后的版本,扩展名是.xlsx; https://blog.csdn.net/YiQ2018/article/details/81458149
具体代码:
private HSSFWorkbook createWorkOrderExcel(List<ExportWorkOrder> exportWorkOrders, String sheetName) {
HSSFWorkbook wb = new HSSFWorkbook();
Sheet sheet = wb.createSheet(sheetName);
Row row = sheet.createRow(0);
sheet.setDefaultColumnWidth(10);
//样式
CellStyle headCellStyle = getCellStyleHead(wb);
CellStyle dataRowStyle = getCellStyle(wb, null);
// 创建列头
List<String> headers = Lists.newArrayList("", "付款方账号", "收款方户名", "收款方账号", "付款金额", "加急标志", "预约发生日期", "用途", "资金计划项目", "备注");
setCellSheetStyle(sheet, row, headCellStyle, headers);
sheet.createRow(0).createCell(1).setCellValue("注:黄色区域为必填项!");
row = sheet.createRow(1);
row.createCell(0).setCellValue("");
row.createCell(1).setCellValue("付款方账号");
row.getCell(1).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(2).setCellValue("收款方户名");
row.getCell(2).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(3).setCellValue("收款方账号");
row.getCell(3).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(4).setCellValue("付款金额");
row.getCell(4).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(5).setCellValue("加急标志");
row.getCell(5).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(6).setCellValue("预约发生日期");
row.getCell(6).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(7).setCellValue("用途");
row.getCell(7).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(8).setCellValue("资金计划项目");
row.getCell(8).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),null));
row.createCell(9).setCellValue("备注");
row.getCell(9).setCellStyle(setSingleCellStyle(wb, IndexedColors.RED.getIndex(),"remark"));
int rowNum = 2;
if (!CollectionUtils.isEmpty(exportWorkOrders)) {
for (ExportWorkOrder exportWorkOrder : exportWorkOrders) {
row = sheet.createRow(rowNum);
row.createCell(0).setCellValue("");
row.createCell(1).setCellValue(exportWorkOrder.getPayAccountNo());
row.createCell(2).setCellValue(exportWorkOrder.getReceiveAccountName());
row.createCell(3).setCellValue(exportWorkOrder.getReceiveAccountNo());
row.createCell(4).setCellValue(exportWorkOrder.getAmount().toString());
row.createCell(5).setCellValue(exportWorkOrder.getIsSmallEmergency());
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
row.createCell(6).setCellValue(df.format(exportWorkOrder.getReserveTime()));
row.createCell(7).setCellValue(exportWorkOrder.getPurpose());
// 资金计划项目[目前放空]
row.createCell(8).setCellValue("");
row.createCell(9).setCellValue(exportWorkOrder.getRemark());
rowNum++;
}
}
//help GC
exportWorkOrders.clear();
return wb;
}
private static CellStyle getCellStyleHead(HSSFWorkbook wb) {
CellStyle style = wb.createCellStyle();
style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setFillForegroundColor(HSSFColor.WHITE.index);
//设置字体
style.setFont(getFont(wb, HSSFColor.WHITE.index));
return style;
}
private static Font getFont(HSSFWorkbook wb, short colorIndex) {
Font font = wb.createFont();
font.setFontHeightInPoints(DEFAULT_FONT_SIZE);
font.setColor(colorIndex);
return font;
}
private static CellStyle getCellStyle(HSSFWorkbook wb, Short colorIndex) {
if (colorIndex == null) {
colorIndex = IndexedColors.GREEN.getIndex();
}
CellStyle cellStyleWHITE = wb.createCellStyle();
cellStyleWHITE.setFillForegroundColor(colorIndex);
cellStyleWHITE.setBorderBottom(HSSFCellStyle.BORDER_THIN);
cellStyleWHITE.setBorderLeft(HSSFCellStyle.BORDER_THIN);
cellStyleWHITE.setBorderTop(HSSFCellStyle.BORDER_THIN);
cellStyleWHITE.setBorderRight(HSSFCellStyle.BORDER_THIN);
return cellStyleWHITE;
}
得到一个HSSFWorkBook参数的返回值之后,怎么样让浏览器直接识别出是excel而不是其他形式的文件呢?这个就需要对返回值做一下处理。
1 将HSSFWorkBook类型参数的返回值转成字节数组
2 将字节数组返回给客户端的时候,通过设置Response 来实现
public static byte[] workbookConvertorStream(HSSFWorkbook workbook) {
byte[] bookByteAry = null;
try {
//临时缓冲区
ByteArrayOutputStream out = new ByteArrayOutputStream();
//创建临时文件
workbook.write(out);
bookByteAry = out.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return bookByteAry;
}
@RequestMapping(value = "/exportWorkOrderToExcel")
public void exportWorkOrderToExcel(WorkPaymentQueryParam workPaymentQueryParam, HttpServletResponse response) throws Exception {
byte[] fileBytes = exportWorkOrderService.exportWorkOrder(workPaymentQueryParam);
response.setHeader("Content-Type", MediaType.APPLICATION_OCTET_STREAM.toString());
response.addHeader("Content-Disposition", "attachment;filename=publicPay"+".xls");
response.getOutputStream().write(fileBytes);
response.getOutputStream().flush();
response.getOutputStream().close();
}
这里补充一下关于网络的小知识:
为什么我们的正常的请求返回json的时候,不用去手动设置response 这些东西。这些其实spring 帮助我们完成了。具体的可以去看看spring 里面字节数组转json的源码。那像文件这种东西,首先用的比较少,另外,java要用到虚拟机,比起c++ ,对内存的要求更为苛刻,多以正常情况下当有以及体量的系统一般都有文件服务器专门做文件这一块的事情。但是网络传输的本质是一样的。报文格式都是固定的[使用的网络协议一样的话],所以当框架没有帮我们做固定形式处理的时候,我们自己要的做的无非也就是从网络传输的本质东西,转换成我们要的东西即可。