excel经过异步的方式导出

起初头儿让我作一个excel的导出功能,由于以前作过,因此代码比较简单,可是因为数据量庞大,致使导出的时间很长,因此只能改为异步的方式。前端

话很少说,下面贴代码吧。java

@RestController
public class ExportExcelHelper {
    @Value("#{personConfig.defaultOrgTree}")
    private Integer defaultTreeId;
    @Autowired
    private CustomQueryService customQueryService;

    public static String RUNNING_STATUS = "该任务仍在运行中";
    public static String STOP_STATUS = "该任务已经被手动中止";
    public static String FINISH_STATUS = "该任务已经完成";

    private volatile int runFlag = 0; //0无任务 1任务进行中 -1任务被手动中止
    private Result<Progress> exportResult;
    XSSFWorkbook wb;
    String processid;

    /**
     * 用于将查询出的数据写入到excel的数据流中
     *
     * @param queryTable 查询出的数据
     * @param totaltitle 第一行的总标题
     * @return XSSFWorkbook excel数据流
     * @author yuanyu
     * @since 2019.12.02
     */
    public static XSSFWorkbook exportExcel(QueryTable queryTable, String totaltitle) throws Exception {
        // 新建一个Excel文件
        XSSFWorkbook wb = new XSSFWorkbook();
        // Excel中的sheet
        XSSFSheet sheet = wb.createSheet();
        //设置第一行也就是总标题的格式
        XSSFCellStyle firstrowcellStyle = wb.createCellStyle();
        firstrowcellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        Font totalTtileFont = wb.createFont();
        totalTtileFont.setFontName("宋体");
        totalTtileFont.setFontHeightInPoints((short) 18);//设置字体大小
        totalTtileFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗体显示
        firstrowcellStyle.setFont(totalTtileFont);
        // 建立第一行 总标题行
        XSSFRow firstrow = sheet.createRow(0);
        XSSFCell cell_00 = firstrow.createCell(0);
        cell_00.setCellValue(totaltitle);
        cell_00.setCellStyle(firstrowcellStyle);
        //建立第二行 属性标题行
        XSSFRow secondrow = sheet.createRow(1);
        XSSFCellStyle secondrowStyle = wb.createCellStyle();
        secondrowStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        Font subtitleFont = wb.createFont();
        //设置第二行属性标题行的格式
        subtitleFont.setFontName("宋体");
        subtitleFont.setFontHeightInPoints((short) 12);//设置字体大小
        subtitleFont.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);//粗体显示
        secondrowStyle.setFont(subtitleFont);
        // 从参数queryTable中解析出打印的每列标题,放入title中
        List<String> title = Lists.newArrayList();
        for (QueryField p : queryTable.getHeader()) {
            title.add(p.getName());
        }
        XSSFCell secondrowcell;
        // 给第一行赋值,值为咱们从参数中解析出的标题,所以须要咱们在传参的时候须要严格按照约定
        for (int i = 0; i < title.size(); i++) {
            secondrowcell = secondrow.createCell(i);
            secondrowcell.setCellValue(title.get(i));
            secondrowcell.setCellStyle(secondrowStyle);
            sheet.setColumnWidth(i, title.get(i).getBytes("UTF-8").length * 2 * 256);
        }
        //二重循环 将行和列的数据填充进去
        XSSFCellStyle datarowStyle = wb.createCellStyle();
        datarowStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        XSSFRow contextrow;
        XSSFCell datarowcell;
        for (int i = 1; i < queryTable.getRows().size(); i++) {
            contextrow = sheet.createRow(i + 1);
            for (int p = 0; p < queryTable.getHeader().size(); p++) {
                datarowcell = contextrow.createCell(p);
                datarowcell.setCellValue(queryTable.getRows().get(i).getString(queryTable.getHeader().get(p).getKey()));
                datarowcell.setCellStyle(datarowStyle);
            }
        }
        //将第一行标题进行合并
        CellRangeAddress region = new CellRangeAddress(0, 0, 0, title.size() - 1);
        sheet.addMergedRegion(region);
        return wb;
    }



    private class Progress {
        private String start = DateUtils.parseDateToString(new Date());
        private String end;
        private String status = RUNNING_STATUS;

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }

        public String getStart() {
            return start;
        }

        public void setStart(String start) {
            this.start = start;
        }

        public String getEnd() {
            return end;
        }

        public void setEnd(String end) {
            this.end = end;
        }
    }

    private class Export extends Thread {
        CustomQueryVo query;

        Export(CustomQueryVo query) {
            this.query = query;
        }

        @Override
        public void run() {
            exportResult = Result.create(new Progress());
            while (runFlag == 1) {  //说明任务仍在进行中
                query.setCatalogid(defaultTreeId);
                try {
                    wb = excelExport(query).getResult();
                    break;
                } catch (Exception e) {
                    if (e instanceof IErrorCode) {
                        Result.create((IErrorCode) e);
                        break;
                    } else {
                        Result.create(CommonError.internal_error);
                        break;
                    }
                }
            }
            if (exportResult.successful()) {
                exportResult.getResult().setEnd(DateUtils.parseDateToString(new Date()));
                if (runFlag == -1) {
                    exportResult.getResult().setStatus(STOP_STATUS);
                } else {
                    exportResult.getResult().setStatus(FINISH_STATUS);
                }
            }
            runFlag = 0;
        }
    }


    @PostMapping("/exportasyn")
    @ApiOperation("excel导出")
    @Api(value = "excel导出", permit = ApiPermit.LOGIN)
    public Result<Void> excelExportAsyn(@RequestBody CustomQueryVo query) throws Exception {
        query.setCatalogid(defaultTreeId);
        String namespace = query.getModel();
        Integer catalogid = query.getCatalogid();
        Integer nodeid = query.getNodeid();
        if (catalogid == null || nodeid == null) {
            throw new MicroException(CommonError.illegal_args, "未设置查询的组织目录");
        }
        List<QueryField> fields = query.getFields();
        if (fields == null || fields.size() == 0) {
            throw new MicroException(CommonError.illegal_args, "未设置查询的字段");
        }
        if (!CustomQueryHelper.MODEL_USER.equals(query.getModel()) && !CustomQueryHelper.MODEL_ORG.equals(query.getModel())) {
            throw new MicroException(CommonError.illegal_args, "不支持" + namespace + "查询");
        }
        if (runFlag == 0) {
            runFlag = 1;
            Export export = new Export(query);
            export.start();
            processid = UUIDUtils.generate();
            System.out.println("线程id是"+processid);
            return Result.create();
        } else {
            return Result.create(CommonError.illegal_operation, "excel正在导出请勿重复造做");
        }
    }

    @GetMapping("/export/{id}")
    @ApiOperation("获取进度")
    @Api(value = "获取进度", permit = ApiPermit.LOGIN)
    public Result<Progress> progress(@PathVariable("id") String id ) {
        if (!id.equals(processid) || StringUtils.isEmpty(id)){
            return Result.create(CommonError.notfound, "没法找到该任务");
        }
        if (exportResult == null) {
            return Result.create(CommonError.notfound, "暂无进度信息");
        }
        return exportResult;
    }

    @GetMapping("/export/download")
    @ApiOperation("下载excel文件")
    @Api(value = "下载excel文件", permit = ApiPermit.LOGIN)
    public Result<Void> download(HttpServletResponse response) throws Exception {
        if (runFlag == 0) {
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            String excelfilename = sdf.format(date) + ".xlsx";
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + excelfilename);
            response.flushBuffer();
            wb.write(response.getOutputStream());
            wb.close();
            return Result.create();
        } else {
            return Result.create(CommonError.notfound, "没法获取数据");
        }
    }


    @GetMapping("/export/stop")
    @ApiOperation("中止excel导出")
    @Api(value = "中止excel导出", permit = ApiPermit.LOGIN)
    public Result<Void> stop() {
        if (runFlag == 0) {
            return Result.create(CommonError.illegal_operation, "没有任务");
        } else {
            runFlag = -1;
            return Result.create();
        }
    }


    /**
     * 根据条件查询数据而且整理数据
     *
     * @param query 前端传来的查询条件
     * @return XSSFWorkbook excel数据流
     * @author yuanyu
     * @since 2019/12/02
     */
    public Result<XSSFWorkbook> excelExport(CustomQueryVo query) throws Exception {

        String title = query.getTitle();
        QueryTable queryTable = new QueryTable();
        List<Data> dataList = new ArrayList<>();
        query.setNeedtotal(false);
        int pagenumber = 1;
        query.setPagenum(pagenumber);
        query.setPagesize(2000);
        Result<QueryTable> queryTableResult;
        try {
            queryTableResult = customQueryService.query(query);
        } catch (Exception e) {
            if (e instanceof IErrorCode) {
                return Result.create((IErrorCode) e);
            } else {
                return Result.create(CommonError.internal_error);
            }
        }
        int maxheadernum = queryTableResult.getResult().getHeader().size();
        long totalDataNumber = 0;
        Map<Integer, List<QueryField>> headermap = new HashMap<>();
        while (queryTableResult.successful()) {
            totalDataNumber += queryTableResult.getResult().getRows().size();
            if (totalDataNumber > 500000) {
                break;
            }
            System.out.println("查询数据总数" + totalDataNumber);
            dataList.addAll(queryTableResult.getResult().getRows());
            //获取最大的属性数 并将最大数与其对应的属性集合放到map里面
            if (maxheadernum < queryTableResult.getResult().getHeader().size()) {
                maxheadernum = queryTableResult.getResult().getHeader().size();
            }
            headermap.put(maxheadernum, queryTableResult.getResult().getHeader());
            pagenumber++;
            query.setPagenum(pagenumber);
            try {
                queryTableResult = customQueryService.query(query);
            } catch (Exception e) {
                if (e instanceof IErrorCode) {
                    return Result.create((IErrorCode) e);
                } else {
                    return Result.create(CommonError.internal_error);
                }
            }
        }
        queryTable.setRows(dataList);
        queryTable.setHeader(headermap.get(maxheadernum));
        XSSFWorkbook wb = ExportExcelHelper.exportExcel(queryTable, title);

        return Result.create(wb);
    }


}
相关文章
相关标签/搜索