java中Excel导出模板(跨行跨列导出)

java中Excel导出模板(跨行跨列导出)

笔者昨天有个需求,就是把下面的课时信息页签的内容原样导出:
java中Excel导出模板(跨行跨列导出)_第1张图片
这个地方看似不难,实际后台很复杂,数据的来源也复杂,并不好处理。但是这不是让我纠结的地方。
我纠结的地方是,表头的跨行跨列,而且有的列还是动态的。

有了技术问题的时候,捋捋思路后,如果还解决不了,那可能是要去百度了,因为毕竟是在工作,不要耽误时间,赶紧解决问题。

七拼八凑整理了一套方法(后边附上代码),实现的小时如下:
java中Excel导出模板(跨行跨列导出)_第2张图片
就这样,表头的问题就解决了。
代码:

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();
		}
	}
}

创建格子的代码说明:
java中Excel导出模板(跨行跨列导出)_第3张图片
其实光看代码就可以了。但是这里有个比较麻烦的地方,需要我们理解。就是 每次计算行的格子的起始位置的问题 很容易错,还不好找原因,下面上图整理下:
java中Excel导出模板(跨行跨列导出)_第4张图片
说明:

  • 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);
  • 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列结束
含义是:夸两行,不跨列

你可能感兴趣的:(java,POI,Excel导出模板,excel跨行跨列导出,java中excel)