需要制作一个报表
成品样式
如图所见,这个报表需要可以配置显示信息,并一直向右向下拓展,且需要合并所需的单元格
第一步 制作模板
模板最终射击成这个样子,两个表中间的距离,由上表的循环极限行数决定,在a1和a13处使用批注jx:area(lastCell="I6") 之类的命令来圈定区域
然后是其他地区的循环,可见行6和行18是向下循环的,而b2:e6、f2:i6、b14:e18、f14:i18区域是向右循环增加的,向右循环需要在批注注明,例如b2处批注为:
jx:each(items="zzz"var="qj"lastCell="E6"direction="RIGHT")
jx:each(items="qj.yearList"var="year"lastCell="E6"direction="RIGHT")
b6处批注为: jx:each(items="year.list"var="l"lastCell="E6")
现在每个表分为三个list进行循环,而主要地区的list中仍有其他list进行循环
第二步 在后台获取填充用的list,这步就随便了
第三部 合并单元格.
jxls有合并单元格的功能 :合并单元格说明
这个功能可以通过提供批注来进行合并单元格操作,例如
jx:mergeCells(cols="year.mergeCell>0?year.mergeCell*4:4"lastCell="E2")之类的,但是不太好用,因为lastCell="E2"的原因,就会停止合并单元格,使得每个循环出的块状区域不能合并,想了半天还是用poi解决.
JxlsHelper.getInstance().processTemplate(is, outputStream, context);
// 生成输出流后将其转换为字节数组
byte[] content = outputStream.toByteArray();
//将字节数组转为poi工作表,并获取该页
XSSFWorkbook wbook = new XSSFWorkbook(new ByteArrayInputStream(content));
Sheet sheet = wbook.getSheet("xxx");
// 获取待合并数据
Row xxx= sheet.getRow(1); // 第一行
Row yyy= sheet.getRow(2); //第二行
String name= "";
int startNum = 0; // 开始合并单元格的列的位置
int endNum = 0; // 结束合并单元格列的位置
int rowNum = 1 ;// 合并起始和结束的行数
for(int ii = 1 ; ii < xxx.getLastCellNum() ; ii += 4) {
if (yyy.getCell(ii).toString().equals("")){
// 如果进入隔壁区域则退出循环
if (endNum > 0){
//如果大于0 则存在合并位置 进行合并
CellRangeAddress region = new CellRangeAddress(rowNum,rowNum,startNum,endNum+3);
sheet.addMergedRegion(region);
xxx.getCell(startNum).setCellValue(name);
}
break;
}
// 1. 获取单元格内容
if (name.equals("")){
name= xxx.getCell(ii).toString();
startNum = ii;
}else{
// 2. 如果相同则进行合并 如果不同则更新对比
if (xxx.getCell(ii).toString().equals(name)){
// 相同则记录单元格位置
endNum = ii;
}else{
// 如果不同 且存在合并区域 则进行更新
if (endNum > 0){
//如果大于0 则存在合并位置 进行合并
CellRangeAddress region = new CellRangeAddress(rowNum,rowNum,startNum,endNum+3);
sheet.addMergedRegion(region);
xxx.getCell(startNum).setCellValue(name);
}else{
//如果大于0 则存在合并位置 进行合并
CellRangeAddress region = new CellRangeAddress(rowNum,rowNum,startNum,startNum+3);
sheet.addMergedRegion(region);
xxx.getCell(startNum).setCellValue(name);
}
//更新单元格起始位置
name= xxx.getCell(ii).toString();
startNum = ii;
endNum = 0;
}
}
}
总之大概就这样, 其他地方类似
然后合并标题单元格
// 合并标题单元格并更新
CellStyle cellStyle = sheet.getRow(0).getCell(0).getCellStyle(); //获取单元格样式
int titleEndNum = zzz.getLastCellNum()-1;
Row row12 = sheet.getRow(12);
Row row0 = sheet.getRow(0);
// 更新标题单元格样式
for (int ii = 7 ; ii< titleEndNum+1; ii++ ){
if ( sheet.getRow(0).getCell(ii) != null){
sheet.getRow(0).getCell(ii).setCellStyle(cellStyle);
sheet.getRow(12).getCell(ii).setCellStyle(cellStyle);
}else{
sheet.getRow(0).createCell(ii);
sheet.getRow(12).createCell(ii);
sheet.getRow(0).getCell(ii).setCellStyle(cellStyle);
sheet.getRow(12).getCell(ii).setCellStyle(cellStyle);
}
}
//表1标题
String title = sheet.getRow(0).getCell(0).toString();
CellRangeAddress region = new CellRangeAddress(0,0,0,titleEndNum);
sheet.addMergedRegion(region);
sheet.getRow(0).getCell(0).setCellValue(title);