灵活使用递归算法,生成Excel文件中的复合表头
最近,在开发中,需要导出数据到excel文件,文件的表头的格式是不一致的。有复合表头,也有单表头,那么如何灵活地生成excel文件中的复合表头。

首先有一个JSON字符串格式的字段描述,如下所示:
var columnDefs = [{
key:"unit",
label:"单位"
},{
key:"form",
label:"货物"
},{
key:"putin",
label:"2011年03月",
children:[{
key:"shout",
label:"buy"
},{
key:"sale",
label:"销售"
},{
key:"rate",
label:"百分比(%)"
}]
},{
key:"average",
label:"平均(%)"
}];
如果表的宾栏中有子栏,children是不为空的。自己写的代码,是在项目中写的,比较匆忙,还有提高的余地:
private int insertHeader(HSSFSheet sheet, List columns, int rowIndex, HSSFWorkbook wb) { HSSFCellStyle cellStyle = this.getCellStyle(wb); cellStyle.setAlignment(HSSFCellStyle.VERTICAL_CENTER); cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); HSSFRow row = sheet.createRow(rowIndex); //横向的单元格的列数,这里设置一个方法外的变量,初始化为零 nextCellIndex = 0; int rowNumber = setSubCellValue(sheet, rowIndex, cellStyle, row, nextCellIndex, columns); //设置每一行的自适应单元格内容的长度 setColumnWidth(sheet, rowNumber); //返回生成表头之后的行数 return rowNumber; } private int setSubCellValue(HSSFSheet sheet, int rowIndex, HSSFCellStyle cellStyle, HSSFRow row, int nextCellIndex, List columns) { HSSFRow nextRow = null; //遍历json格式的字段描述,并横向生成单元格 for (int i = 0; i < columns.size(); i++) { JSONObject column = (JSONObject) columns.get(i); JSONArray children = (JSONArray) column.get("children"); if (children != null) { //设置父表格,并返回下一个单元格的列数 nextCellIndex = setParentCellValue(sheet, cellStyle, row, nextCellIndex, column, children.size()); nextCellIndex = nextCellIndex + 1; //因为存在子表格,所以生成下一行 if (nextRow == null) { nextRow = sheet.createRow(++rowIndex); } //使子单元格的位置,回退的到起始位置 int subCellStartPosition = nextCellIndex - children.size(); //递归生成子单元格,这里参数可以简化 setSubCellValue(sheet, rowIndex, cellStyle, nextRow, subCellStartPosition, children); } else { //如果不是复合表头,直接生成并设置单元格 nextCellIndex = setCellValue(sheet, cellStyle, row, nextCellIndex, column); ++nextCellIndex; } } //跨行的单元格合并 mergeRowByColumn(sheet, rowIndex, columns, nextRow, cellStyle); //递归,生成这一行的单元格,并返回当前行数 return rowIndex; } //设置复合单元格的父表格 private int setParentCellValue(HSSFSheet sheet, HSSFCellStyle cellStyle, HSSFRow row, int cellIndex, JSONObject field, int childrenSize) { cellIndex = setCellValue(sheet,cellStyle, row, cellIndex, field); int columnFrom = cellIndex; int columnTo = columnFrom + childrenSize - 1; createMergeCell(sheet, row, cellStyle, columnFrom, columnTo); return columnTo; } private int setCellValue(HSSFSheet sheet, HSSFCellStyle cellStyle, HSSFRow row, int cellIndex, JSONObject column) { HSSFCell subCell = row.createCell(cellIndex); subCell.setCellStyle(cellStyle); subCell.setCellValue(column.get("label").toString()); return cellIndex; }