百万数据Excel导出


    /**
     * 订单的excel导出
     *
     * @param request
     * @param iccid
     * @param fullName
     *            商户名称
     * @param orderStatus
     *            订单状态
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/orderExcel")
    public void orderExcel(HttpServletRequest request, HttpServletResponse response,
            @RequestParam(value = "accessNumber", required = false) String accessNumber,
            @RequestParam(value = "fullName", required = false) String fullName,
            @RequestParam(value = "orderStatus", required = false) Integer orderStatus,
            @RequestParam(value = "access_token", required = true) String accessToken) throws Exception {
        AdminUserDTO usrDto = (AdminUserDTO) request.getAttribute(Constants.SESSION_NAME_USER);
        Map<String,Object> params = new HashMap<String,Object>();
        params.put("agentId", usrDto.getUserInfo().getAgentId());
        params.put("accessNumber", accessNumber);
        params.put("fullName", fullName);
        params.put("orderStatus", orderStatus);
        rechargeOrderService.orderExcel(params, response);
    }

@Override
    public void orderExcel(Map<String, Object> params, HttpServletResponse response) {

        try {
            String[] export = {"订单号","接入号","订购套餐","充值","分润","所属商户","支付状态","订购时间"};//标题元素
            String fileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
            StringBuffer sbsql = new StringBuffer("select fpo.order_id as orderId,ic.access_number as accessNumber,fp.name,round(fpo.order_money/100,2) as orderMoney,\r\n" +
                    " round(po.profit_money/100,2) as profitMoney,cu.full_name as fullName,fpo.order_status as orderStatus,date_format(fpo.modify_date,'%Y-%m-%d') as modifyDate\r\n" +
                    " from agency_flow_package_order fpo\r\n" +
                    " LEFT JOIN agency_customer cu ON cu.customer_id = fpo.customer_id \r\n" +
                    " LEFT JOIN agency_flow_package_order_detail fpod ON fpod.order_id = fpo.order_id\r\n" +
                    " LEFT JOIN agency_flow_package fp ON fp.id = fpod.package_id\r\n" +
                    " LEFT JOIN agency_iot_cards ic ON ic.iccid = fpod.iccid\r\n" +
                    " LEFT JOIN agency_profit_order po ON po.order_id = fpod.order_id\r\n" +
                    " where fpo.is_del != 1\r\n" +
                    " and cu.status != 1\r\n" +
                    " and fp.is_del != 1" +
                    " and cu.agent_id in(select agent_id from agency_info where agent_id = " + params.get("agentId").toString() + " or parent_agent_id = " + params.get("agentId").toString() + ")\r\n");
            
            List<String> parList = new ArrayList<String>();
            if(null != params.get("accessNumber")&&StringUtils.isNotBlank(params.get("accessNumber").toString())) {
                parList.add(params.get("accessNumber").toString());
                sbsql.append(" and ic.access_number=?");
            }
            if(null != params.get("fullName")&&StringUtils.isNotBlank(params.get("fullName").toString())) {
                parList.add("%"+params.get("fullName").toString()+"%");
                sbsql.append(" and cu.full_name like?");
            }
            if(null != params.get("orderStatus")&&StringUtils.isNotBlank(params.get("orderStatus").toString())) {
                parList.add(params.get("orderStatus").toString());
                sbsql.append(" and fpo.order_status = ?");
            }
            sbsql.append(" ORDER BY fpo.modify_date DESC");
            ExcelUtils2.excelExport(response, fileName, export,sbsql.toString(),parList,"yyyy-MM-dd");// 调用封装好的导出方法,具体方法在下面
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 百万级数据导出
     *
     * @param response
     * @param fileName,生成的文件名称
     * @param excelHeader,存放"标题#字段"这样格式的数组
     * @param sql执行的sql,如:"SELECT
     *            * FROM users WHERE username=? AND PASSWORD = ?"
     * @param params,sql里面的参数
     */
    public static void excelExport(HttpServletResponse response, String fileName, String[] excelHeader, String sql,
            List params,String rule) throws InstantiationException, IllegalAccessException, ClassNotFoundException, IOException,
            InterruptedException {
        // 设置请求
        response.setContentType("application/application/vnd.ms-excel");
        response.setHeader("Content-disposition",
                "attachment;filename=" + URLEncoder.encode(fileName + ".xlsx", "UTF-8"));
        // 内存中只创建100个对象,写临时文件,当超过100条,就将内存中不用的对象释放。
        @SuppressWarnings("resource")
        SXSSFWorkbook wb = new SXSSFWorkbook(1000); // 关键语句
        // 设置标题样式
        CellStyle titleStyle = wb.createCellStyle();
        // 设置单元格边框样式
        titleStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);// 上边框 细边线
        titleStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);// 下边框 细边线
        titleStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);// 左边框 细边线
        titleStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);// 右边框 细边线
        // 设置单元格对齐方式
        titleStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水平居中
        titleStyle.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); // 垂直居中
        // 设置字体样式
        Font titleFont = wb.createFont();
        titleFont.setFontHeightInPoints((short) 15); // 字体高度
        titleFont.setFontName("黑体"); // 字体样式
        titleStyle.setFont(titleFont);
        Sheet sheet = null; // 工作表对象
        Row nRow = null; // 行对象
        Cell nCell = null; // 列对象
        long startTime = 0;// 开始操作数据时间
        // 使用jdbc链接数据库
        Class.forName(PropertiesUtil.getStringValue("driverClassName_admin")).newInstance();
        String url = PropertiesUtil.getStringValue("url_admin");
        String user = PropertiesUtil.getStringValue("username_admin");
        String passward = PropertiesUtil.getStringValue("password_admin");
        try {
            Class.forName(PropertiesUtil.getStringValue("driverClassName_admin"));
        } catch (ClassNotFoundException e1) {
            e1.printStackTrace();
        }
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            // 创建数据库连接
            con = DriverManager.getConnection(url, user, passward);
            // ResultSet的TYPE_FORWARD_ONLY属性只允许结果集的游标向下移动,ResultSet.CONCUR_READ_ONLY属性类似只读
            // 属性,不可仪更改,不能用结果集更新数据
            ps = (PreparedStatement) con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            System.out.println("excel sql:  "+sql);
            ps.setFetchSize(Integer.MIN_VALUE);// 每次抓取数据的条数

            ps.setFetchDirection(ResultSet.FETCH_REVERSE);
            if (params == null) {
                params = new ArrayList<>();
            }
            for (int i = 0; i < params.size(); i++) {
                if (params.get(i) == null) {
                    continue;
                }
                if (params.get(i) instanceof Integer) {
                    ps.setInt(i + 1, (int) params.get(i));
                } else if (params.get(i) instanceof Double) {
                    ps.setDouble(i + 1, (double) params.get(i));
                } else if (params.get(i) instanceof Float) {
                    ps.setFloat(i + 1, (float) params.get(i));
                } else if (params.get(i) instanceof Long) {
                    ps.setLong(i + 1, (long) params.get(i));
                } else if (params.get(i) instanceof Date) {
                    ps.setDate(i + 1, (java.sql.Date) params.get(i));
                } else if (params.get(i) instanceof BigDecimal) {
                    ps.setBigDecimal(i + 1, (BigDecimal) params.get(i));
                } else if (params.get(i) instanceof Boolean) {
                    ps.setBoolean(i + 1, (boolean) params.get(i));
                } else if (params.get(i) instanceof Timestamp) {
                    ps.setTimestamp(i + 1, (Timestamp) params.get(i));
                } else {
                    ps.setString(i + 1, params.get(i).toString());
                }
            }
            rs = ps.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();
            startTime = System.currentTimeMillis(); // 开始时间
            System.out.println("strat execute time: " + startTime);

            int rowNo = 0; // 总行号
            int pageRowNo = 0; // 页行号
            boolean haveData = false;//默认执行sql没有返回数据
            while (rs.next()) {
                haveData = true;
                // 打印300000条后切换到下个工作表
                if (rowNo %300000  == 0) {//300000
                    System.out.println("Current Sheet:" + rowNo / 300000);
                    sheet = wb.createSheet("第" + (rowNo / 300000 + 1) + "个工作簿");// 建立新的sheet对象
                    sheet = wb.getSheetAt(rowNo / 300000); // 动态指定当前的工作表
                    pageRowNo = 1; // 每当新建了工作表就将当前工作表的行号重置为0
                    // 为标题行赋值
                    Row row = sheet.createRow(0);// 行数从0开始
                    for (int i = 0; i < excelHeader.length; i++) {
                        Cell titleCell = row.createCell(i);
                        titleCell.setCellValue(excelHeader[i]);
                        titleCell.setCellStyle(titleStyle);
                    }
                }
                rowNo++;
                nRow = sheet.createRow(pageRowNo++); // 新建行对象
                for (int j = 0; j < rsmd.getColumnCount(); j++) {
                    nCell = nRow.createCell(j);
                    if(rs.getObject(j+1) instanceof Date) {
                        Date date = (Date) rs.getObject(j + 1);
                        String dateStr = new SimpleDateFormat(rule).format(date);
                        nCell.setCellValue(dateStr);
                    }else {
                        if(j == 6) {
                            if(rs.getString(j+1)!=null) {
                                nCell.setCellValue(Integer.parseInt(rs.getString(j+1)) == 1?"已支付":"未支付");
                            }else {
                                nCell.setCellValue("-");
                            }
                            continue;
                        }
                        nCell.setCellValue(rs.getString(j+1));
                    }
                }

                if (rowNo % 10000 == 0) {
                    System.out.println("row no: " + rowNo);
                }
                Thread.sleep(1); // 休息一下,防止对CPU占用
            }
            if(!haveData) {//没有数据的时候
                sheet = wb.createSheet("第1个工作簿");// 建立新的sheet对象
                sheet = wb.getSheetAt(rowNo / 300000); // 动态指定当前的工作表
                // 为标题行赋值
                Row row = sheet.createRow(0);// 行数从0开始
                for (int i = 0; i < excelHeader.length; i++) {
                    Cell titleCell = row.createCell(i);
                    titleCell.setCellValue(excelHeader[i]);
                    titleCell.setCellStyle(titleStyle);
                }
            
            }
            long finishedTime = System.currentTimeMillis(); // 处理完成时间
            System.out.println("finished execute  time: " + (finishedTime - startTime) / 1000 + "m");
            OutputStream outputStream = response.getOutputStream();// 打开流
            wb.write(outputStream);
            outputStream.flush(); // 刷新缓冲区
            outputStream.close();
            // 销毁临时文件
            wb.dispose();

            long stopTime = System.currentTimeMillis(); // 写文件时间
            System.out.println("write xlsx file time: " + (stopTime - startTime) / 1000 + "m");
        } catch (Exception e) {
            e.printStackTrace();
            throw new BizException("E1000005", MessageUtil.getMessage("E1000005"));
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
    }

注意:一定要用原生的jdbc,原生的jdbc查出来的是游标不会出现内存溢出

猜你喜欢

转载自blog.csdn.net/qq_31896193/article/details/83504512