跳转地址:点我
java中Excel导出模板(跨行跨列导出)
在这里插入图片描述
这个地方看似不难,实际后台很复杂,数据的来源也复杂,并不好处理。但是这不是让我纠结的地方。
我纠结的地方是,表头的跨行跨列,而且有的列还是动态的。
有了技术问题的时候,捋捋思路后,如果还解决不了,那可能是要去百度了,因为毕竟是在工作,不要耽误时间,赶紧解决问题。
七拼八凑整理了一套方法(后边附上代码),实现的小时如下:
在这里插入图片描述
就这样,表头的问题就解决了。
代码:
package com.incon.project.xmsb.controller;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.Region;
/**
-
@方法描述 java中excel导出包括合并单元格和单元格样式
-
@初次开发 平传胜
-
@开发日期 2019年4月23日下午2:21:05
*/
public class TestPoi2 {
public static void main(String[] args) throws IOException {
try {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet(“POI-Excel测试”);HSSFCellStyle style = wb.createCellStyle(); // 样式对象 style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 垂直 style.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 水平 //因为需求一共有3行数据,这里就先创建3个行的空数据,之后分别对这3个行数据进行操作 HSSFRow row1 = sheet.createRow((short) 0);//先创建第一行空数据 HSSFRow row2 = sheet.createRow((short) 1);//先创建第二行空数据 HSSFRow row3 = sheet.createRow((short) 2);//先创建第三行空数据 /** 设置第一行的数据 */ // 四个参数分别是:起始行,起始列,结束行,结束列 //第1个格子,夸3行 sheet.addMergedRegion(new Region(0, (short) 0, 2, (short) 0)); HSSFCell ce1 = row1.createCell((short) 0); ce1.setCellValue("序号");//表格的第一行第一列显示的数据 ce1.setCellStyle(style);//样式,居中 //第2个格子,夸3行 sheet.addMergedRegion(new Region(0, (short) 1, 2, (short) 1)); HSSFCell ce2 = row1.createCell((short) 1); ce2.setCellValue("所在学院"); ce2.setCellStyle(style); //第3个格子,夸3行 sheet.addMergedRegion(new Region(0, (short) 2, 2, (short) 2)); HSSFCell ce3 = row1.createCell((short) 2); ce3.setCellValue("教师姓名"); ce3.setCellStyle(style); //第4个格子,夸14列 sheet.addMergedRegion(new Region(0, (short) 3, 0, (short) 16)); HSSFCell ce4 = row1.createCell((short) 3); ce4.setCellValue("近几年课堂教学学时"); ce4.setCellStyle(style); /** 设置第二行的数据 */ //第5个格子,夸2行 sheet.addMergedRegion(new Region(1, (short) 3, 2, (short) 3)); HSSFCell ce5 = row2.createCell((short) 3); ce5.setCellValue("课程名称"); ce5.setCellStyle(style); //第6个格子,夸2行 sheet.addMergedRegion(new Region(1, (short) 4, 2, (short) 4)); HSSFCell ce6 = row2.createCell((short) 4); ce6.setCellValue("课程性质"); ce6.setCellStyle(style); //生成动态的那些行列值 for (int i = 0; i < 6; i++) { // 计算从那个单元格跨到那一格 int row2_cell_1 = 4;//第二行的第1个值(其实是第4个值,因为前面已经有3列被占用,所以要从第四列开始) int row2_cell_2 = 5;//第二行的第2个值(其实是第5个值,因为前面已经有4列被占用,所以要从第四列开始) if (i > 0) { row2_cell_1 = (i * 2 + 4);//每行夸两列 row2_cell_2 = (i * 2 + 4 + 1);// +1表示下一列的值的取值范围 } // 单元格合并 sheet.addMergedRegion(new Region(1, (short) (row2_cell_1 + 1), 1, (short) (row2_cell_2 + 1))); HSSFCell cell = row2.createCell((short) (row2_cell_1 + 1)); cell.setCellValue("201" + i + "秋季"); // 跨单元格显示的数据 cell.setCellStyle(style); /** 设置第三行的数据 */ // 不跨单元格显示的数据,如:分两行,上一行分别两格为一格,下一行就为两格,“课时”,“人数” sheet.addMergedRegion(new Region(0, (short) (row2_cell_1 + 1), 0, (short) (row2_cell_2 + 1))); HSSFCell cell1 = row3.createCell((short) row2_cell_2); HSSFCell cell2 = row3.createCell((short) (row2_cell_2 + 1)); cell1.setCellValue("课时"); cell1.setCellStyle(style); cell2.setCellValue("人数"); cell2.setCellStyle(style); } //将文件生成到 d 盘根目录下,取名为 workbook.xls FileOutputStream fileOut = new FileOutputStream("d:/workbook.xls"); wb.write(fileOut);//写出文件 fileOut.close();//关闭流 System.out.print("Excel文件已成功导出,请到D盘根目录查找 workbook.xls 文件!"); } catch (Exception ex) { ex.printStackTrace(); }
}
}
创建格子的代码说明:
在这里插入图片描述
其实光看代码就可以了。但是这里有个比较麻烦的地方,需要我们理解。就是 每次计算行的格子的起始位置的问题 很容易错,还不好找原因,下面上图整理下:
在这里插入图片描述
说明:
1,红黄蓝,分别对应代码中的第一行(row1)、第二行(row2)、第三行(row3)的数据的获取;
2,行号、列号,在程序里取值的时候都是从0开始的;
3,编号为圈4的那个大格子,是第一行的第四个值,所以取值的方法是:
//第4个格子,夸14列
sheet.addMergedRegion(new Region(0, (short) 3, 0, (short) 16));
HSSFCell ce4 = row1.createCell((short) 3);
ce4.setCellValue(“近几年课堂教学学时”);
ce4.setCellStyle(style);
1
2
3
4
5
4,编号从21-28的都是第二行数据。这里取值就要注意了。因为其实,21号是第二行的第4列了。所以取第21号的数据的时候代码应是:
sheet.addMergedRegion(new Region(1, (short) 3, 2, (short) 3));
HSSFCell ce5 = row2.createCell((short) 3);
ce5.setCellValue(“课程名称”);
ce5.setCellStyle(style);
代码解释:
new Region(1, (short) 3, 2, (short) 3)
表示:第2行开始,第4列开始,第3行结束,第4列结束
含义是:夸两行,不跨列