1. 程式人生 > >Java poi 根據業務合併單元格

Java poi 根據業務合併單元格

        Java poi操作Excel 是比較常用的,通常我們用來匯出Excel格式的文字資料。比如說兩個表,一個是入庫明細,一個是結算明細。針對每一條的入庫明細可能有對於的幾條的結算明細資訊,結算明細中有id關聯到入庫明細。這時候可能會要求把資料展示在一張Excel中。

類似以下的表格


從入庫時間到有效期是 來自於 入庫明細的表,從結算時間到後面的列是來源於結算明細的表。

要操作合併單元格 主要用到的對 CellRangeAddress的操作。

public CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) 計算好 它的構造引數的值

根據每條入庫明細下的結算明細數量 計算出跨行的 firstRow 與lastRow

/**
     * 根據跨行數來轉化 CellRangeAddress(int firstRow, int lastRow, int firstCol, int lastCol) 的 firstRow 與 lastRow
     * @param list   每條記錄需要的跨行數
     * @param minRow 從第幾行開始跨行
     * @return
     */
    private Map<Integer,Integer> transPositionMap(List<Integer> list,Integer minRow){
    	if(CollectionUtils.isNotEmpty(list)){
    		Map<Integer,Integer> linkedMap = new LinkedHashMap<>();
        	List<Integer> xPositionList = new ArrayList<>();
        	xPositionList.add(minRow);
        	for(Integer pos:list){
        		if(pos == 1 || pos == 0){
        			pos = 1;
        			Integer xPosition = Collections.max(xPositionList);
        			xPositionList.add(xPosition+pos);
        			continue;
        		}
        		Integer xPosition = Collections.max(xPositionList);
        		linkedMap.put(xPosition, xPosition+pos-1);
        		xPositionList.add(xPosition+pos);
        	}
        	return linkedMap;
    	}
		return Collections.emptyMap();
    }
@Test
    public void test3(){
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("test");
        HSSFRow row = sheet.createRow(0);
        String[] strArr = {"入庫時間","產品名","商業公司","批號","單價","數量","金額","有效期","結算時間","實際結算數量","實際結算單價","實際結算金額","票號","稅金","備註"};
        HSSFCellStyle cellStyle = workbook.createCellStyle();
        Font fontStyle = workbook.createFont();
        fontStyle.setFontHeightInPoints((short) 11);  
        cellStyle.setFont(fontStyle);  
        cellStyle.setAlignment(HorizontalAlignment.CENTER); 
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        for(int i = 0;i<strArr.length;i++){
        	HSSFCell cell = row.createCell(i);
        	cell.setCellValue(strArr[i]);
        	cell.setCellStyle(cellStyle);
        }
        for(int i = 1;i < 20 ;i++){
        	row = sheet.createRow(i);
        	for(int j = 0;j<strArr.length;j++){
        		HSSFCell cell = row.createCell(j); 
        		cell.setCellValue("單元格"+i);
        		cell.setCellStyle(cellStyle);
        	}
        }
        //spanRows 表示 每條記錄可能的跨行數
        List<Integer> spanRows = Arrays.asList(1,3,4,4,4,3,1);
        Map<Integer,Integer> positions = transPositionMap(spanRows, 1);
        for(int j = 0;j<8 ;j++){
        	for(Map.Entry<Integer, Integer> entry:positions.entrySet()){
        		CellRangeAddress cra =new CellRangeAddress(entry.getKey(),entry.getValue(), j, j);// 起始行, 終止行, 起始列, 終止列  
                sheet.addMergedRegion(cra); 
        	}
        }
        String excelName = "D:/myExcel.xls";  
        FileOutputStream out = null;  
        try {  
            out = new FileOutputStream(excelName);  
            workbook.write(out);  
            out.flush();  
            out.close();  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            if (out != null)  
                try {  
                    out.close();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            out = null;  
        }  
    }

控制檯執行單元測試後


以上為了簡便,直接用的資料來模擬效果。實際中比如 agent_stock 入庫明細表 agent_stock 結算明細表

1.agent_stock   left join  agent_stock  來刷選匹配的記錄集

2.agent_stock  left join  agent_stock  group by agent_stock  的id ,count(agent_stock.id) 計算每條 agent_stock的跨行數

即相當於單元測試中  List<Integer> spanRows 的作用。

3.注意private Map<Integer,Integer> transPositionMap(List<Integer> list,Integer minRow) 中的方法。