赞
踩
近期项目开发设计一个批处理报表数据的展示,原本是将数据以前台模板Thymylef的形式下展示发送邮件的,近期生产报出严重问题数据量太大超过200m无法发送成功邮件,以致添加新的需求,将数据放到附件excel发送。
注意我们的方法不生成文件,再服务器上生成文件再取再存入附件太过麻烦,而且大多数生产服务器是不允许你有这个权限,所以我们用流的方式存储。POI生成流
public static ByteArrayOutputStream createExcel(List<Map<String, Object>> excelDataList) { try { // 1、创建一个流文件 ByteArrayOutputStream excel = new ByteArrayOutputStream(); //创建一个excel WritableWorkbook workbook = Workbook.createWorkbook(excel); // 2、创建一个Excel的工作表sheet WritableSheet sheet = workbook.createSheet("指标群异常数据", 0); // 3、样式设置 WritableFont bold = new WritableFont(WritableFont.createFont("微软雅黑"), 12, WritableFont.BOLD); WritableFont noBold = new WritableFont(WritableFont.createFont("微软雅黑"), 12, WritableFont.NO_BOLD); WritableCellFormat titleFormate = new WritableCellFormat(bold); // 设置单元格中的内容水平方向居中、垂直方向居中设置边框 titleFormate.setAlignment(jxl.format.Alignment.CENTRE); titleFormate.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE); titleFormate.setBorder(Border.ALL, BorderLineStyle.THIN); // 设置正文内容样式,单元格样式控制对象 WritableCellFormat textFormat = new WritableCellFormat(noBold); // 单元格中的内容水平方向居中、垂直方向居中、设置边框 textFormat.setAlignment(jxl.format.Alignment.CENTRE); textFormat.setVerticalAlignment(jxl.format.VerticalAlignment.CENTRE); textFormat.setBorder(Border.ALL,BorderLineStyle.THIN); // 3.4、窗口冻结第一行 sheet.getSettings().setVerticalFreeze(1); //sheet.getSettings().setHorizontalFreeze(2);//冻结 2列两行 // 3.5、设置行高--第一行标题行 sheet.setRowView(0,500); // 3.6、设置列宽 sheet.setColumnView(0,15); sheet.setColumnView(1,25); sheet.setColumnView(2,30); sheet.setColumnView(3,15); sheet.setColumnView(4,15); sheet.setColumnView(5,20); // 4、构造表头 ExcelUtil.setSheetHeader(sheet, titleFormate); // 5、填充数据 ExcelUtil.setSheetData(sheet, textFormat, 1, excelDataList); workbook.write(); workbook.close(); return excel; }catch (Exception e){ e.printStackTrace(); throw new RuntimeException("创建邮件失败"); } }
因为生成的临时文件我不需要放到本地,所以这里直接用了一个字节流来存储excel信息
private static void setSheetHeader(WritableSheet sheet, WritableCellFormat titleFormate) throws WriteException {
// 构造表头
//mergeCells(0, 0, 0, 0) 表示不合并; sheet.mergeCells(1,0,2,0)表示第2列和第3列合并成一列
//Label label_20 = new Label(2, 0, "描述", cellFormat); 前面的数字表示第几列,第几行
//4.1、创建表数据
List<String> titleList = Arrays.asList("测试1", "测试2", "测试3", "测试4", "测试5", "测试6");
for (int i = 0; i < titleList.size(); i++) {
Label label_00 = new Label(i,0, titleList.get(i), titleFormate);
sheet.addCell(label_00);
}
}
表头以及信息方便展示,我就是固定死了,也可以用数据库中的数据
private static void setSheetData(WritableSheet sheet, WritableCellFormat textFormat, int startRow, List<Map<String,Object>> excelDataList) throws WriteException { for (int i = 0; i < excelDataList.size(); i++, startRow++) { Map excelData = excelDataList.get(i); Label label_02 = new Label(0, startRow, (String) excelData.get("INDEX_CODE"), textFormat); sheet.addCell(label_02); Label label_12 = new Label(1, startRow, (String) excelData.get("INDEX_NAME"), textFormat); sheet.addCell(label_12); Label label_22 = new Label(2, startRow, (String) excelData.get("IND_CONDITION"), textFormat); sheet.addCell(label_22); Label label_32 = new Label(3, startRow, (String) excelData.get("STATISTICAL_FREQUENCY"), textFormat); sheet.addCell(label_32); Label label_42 = new Label(4, startRow, (String) excelData.get("exceptionDate"), textFormat); sheet.addCell(label_42); Label label_52 = new Label(5, startRow, (String) excelData.get("msg"), textFormat); sheet.addCell(label_52); } }
excelDataList就是要插入的行数据了,通过循环将数据插入到这些列中。当然列信息也是可以写成动态的,不过我只需要几列,也是固定死了。
上面代码执行完成之后,就得到了一个ByteArrayOutputStream类的excel流文件
// 将流文件存到字节数组缓冲区 (以上的所有代码可放在一个方法体中 设置格式设置字体添加信息转换字节流 然后将ByteArrayInputStream作为return的对象返回,因为mail附件的格式是要求是InputStream格式的)
ByteArrayInputStream excelAttachment = new ByteArrayInputStream(excel.toByteArray());
然后将流文件放到字节数组缓冲区中,以待使用。接下来就是创建邮件发送类
try { // 创建邮件发送类 JavaMailSenderImpl javaMailSender = setMailSender(); // 创建邮件信息类 MimeMessage msg = javaMailSender.createMimeMessage(); // 创建MimeMessageHelper对象,MimeMessage的辅助类 MimeMessageHelper message = new MimeMessageHelper(msg, true); message.setFrom(javaMailSender.getUsername()); String[] emailArray = emailList.toArray(new String[emailList.size()]); // message.setTo(emailArray); // 要发送的账号 message.setTo("***********@qq.com"); // 标题 message.setSubject(INDEX_CODE + "——" + INDEX_NAME + "——" + STATISTICAL_FREQUENCY + "——指标异常"); // 主体 message.setText(generateEmailMsg(item)); ByteArrayDataSource file = new ByteArrayDataSource(excelAttachment, "application/vnd.ms-excel;charset=UTF-8"); // 附件 关键部分 message.addAttachment(MimeUtility.encodeWord("指标异常数据信息.xls","utf-8","B"),file); javaMailSender.send(msg); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("邮件发送失败!" + e); }
至于发送邮件以及类的方法我就不一一展示了,说一下注意的坑点。我之前者应部署后会报一个错误JavaMailSender with Exception writing Multipart。
ByteArrayDataSource file = new ByteArrayDataSource(excelAttachment, "application/vnd.ms-excel;charset=UTF-8");
// 附件 关键部分
message.addAttachment(MimeUtility.encodeWord("指标异常数据信息.xls","utf-8","B"),file);
message.setText(generateEmailMsg(item));
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。