当前位置:   article > 正文

Java&POI以流的形式的形式生成Excel文件并作为邮件附件发送(不生成实际Excel文件)_java生成excel文件流

java生成excel文件流

近期项目开发设计一个批处理报表数据的展示,原本是将数据以前台模板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("创建邮件失败");
        }
    }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

因为生成的临时文件我不需要放到本地,所以这里直接用了一个字节流来存储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);
        }

    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

表头以及信息方便展示,我就是固定死了,也可以用数据库中的数据

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);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

excelDataList就是要插入的行数据了,通过循环将数据插入到这些列中。当然列信息也是可以写成动态的,不过我只需要几列,也是固定死了。

上面代码执行完成之后,就得到了一个ByteArrayOutputStream类的excel流文件

// 将流文件存到字节数组缓冲区 (以上的所有代码可放在一个方法体中 设置格式设置字体添加信息转换字节流 然后将ByteArrayInputStream作为return的对象返回,因为mail附件的格式是要求是InputStream格式的)
        ByteArrayInputStream excelAttachment = new ByteArrayInputStream(excel.toByteArray());
        
  • 1
  • 2
  • 3

然后将流文件放到字节数组缓冲区中,以待使用。接下来就是创建邮件发送类

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

至于发送邮件以及类的方法我就不一一展示了,说一下注意的坑点。我之前者应部署后会报一个错误JavaMailSender with Exception writing Multipart。

  • 使用存在方法检查文件是否在FileSystemResource中退出
  • 请发布完整的异常堆栈跟踪。
    我去搜了解决办法是因为它默认判断我的主体是空的,所以我把 message.setText 放在添加附件代码的下面就行了按循序执行就可以正常发送了。很神奇

           
            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));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/591758
推荐阅读
相关标签
  

闽ICP备14008679号