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


}
相關文章
相關標籤/搜索