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) 中的方法。


阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页