report.java

来自「Excel Report是一款基于Excel的报表生成工具」· Java 代码 · 共 1,082 行 · 第 1/3 页

JAVA
1,082
字号
        try {
            if(log.isDebugEnable()){
                log.debug("Begin create workbook.");
            }
            Workbook wbTemplet = this.reportConfig.getTempletWorkbook();
            wb = Workbook.createWorkbook(os, wbTemplet);
            
            if(log.isDebugEnable()){
                log.debug("create workbook success!");
            }
            
            String[] sheetNames = reportConfig.getSheetName();
            WritableSheet sheet = null;
            
            if(log.isDebugEnable()){
                log.debug("Writing data...");
            }
            for (int i = 0; i < sheetNames.length; i++) {
                sheet = wb.getSheet(sheetNames[i]);
                if (null == sheet) {
                    log.error("Can't get the sheet with the specified name(:"
                                    + sheetNames[i] + ") from templet file");
                } else {
                    //writeSheet(sheet, reportConfig.getSheet(sheetNames[i]), this.dataSources);
                    writeSheetEx(sheet, reportConfig.getSheet(sheetNames[i]));
                } 
            }

            wb.write();
            if(log.isDebugEnable()){
                log.debug("Writing data success!");
            }
        } catch (Exception e) {
            log.error("Error:" + e.getMessage());
            throw e;
        } finally {
            if (wb != null)
                wb.close();
        }
    }
    
    
    public void writeSheet(WritableSheet sheet, SheetConfig sheetConfig,
            Map dataSource) throws Exception{
        WritableCell wc = null;
        CellFormat cf = null;
        Group group = null;
        
        //生成嵌套组
        groups = new GroupManager();
        Stack groupStack = new Stack();
        
        //取得数据源
        this.dataSources = dataSource;
        
        //分析模板文件
        int rows = sheet.getRows();
        for(int i=0; i<rows; i++){
            Cell[] cells = sheet.getRow(i);
            for(int j=0; j<cells.length; j++){
                wc = sheet.getWritableCell(cells[j].getColumn(),cells[j].getRow());
                //配置信息记录单元都为LABEL
                if ((wc.getType() != CellType.LABEL) ){
                    continue;
                }
                if(this.isGroupBegin(wc)){
                    //处理组信息.
                    group = getGroup(wc);
                    groups.add(group);
                    groupStack.push(group);
                }else if(this.isGroupEnd(wc)){
                    //判断当前组是否正确关闭.如果组正常关闭则记录组结束信息.
                    if(!isGroupEnd(wc, (Group)groupStack.pop())){
                        //无效的组配置信息,组必须按顺序嵌套.
                        throw new Exception("Error: Invalid group config!");
                    }
                }else if(isVariable(wc) && groupStack.isEmpty()){
                    //从数据源中取出相应变量值,并写入报表文件.
                    writeValue(wc, dataSources);
                }
            }
        }
        
        if(groups.size() > 0){
            //读取模板组包含的其他信息.
            getGroupOtherInfo(sheet);
            //写入组信息.
            writeGroup(sheet, dataSources);
            //删除模板
            deleteTempletTrace(sheet);
        }
    }

    public void writeGroup(WritableSheet sheet, Map dataSource)
    	throws Exception{
        //取得顶层组
        int rows = 0, curGroupIndex = 0;
        Group group = groups.get(curGroupIndex);
        
        //取得组对应数据源.
        IDataSource ds = getGroupDataSource(dataSource, group);
        
        Map rowData = null;
        WritableCell wc = null;
        int curRow = 0, curCol = 0;
        int endRow = 0, endCol = 0;
        int templetEndRow = 0, templetBeginRow = 0;
        
        //按照组模板定义格式生成报表数据.
        if(null != ds && ds.size() > 0){
            templetBeginRow = group.getBeginRow();
            templetEndRow = group.getEndRow();
            //第一组信息用作模板,其他信息都是根据模板来生成.
            curRow = group.getEndRow() + 1;
            do{
                curRow = writeCurrentRecordToSheet(sheet, 
					                        dataSource, 
					                        ds, 
					                        curGroupIndex, 
					                        curRow);
                ds.next();
            }while(ds.hasNext());
        }
    }
    
    //输出嵌套组的报表信息.
    public int writeSubGroup(WritableSheet sheet, 
            Map dataSource, 
            int curGroupIndex,
            int curRow) throws Exception {
        //取得datasource
        Group group = groups.get(curGroupIndex);
        
        //取得组对应数据源.
        IDataSource ds = getGroupDataSource(dataSource, group);
        
        if(null != ds && ds.size() > 0){
            int templetBeginRow = group.getBeginRow();
            int templetEndRow = group.getEndRow();
            
            Group nextGroup = groups.get(curGroupIndex + 1);
            //输出嵌套组报表数据
            do{
                curRow = writeCurrentRecordToSheet(sheet, 
				                        dataSource, 
				                        ds, 
				                        curGroupIndex, 
				                        curRow);
                ds.next();
            }while(ds.hasNext());
        }
        return curRow;
    }
    
    private void deleteTempletTrace(WritableSheet sheet){
        ArrayList allGroups = groups.getAllGroups();
        Group rootGroup = (Group)allGroups.get(0);
        
        int beginRow = rootGroup.getBeginRow();
        int endRow = rootGroup.getEndRow();
        
        //此处不能从结束行开始删除,否则保存数据时会出现合并错误的单元格.
        for (int i = beginRow; i <= endRow; i++) {
            sheet.removeRow(beginRow);
        }
        
    }
    
    /*
     * 读取模板组内的其他信息,如组内包含的图片信息,超链接信息,
     * 合并单元格信息等,因为这些信息不能通过单个单元格的拷贝操作
     * 来拷贝,只能标识出来一个一个手动拷贝.
     */
    public void getGroupOtherInfo(WritableSheet sheet){
        ArrayList allGroups = groups.getAllGroups();
        Range[] mergedCells = sheet.getMergedCells();
        Group curGroup = null;
        
        //不存在合并单元格则退出.
        if(mergedCells.length <= 0) return;
        
        //将合并单元格信息拷贝到链表中,方便动态删除已经保存过的合并单元格.
        List mergedCellLists = new LinkedList();
        for(int i=0; i<mergedCells.length; i++){
            mergedCellLists.add(mergedCells[i]);
        }
        
        //这里循环必须从最里面的组开始循环
        int row = 0, col = 0;
        Range rang = null;
        for (int i = groups.size() - 1; i >= 0; i--) {
            curGroup = groups.get(i);
            //链表的大小会改变.
            Iterator itr = mergedCellLists.iterator();
            
            while(itr.hasNext()){
                rang = (Range)itr.next();
                row = rang.getTopLeft().getRow();
                col = 0;
                if(curGroup.contain(row, col)){
                    curGroup.setMergedCell(rang);
                    //从链表中删除该记录,否则上级组会重复包含该信息.
                    itr.remove();
                }
            }
        }
    }
    
    /*
     * 将数据源的当前记录数据写入报表.(数据分布格式根据模板来取得)
     */
    private int writeCurrentRecordToSheet(WritableSheet sheet, 
            						Map dataSource, //所有dataSource集合
            						IDataSource ds, //当前组正在处理的DataSource
            						int curGroupIndex, //嵌套组数据
            						int currentRow //当前数据写入行
            						) throws Exception {
        //当前处理组.
        Group group = this.groups.get(curGroupIndex);
        int templetBeginRow = group.getBeginRow();
        int templetEndRow = group.getEndRow();
        
        //取得嵌套组
        Group nextGroup = groups.get(curGroupIndex + 1);
        
        //组写入开始行
        int beginRow = currentRow;
        int curRow = beginRow;
        int cells = sheet.getColumns();
        
        for (int i = templetBeginRow + 1; i < templetEndRow; ) {
            //判断当前行是否嵌套组
            if(nextGroup != null){
                if (nextGroup.contain(i, 0)) {
                    //存在嵌套组
                    curRow = writeSubGroup(sheet, dataSource, curGroupIndex + 1, curRow);
                    //跳过嵌套组行数,继续处理本组数据.
                    //嵌套组的数据writeSubGroup函数负责处理
                    i += nextGroup.getEndRow() - nextGroup.getBeginRow() + 1;
                    continue;
                }
            }
            
            //拷贝行高度
            CellView rowView = sheet.getRowView(i);
            sheet.insertRow(curRow);
            sheet.setRowView(curRow, rowView.getSize());

            //拷贝模板行数据, 将模板行对应的数据写入目标行,如果存在变量则取出变量值.
            copyRow(sheet, i, curRow, 0, cells);
            curRow++;
            i++;
        }
        
        //拷贝组内合并单元格信息.
        copyMergedCells(sheet, curGroupIndex, beginRow);
        
        //拷贝组内图片信息.
        
        //拷贝组内超链接信息.
        
        return curRow;
    }
    
    /*
     * 拷贝组内合并单元格信息
     */
    public void copyMergedCells(WritableSheet sheet, 
				            int curGroupIndex, 
				            int beginRow)
    						throws Exception{
        
        //处理当前组.
        Group group = this.groups.get(curGroupIndex);
        Object[] mergedCells = group.getMergedCells();
        Cell topLeft = null, bottonRight = null;
        int topLeftRow = 0, btRightRow = 0;
        
        for(int i=0; i<mergedCells.length; i++){
            topLeft = ((Range)mergedCells[i]).getTopLeft();
            bottonRight = ((Range)mergedCells[i]).getBottomRight();
            topLeftRow = beginRow + (topLeft.getRow() - (group.beginRow + 1));
            btRightRow = beginRow + (bottonRight.getRow() - (group.beginRow + 1));
            //debug info
            log.debug("merge cell beginrow:" + topLeftRow 
                    				+ " begincol:" + topLeft.getColumn()
                    				+ " endRow:" + btRightRow
                    				+ " endCol:" + bottonRight.getColumn());
            
            sheet.mergeCells(topLeft.getColumn(), 
                    topLeftRow,
                    bottonRight.getColumn(),
                    btRightRow);
        }
    }
    
    /*
     * 拷贝一行数据到另外一行.
     */
    public void copyRow(WritableSheet sheet, 
            int sourceRow, 
            int destRow)
    		throws Exception{
        Cell[] cells = sheet.getRow(sourceRow);
        copyRow(sheet, sourceRow, destRow, 0, cells.length);
    }
    
    /*
     * 拷贝指定行数据, sourceRow开始行,destRow拷贝目标行,
     * 				beginCol开始列,endCol结束列.
     */
    public void copyRow(WritableSheet sheet, 
            int sourceRow, 
            int destRow,
            int beginCol, 
            int endCol)
    		throws Exception{
        WritableCell wc = null;
        Cell[] cells = sheet.getRow(sourceRow);
        
        //循环模板单元格,处理组当前行数据
        for (int i = beginCol; i < endCol; i++) {
            wc = sheet.getWritableCell(i, sourceRow);
            WritableCell newWc = wc.copyTo(i, destRow);
            
            //配置信息记录单元都为LABEL
            if ((newWc.getType() == CellType.LABEL)
                    && isVariable(newWc)) {
                //从数据源中取出相应变量值,并写入报表文件.
                writeValue(newWc, this.dataSources);
            }
            sheet.addCell(newWc);
        }
    }
    
    /*
     * 根据组配置的数据源信息,取得组对应数据源及数据.
     */
    private IDataSource getGroupDataSource(Map dataSource, Group group)
    	throws Exception {
        String fieldMap = null;
        boolean resetParam = false;
        String groupSourceName = group.getDataSource();
        IDataSource ds = (IDataSource)dataSource.get(groupSourceName);
        
        if(null != ds){
            String temp = "", value = "";
            Map paramsMap = group.getParamsMap();
            List params = ds.getConfig().getParams();
            if(paramsMap.size() != params.size()){
                log.warn("The number of user passed parameters are not equal " +
                		"the number of the config file defined! Group name=" + group.getName());
            }
            if(paramsMap.size() == params.size()){
	            //取得检索组数据的DataSource的参数值
	            for(int i=0; i<params.size(); i++){
	                fieldMap = (String)paramsMap.get(params.get(i));
		            if(null != fieldMap){
		                String fieldValue = getDataFromDataSource(dataSource, "[" + fieldMap + "]");
		                if(null != fieldValue){
		                    ds.setParameter((String)params.get(i), fieldValue);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?