1. 程式人生 > 實用技巧 >匯出excel美化合並單元格

匯出excel美化合並單元格

有時感覺客戶給的匯出模板比較複雜既有合併單元格還有不規則的分類配置,其實都是為了匯出excel後可以很直觀的瀏覽資料,得到反饋;從這點出發,開發出來的功能客戶用起來才會覺得好用。為了方便以後Ctrl C and Ctrl V,在這裡和童鞋們分享兩種相似的合併單元格的方法;

一、固定列名+變動有規律的列名

    /**
     * 匯出excel到瀏覽器,美化合並單元格
     * @param titles 表頭,合併單元格時取左上角第一個的值
     * [序號, 生產系, 部品番號, 上月滯後, , 12月1日-白班A, , , 12月1日-夜班B, , , 12月2日-白班A, , , 12月2日-夜班B, , , 12月3日-白班A, , , 12月3日-夜班B, , , 12月4日-白班A, , , 12月4日-夜班B, , , 12月5日-白班A, , , 12月5日-夜班B, , , 12月6日-白班A, , , 12月6日-夜班B, , , 12月7日-白班A, , , 12月7日-夜班B, , , 12月8日-白班A, , , 12月8日-夜班B, , , 12月9日-白班A, , , 12月9日-夜班B, , , 12月10日-白班A, , , 12月10日-夜班B, , , 12月11日-白班A, , , 12月11日-夜班B, , , 12月12日-白班A, , , 12月12日-夜班B, , , 12月13日-白班A, , , 12月13日-夜班B, , , 12月14日-白班A, , , 12月14日-夜班B, , , 12月15日-白班A, , , 12月15日-夜班B, , , 12月16日-白班A, , , 12月16日-夜班B, , , 12月17日-白班A, , , 12月17日-夜班B, , , 12月18日-白班A, , , 12月18日-夜班B, , , 12月19日-白班A, , , 12月19日-夜班B, , , 12月20日-白班A, , , 12月20日-夜班B, , , 12月21日-白班A, , , 12月21日-夜班B, , , 12月22日-白班A, , , 12月22日-夜班B, , , 12月23日-白班A, , , 12月23日-夜班B, , , 12月24日-白班A, , , 12月24日-夜班B, , , 12月25日-白班A, , , 12月25日-夜班B, , , 12月26日-白班A, , , 12月26日-夜班B, , , 12月27日-白班A, , , 12月27日-夜班B, , , 12月28日-白班A, , , 12月28日-夜班B, , , 12月29日-白班A, , , 12月29日-夜班B, , , 12月30日-白班A, , , 12月30日-夜班B, , , 12月31日-白班A, , , 12月31日-夜班B, ]
     * [, , , , 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異, 計劃, 實績, 差異]
     * @param datas 列表資料
     * @param response 響應體
     * @param sheetName 匯出表名
     
*/ private void getMergeExcel(List<String[]> titles, List<String[]> datas, HttpServletResponse response, String sheetName){ ByteArrayOutputStream bout = null; SXSSFWorkbook xssfWorkbook; try{ Row row = null; Cell cell = null; CellRangeAddress cellRangeAddress
= null; xssfWorkbook = new SXSSFWorkbook(); Sheet sheet = xssfWorkbook.createSheet(sheetName); // 水平居中 XSSFCellStyle alignStyle = (XSSFCellStyle) xssfWorkbook.createCellStyle(); alignStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
// 垂直居中 XSSFCellStyle verticalStyle = (XSSFCellStyle) xssfWorkbook.createCellStyle(); verticalStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); // 水平垂直居中 XSSFCellStyle horizontalVerticalStyle = (XSSFCellStyle) xssfWorkbook.createCellStyle(); horizontalVerticalStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER); horizontalVerticalStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER); // 拼接表頭 for (int i = 0; i < titles.size(); i++) { row = sheet.createRow(i); if(i == 0){ // 合併表頭個數 + 固定列名個數 int length = (titles.get(i).length - 4) / 3 + 4; // 第一行,序號、生產系、部品番號、上月滯後、日期 for (int j = 0; j < length; j ++) { if(j < 4){ // 0~3,固定表頭的索引 cellRangeAddress = new CellRangeAddress(0, 1, j, j); sheet.addMergedRegion(cellRangeAddress); cell = row.createCell(j); cell.setCellStyle(horizontalVerticalStyle); cell.setCellValue(titles.get(i)[j]); continue; } // 需要合併的單元格 // 指定合併的範圍,開始行,結束行,開始列,結束列 cellRangeAddress = new CellRangeAddress(0, 0, j + 2 * (j - 4), j + 2 * (j - 3)); // 將合併單元格加入表中 sheet.addMergedRegion(cellRangeAddress); cell = row.createCell(j + 2 * (j - 4)); // 指定合併單元格內容居中樣式 cell.setCellStyle(alignStyle); // cell.setCellValue("5月5日-白班A"); // 為合併單元格賦值 cell.setCellValue(titles.get(i)[3 * (j - 2) - 1]); } }else{ int length = titles.get(i).length; // 第二行、計劃、實績、差異 for (int j = 0; j < length; j ++) { if(j < 4){ // 跳過固定表頭的索引 continue; } // 4~end,非固定表頭的索引 cell = row.createCell(j); cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue(titles.get(i)[j]); } } } for (int i = 0; i < datas.size(); i++) { row = sheet.createRow(i+2); String[] rows = datas.get(i); for (int j = 0; j < rows.length; j++) { cell = row.createCell(j); cell.setCellType(Cell.CELL_TYPE_STRING); cell.setCellValue(rows[j]); } } String title = new String(sheetName.getBytes("utf-8"), "ISO-8859-1"); response.setHeader("content-disposition", "attachment;filename=" + title + ".xlsx"); response.flushBuffer(); xssfWorkbook.write(response.getOutputStream()); }catch(Exception e){ e.printStackTrace(); }finally{ if(bout!=null){ try { bout.close(); } catch (IOException e) { e.printStackTrace(); } } } }

匯出excel格式參考:

二、固定列名+變動無規律的列名

    /**
     * 匯出excel到瀏覽器,美化合並單元格
     * @param titles 表頭,合併單元格時取左上角第一個的值 
     * [序號, 日期, 班次, 生產系, 部品, 正常停止, 正常停止, 正常停止, 正常停止, 正常停止, 正常停止, 正常停止, 品質, 品質, 品質, 品質, 技改, 技改, 技改, 技改, 組裝, 組裝, 組裝, 組裝, 保全, 保全, 保全, 保全, 保全, 保全, 保全, 保全, 保全, 保全, 保全, 物流, 物流, 物流, 物流, 物流, 物流, 衝壓, 衝壓, 其他, 其他, 其他, 其他, 其他, 其他]
     * [, , , , , 剝離、壓力測試, 電極研磨, 電極更換, 焊絲更換, 貼標籤, 段取, 點檢, 品質異常判定, 單品、KD來料不良, 焊點不良.co2焊道不良.壓力值不足, 品質不良調查/改善, 夾具精度不良.調整, 夾具氣路異常(氣缸.氣管.接頭等氣路元件損壞), 夾具機械異常(定位銷.導向塊等易耗類故障), 塗膠機/遮斷器/刻印機,機械異常, 平衡器異常及機械類故障, 電極.定位芯.研磨刀更換異常更換, 握杆、電極杆、電極異常更換, 水、氣管破損更換, 夾具線路.感應器故障.磁性開關損壞, 懸掛式點焊機.固定焊故障, co2焊機故障.DCE焊機故障, 機器人.自動打點機故障, 螺母(栓)輸送機故障, 螺母(栓)機焊接異常, 研磨機電路故障, 塗膠機/遮斷器異常, 刻印機線路故障.光柵異常, co2機器人研磨.噴油故障, 刻印機電路.程式故障.電磁閥損壞, 缺輔材, 缺單品, 缺KD, 單/成品待叉車, 缺膠箱.容器不良, 納入異常, 缺單品, 產品不良, 生理現象, 作業指導, 停電, 停水, 停氣, 其他]
     * @param titleMap 可變動的列名及其列的個數
     * {正常停止=[剝離、壓力測試, 電極研磨, 電極更換, 焊絲更換, 貼標籤, 段取, 點檢], 品質=[品質異常判定, 單品、KD來料不良, 焊點不良.co2焊道不良.壓力值不足, 品質不良調查/改善], 技改=[夾具精度不良.調整, 夾具氣路異常(氣缸.氣管.接頭等氣路元件損壞), 夾具機械異常(定位銷.導向塊等易耗類故障), 塗膠機/遮斷器/刻印機,機械異常], 組裝=[平衡器異常及機械類故障, 電極.定位芯.研磨刀更換異常更換, 握杆、電極杆、電極異常更換, 水、氣管破損更換], 保全=[夾具線路.感應器故障.磁性開關損壞, 懸掛式點焊機.固定焊故障, co2焊機故障.DCE焊機故障, 機器人.自動打點機故障, 螺母(栓)輸送機故障, 螺母(栓)機焊接異常, 研磨機電路故障, 塗膠機/遮斷器異常, 刻印機線路故障.光柵異常, co2機器人研磨.噴油故障, 刻印機電路.程式故障.電磁閥損壞], 物流=[缺輔材, 缺單品, 缺KD, 單/成品待叉車, 缺膠箱.容器不良, 納入異常], 衝壓=[缺單品, 產品不良], 其他=[生理現象, 作業指導, 停電, 停水, 停氣, 其他]}
     * @param datas 列表資料
     * @param response 響應體
     * @param sheetName 匯出表名
     */
    private void getMergeExcel(List<String[]> titles, LinkedHashMap<String, List<String>> titleMap, List<String[]> datas, HttpServletResponse response, String sheetName){
        ByteArrayOutputStream bout = null;
        SXSSFWorkbook xssfWorkbook;
        try{
            Row row = null;
            Cell cell = null;
            CellRangeAddress cellRangeAddress = null;
            xssfWorkbook = new SXSSFWorkbook();
            Sheet sheet = xssfWorkbook.createSheet(sheetName);
            
            // 水平居中
            XSSFCellStyle alignStyle = (XSSFCellStyle) xssfWorkbook.createCellStyle();
            alignStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
            // 垂直居中
            XSSFCellStyle verticalStyle = (XSSFCellStyle) xssfWorkbook.createCellStyle();
            verticalStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
            // 水平垂直居中
            XSSFCellStyle horizontalVerticalStyle = (XSSFCellStyle) xssfWorkbook.createCellStyle();
            horizontalVerticalStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
            horizontalVerticalStyle.setVerticalAlignment(XSSFCellStyle.VERTICAL_CENTER);
            
            // 拼接表頭
            for (int i = 0; i < titles.size(); i++) {
                row = sheet.createRow(i);
                if(i == 0){
                    // 合併表頭個數 + 固定列名個數
                    String[] title0 = titles.get(i);
                    int length = title0.length;
                    
                    // 第一行,序號、日期、班次、生產系、部品
                    for (int j = 0; j < length;) {
                        if(j < 5){
                            // 0~4,固定表頭的索引
                            cellRangeAddress = new CellRangeAddress(0, 1, j, j);
                            sheet.addMergedRegion(cellRangeAddress);
                            cell = row.createCell(j);
                            cell.setCellStyle(horizontalVerticalStyle);
                            cell.setCellValue(title0[j]);
                            j ++;
                            continue;
                        }
                        
                        // 需要合併的單元格
                        int mergeNum = titleMap.get(title0[j]).size();
                        // 指定合併的範圍,開始行,結束行,開始列,結束列
                        cellRangeAddress = new CellRangeAddress(0, 0, j, j + mergeNum - 1);
                        // 將合併單元格加入表中
                        sheet.addMergedRegion(cellRangeAddress);
                        cell = row.createCell(j);
                        // 指定合併單元格內容居中樣式
                        cell.setCellStyle(alignStyle);
                        // 為合併單元格賦值
                        cell.setCellValue(title0[j]);
                        // 指定下一個動態列名的索引位置
                        j += mergeNum;
                    }
                }else if(i == 1){
                    String[] title1 = titles.get(1);
                    int length = title1.length;
                    // 第二行、計劃、實績、差異
                    for (int j = 0; j < length; j ++) {
                        if(j < 5){
                            // 跳過固定表頭的索引
                            continue;
                        }
                        
                        // 5~end,非固定表頭的索引
                        cell = row.createCell(j);
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        cell.setCellValue(title1[j]);
                    }
                }
            }
            for (int i = 0; i < datas.size(); i++) {
                row = sheet.createRow(i+2);
                String[] rows = datas.get(i);
                for (int j = 0; j < rows.length; j++) {
                    cell = row.createCell(j);
                     cell.setCellType(Cell.CELL_TYPE_STRING);
                     cell.setCellValue(rows[j]);
                }
            }
            String title = new String(sheetName.getBytes("utf-8"), "ISO-8859-1");
            response.setHeader("content-disposition", "attachment;filename=" + title + ".xlsx");
            response.flushBuffer();
            xssfWorkbook.write(response.getOutputStream());
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            if(bout!=null){
                try {
                    bout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

匯出excel格式參考: