復制帶表頭的excel sheet頁(poi的HSSFWorkbook)


HSSFWorkbook導出excel時會有65535行的限制,當我們數據量大的時候可以分多個sheet頁的方案來解決,

但是每個sheet頁都需要讀取下載模版文件的表頭,而poi庫對一個excel之間的多sheet頁都讀取模版excel文件不支持,

本文的思路是先生成多個excel文件到內存,然后再將這些excel復制到一個文件的多個sheet頁中。

一 . 首先查出來數據總數,按6萬條一個excel進行生成。

  //生成excel
    @GetMapping("/generate")
    public void generate(String fileName){
        List<Map<String,Object>> dataList=new ArrayList();
        //測試數據
        for (int i=0;i<200000;i++){
            Map m1 = new HashMap();
            m1.put("Zara", "8bbb");
            m1.put("Mahnaz", "31cc");
            m1.put("Ayan", "12");
            m1.put("Daisy", "14111aa");
            dataList.add(m1);
        }
        //單個sheet處理65536條最多
        final int sheetNum= new Double(Math.ceil((float)dataList.size()/60000)).intValue();
      HSSFWorkbook sumWorkBook
=new HSSFWorkbook(); for (int i=0;i<sheetNum;i++){ HSSFWorkbook workbook1=exportExcelByPostFix(dataList.subList(60000*i, (i!=(sheetNum-1)?(60000*(i+1)):dataList.size()))); HSSFSheet sheet1=workbook1.getSheetAt(0); HSSFSheet newsheet =sumWorkBook.createSheet("sheet"+(i+1)); ExcelUtil.copySheet(sumWorkBook,sheet1,newsheet); } //生成文件 exportFile(sumWorkBook,fileName); return Result.succ("copy"); }

 二 . 將每6萬條數據生成一個excel到內存中,即excel的第一個sheet頁

public HSSFWorkbook exportExcelByPostFix(List<Map<String,Object>> dataList){
        //獲取模版表頭
        Resource resourceData=new DefaultResourceLoader().getResource("classpath:doctemp/temp.xls");
        InputStream inputStream=null;
        HSSFWorkbook wb=null;
        try {
            //獲取輸入流
            inputStream= resourceData.getInputStream();
            //創建帶表頭的工作表
            wb=new HSSFWorkbook(inputStream);

            //設置單元格基礎樣式,加邊框,加基礎黑框
            CellStyle hssfCellStyle=wb.createCellStyle();
            hssfCellStyle.setBorderBottom(BorderStyle.THIN);
            hssfCellStyle.setBorderLeft(BorderStyle.THIN);
            hssfCellStyle.setBorderRight(BorderStyle.THIN);
            hssfCellStyle.setBorderTop(BorderStyle.THIN);
            //字居中
            hssfCellStyle.setAlignment(HorizontalAlignment.CENTER);
            //獲取第一個sheet頁
            HSSFSheet sheet=wb.getSheetAt(0);
            //前五行表頭
            int count=5;
            ExcelUtil.exportForData(dataList,sheet,hssfCellStyle,count);
        }
        catch (IOException e){

        }
        finally {

        }
        return wb;
    }

三.生成excel工具類,以及復制sheet頁的方法

public class ExcelUtil {
    /**
     * sheet復制
     */
    public static void copySheet(HSSFWorkbook wb, HSSFSheet fromSheet, HSSFSheet toSheet){

        //合並區域處理
        mergeSheetAllRegion(fromSheet, toSheet);
        // 列寬
        int length = fromSheet.getRow(fromSheet.getFirstRowNum()).getLastCellNum();
        for (int i = 0; i <= length; i++) {
            toSheet.setColumnWidth(i, fromSheet.getColumnWidth(i));
        }

        int flag=0;
        //設置單元格基礎樣式,加邊框,加基礎黑框
        CellStyle hssfCellStyle=wb.createCellStyle();
        hssfCellStyle.setBorderBottom(BorderStyle.THIN);
        hssfCellStyle.setBorderLeft(BorderStyle.THIN);
        hssfCellStyle.setBorderRight(BorderStyle.THIN);
        hssfCellStyle.setBorderTop(BorderStyle.THIN);
        //字居中
        hssfCellStyle.setAlignment(HorizontalAlignment.CENTER);

        for (Iterator rowIt = fromSheet.rowIterator(); rowIt.hasNext(); ) {
            HSSFRow oldRow = (HSSFRow) rowIt.next();
            HSSFRow newRow = toSheet.createRow(oldRow.getRowNum());
            flag++;
            copyRow(wb, oldRow, newRow,flag,hssfCellStyle);
        }
    }
    /**
     * 行復制
     */
    private static void copyRow(HSSFWorkbook wb, HSSFRow oldRow, HSSFRow toRow,int flag,
                                CellStyle hssfCellStyle) {
        toRow.setHeight(oldRow.getHeight());
        for (Iterator cellIt = oldRow.cellIterator(); cellIt.hasNext(); ) {
            HSSFCell tmpCell = (HSSFCell) cellIt.next();
            HSSFCell newCell = toRow.createCell(tmpCell.getColumnIndex());
            copyCell(wb, tmpCell, newCell,flag,hssfCellStyle);
        }
    }
    /**
     * 合並單元格處理
     */
    private static void mergeSheetAllRegion(HSSFSheet fromSheet, HSSFSheet toSheet) {
        int sheetMergeCount = fromSheet.getNumMergedRegions();
        CellRangeAddress cellR = null;
        for (int i = 0; i < sheetMergeCount; i++) {
            cellR = fromSheet.getMergedRegion(i);
            toSheet.addMergedRegion(cellR);
        }
    }
    /**
     * 復制單元格
     */
    private static void copyCell(HSSFWorkbook wb, HSSFCell fromCell, HSSFCell toCell, int flag,
                                 CellStyle hssfCellStyle) {
        //excel表頭有5行
        if(flag<6){
            HSSFCellStyle newstyle = wb.createCellStyle();
            // 復制單元格樣式
            newstyle.cloneStyleFrom(fromCell.getCellStyle());
            // 樣式
            toCell.setCellStyle(newstyle);
        }
        else {
            //其它的單元格用標准格式
            //單元格格式過多會拋出異常,不支持創建太多
            toCell.setCellStyle(hssfCellStyle);
        }

        if (fromCell.getCellComment() != null) {
            toCell.setCellComment(fromCell.getCellComment());
        }
        // 不同數據類型處理
        CellType fromCellType = fromCell.getCellType();
        toCell.setCellType(fromCellType);
        if (fromCellType == CellType.NUMERIC) {
            if (DateUtil.isCellDateFormatted(fromCell)) {
                toCell.setCellValue(fromCell.getDateCellValue());
            } else {
                toCell.setCellValue(fromCell.getNumericCellValue());
            }
        } else if (fromCellType == CellType.STRING) {
            toCell.setCellValue(fromCell.getRichStringCellValue());
        } else if (fromCellType == CellType.BLANK) {
            // nothing21
        } else if (fromCellType == CellType.BOOLEAN) {
            toCell.setCellValue(fromCell.getBooleanCellValue());
        } else if (fromCellType == CellType.ERROR) {
            toCell.setCellErrorValue(fromCell.getErrorCellValue());
        } else if (fromCellType == CellType.FORMULA) {
            toCell.setCellFormula(fromCell.getCellFormula());
        } else {
            // nothing29
        }
    }

    /**
     * 創建單元格
     */
    public static void createCell(Row rows,int column,String value,CellStyle hssfCellStyle){
        Cell cell=rows.createCell(column);
        cell.setCellValue(value);
        cell.setCellStyle(hssfCellStyle);
    }
    /**
     * 根據數據組裝cell數據
     * count=5表示從第6行開始生成單元格,前面5行是表頭
     */
    public static void exportForData(List<Map<String,Object>> list, HSSFSheet hssfSheet,
                                     CellStyle hssfCellStyle,int count){
        if(list!=null&& list.size()!=0){
            for (int i=0;i<list.size();i++){
                //創建行
                Row rows=hssfSheet.createRow(count);
                Map<String,Object> map= list.get(i);
                //是否總計數據
                int j=0;
                Set<String> sets= map.keySet();
                if(sets==null||sets.size()<1){
                    continue;
                }
                for (String key:sets){
                    createCell(rows,j,String.valueOf(map.get(key)),hssfCellStyle);
                    //在for循環中。單元格緯度下調用該函數,會極大降低效率
                    //所以在最后一行數據時,才調用這個函數
                    if(i==list.size()-1){
                        hssfSheet.autoSizeColumn(j);//按內容撐開單元格寬度
                    }
                    j++;
                }
                count++;
            }
        }
    }
}

四,將生成的每個excel的sheet1合並到一個總的excel中,代碼在第一步已經列出。然后生成文文件

private  void exportFile(HSSFWorkbook workbook,String fileName){
        String c="/workspace/java/";
        File file=new File(c);
        if(!file.exists()){
            file.mkdir();
        }

        String exportFilePath=file +"/"+fileName+".xls";
        FileOutputStream outputStream=null;
        try {
            outputStream =new FileOutputStream(exportFilePath);
            workbook.write(outputStream);
            outputStream.flush();
        }
        catch (Exception e){

        }
        finally {

        }
    }

五,結束。需要注意的是window開發環境和部署的linux環境的差別


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM