Java使用poi导出excel文件包含多个sheet

本文介绍了一种将网页上的两个报表数据导出至单个Excel文件并分为两个Sheet的方法,涉及前端JS代码和后端Java代码实现,包括用户交互、数据处理及Excel文件生成等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近一次小需求要求对一个页面的两个报表通过点击一个导出按钮导出到一个excel中,当然,是要求在一个excel中建立多个sheet来保存两个报表的数据,否则全部放置在一个报表中就没有意义了,记录一下,以免下次使用CV大法的使用

讲讲详细的过程

1.页面

        

如上图,点击导出明细按钮,要将查询条件查询出的两个表中的数据导出到一个excel,分成两个sheet

2.js代码

按钮的点击事件代码如下:

    //导出明细按钮
    $("#exportDetailButton").on('click',function() {
        $.messager.confirm('导出', '确定导出明细数据?', function(r){
            if (r){
                downloadFile('/reconciliacionCount/exportDetail?' + $.param(exprotParam));
            }
        });
    });

exprotParam是一个js对象,就是查询条件,通过JQuery的param方法把它变成请求参数,downloadFile()方法的代码如下:

//js文件下载
window.downloadFile = function (sUrl) {
    var isChrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
    var isSafari = navigator.userAgent.toLowerCase().indexOf('safari') > -1;
    $.ajax({
        type: 'get',
        dataType : 'json',  
        url: '/user/isSessionInvalid',
        success: function (data) {
            if(data.code ==="1"){
              //iOS devices do not support downloading. We have to inform user about this.
                if (/(iP)/g.test(navigator.userAgent)) {
                    return false;
                }

                //If in Chrome or Safari - download via virtual link click
                if (isChrome || isSafari) {
                    //Creating new link node.
                    var link = document.createElement('a');
                    link.href = sUrl;
                    //Dispatching click event.
                    if (document.createEvent) {
                        var e = document.createEvent('MouseEvents');
                        e.initEvent('click', true, true);
                        link.dispatchEvent(e);
                        return true;
                    }
                }
                
                window.open(sUrl, '_self');
                return true;
            }
            return false;
        },
        error: function(){
            return false;
        }
    });
    
}

这里的ajax请求/user/isSessionInvalid是在判断用户登录是否失效,如果失效,不让其做任何操作,由于我们的架构用到Shiro,大家在使用时,看情况处理,如果不需要做用户登录验证,可以直接用success方法的代码,这里我暂且贴出这个请求的方法

    @RequestMapping(value = "/isSessionInvalid")
    public @ResponseBody Object isSessionInvalid() {
        User shiroUser = (User) SecurityUtils.getSubject().getPrincipal();
        return shiroUser != null ? DataPacket.jsonResult(Constants.SUCCESS_MSG)
                : DataPacket.errorJsonResult(Constants.FAIL_MSG);
    }

2.后台java代码

    /**
     * 
     * @param reconciliationRecord 查询条件
     * @param areaId 区域id
     * @param flag
     * @param response
     * @return
     */
    @RequiresPermissions(AuthConstants.RECONCILIATION_COUNT_EXPORT)
    @RequestMapping(value = "/exportDetail", method = RequestMethod.GET, name = "导出对账统计明细记录")
    @ResponseBody
    public Object exportDetailData(ReconciliationRecord reconciliationRecord, Integer areaId, String flag, HttpServletResponse response) {
        LOG.info("开始导出对账统计数据");
        // 将文件存到浏览器设置的下载位置
        try (OutputStream out = response.getOutputStream()) {
            SXSSFWorkbook wb = reconciliationRecordService.exportDetail(reconciliationRecord);
            wb.setCompressTempFiles(true);
            response.setContentType("application/x-download;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("对账统计明细报表.xlsx", "UTF-8"));
            wb.write(out);// 将数据写出去
        } catch (RuntimeException ge) {
            LOG.error("对账统计明细导出失败{}", ge);
            return DataPacket.errorJsonResult("导出失败");
        } catch (IOException e) {
            LOG.error("对账统计明细导出失败{}", e);
            return DataPacket.errorJsonResult("导出失败");
        } catch (Exception gge) {
            LOG.error("对账统计明细导出失败 {}", gge);
            return DataPacket.errorJsonResult("导出失败");
        }
        return DataPacket.jsonResult("导出成功");
    }

除了exportDetail是根据大家自身业务处理,其他都是死代码,直接cv,主要看下这个方法的实现

    @Override
    public SXSSFWorkbook exportDetail(ReconciliationRecord reconciliationRecord) {
        SXSSFWorkbook wb = new SXSSFWorkbook(INT_1000);
        // 生成医院账单明细sheet
        generateHisBillSheet(wb, reconciliationRecord, "医院账单明细报表");
        // 生成渠道账单明细sheet
        generateChannelBillSheet(wb, reconciliationRecord, "渠道交易明细报表");
        return wb;
    }

由于两个生成sheet的方法基本一样,我这里只列举一个方法的实现

 private void generateHisBillSheet(SXSSFWorkbook wb, ReconciliationRecord reconciliationRecord, String sheetName) {
        List<HisBillRecord> hisBillRecordList = hisBillRecordMapper.selectAllByCondition(reconciliationRecord);
        String[][] dataList = getHisBillData(hisBillRecordList);
        int[] columnWidth = { COLUMN_WITH_30, COLUMN_WITH_30, COLUMN_WITH_22, 
                COLUMN_WITH_22, COLUMN_WITH_22,COLUMN_WITH_22 };
        String[] columnName = { "医院交易时间", "医院支付金额", "交易流水号", 
                "医院业务类型", "交易类型", "收费员" };
        SXSSFSheet sheet = wb.createSheet(sheetName);
        for (int i = 0; i < HIS_COLUMN_NUMBER; i++) {
            sheet.setColumnWidth(i, columnWidth[i] * COLUMN_PX);
        }

        // 创建第0行 也就是标题
        SXSSFRow row1 = sheet.createRow(ZERO_ROW);
        CellStyle headerStyle = setSheetSomeStyle(wb, row1);
        // 创建标题第一列
        SXSSFCell cell1 = row1.createCell(ZERO_CELL);
        // 合并列标题
        sheet.addMergedRegion(new CellRangeAddress(ZERO_ROW, ZERO_ROW, ZERO_CELL, HIS_COLUMN_NUMBER - 1));
        // 设置值标题
        cell1.setCellValue(sheetName);
        cell1.setCellStyle(headerStyle);

        // 创建第1行 也就是表头
        SXSSFRow row = sheet.createRow(ONE_ROW);
        // 设置表头高度
        row.setHeightInPoints(TABLE_HIGHT);

        // 创建表头的列
        for (int i = 0; i < HIS_COLUMN_NUMBER; i++) {
            SXSSFCell cell = row.createCell(i);
            cell.setCellValue(columnName[i]);
            cell.setCellStyle(headerStyle);
        }

        // 创建单元格,并设置值
        for (int i = 0; i < hisBillRecordList.size(); i++) {
            row = sheet.createRow(i + TWO_ROW);
            SXSSFCell datacell8 = null;
            for (int j = 0; j < HIS_COLUMN_NUMBER; j++) {
                datacell8 = row.createCell(j);
                datacell8.setCellValue(dataList[i][j]);
                datacell8.setCellStyle(headerStyle);
            }
        }
    }
private String[][] getHisBillData(List<HisBillRecord> hisBillRecordList) {
        int colume = hisBillRecordList.size();
        String[][] hisBillRecordListArr = new String[colume][LENGTH_6];
        for (int i = 0; i < hisBillRecordList.size(); i++) {
            hisBillRecordListArr[i][0] = hisBillRecordList.get(i).getTradeDate();
            if(hisBillRecordList.get(i).getFee() != null) {
                BigDecimal free = new BigDecimal(hisBillRecordList.get(i).getFee());
                free = free.divide(new BigDecimal(INT_100), 2, RoundingMode.HALF_UP);
                hisBillRecordListArr[i][1] = free.toString();
            }else {
                hisBillRecordListArr[i][1] = "0.00";
            }
            hisBillRecordListArr[i][2] = hisBillRecordList.get(i).getTradeNo();
            hisBillRecordListArr[i][3] = hisBillRecordList.get(i).getBusiName();
            if("1".equals(hisBillRecordList.get(i).getIncomeType())) {
                hisBillRecordListArr[i][4] = "收入";
            }else {
                hisBillRecordListArr[i][4] = "支出";
            }
            hisBillRecordListArr[i][5] = hisBillRecordList.get(i).getTollCollector();
        }
        return hisBillRecordListArr;
    }

上面的这个方法主要是对数据做处理,先将数据集合转化成二维数组,再把数据库的数据做处理,比如某个字段1代表支出,2代表收入,金额我们是以分做单位存,转化成元这种处理操作

 

以上就是详细的操作过程,如果大家有好的方式,也欢迎分享

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bigbear776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值