【Java】使用POI按模板样式导出Excel

一、场景

根据模板样式进行excel导出。

二、实现

首先,当然是要有一个excel模板,excel的样式用wps等进行设置。
然后就是代码的实现了,先引入POI的依赖:

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
        </dependency>

然后就是实现方法里的代码,首先定义响应信息:

		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
		// 设置响应类型
		response.setContentType("application/vnd.ms-excel");
		// 设置字符编码
		response.setCharacterEncoding("utf-8");
		// 设置响应头信息
		response.setHeader("Content-Disposition", "attachment; filename="文件名.xlsx", "utf-8"));

然后将excel模板转为输入流,这一步的实现方法有很多,具体选择因人而异,我这里就举一个例子:

		org.springframework.core.io.Resource resource = new ClassPathResource("templates/文件名.xlsx");
		@Cleanup InputStream inputStream = resource.getInputStream();
		ServletOutputStream outputStream = response.getOutputStream();

然后获取excel模板数据:

		XSSFWorkbook workbook = new XSSFWorkbook(inputStream); // 传入上一步转换的输入流
		Sheet sheet = workbook.getSheetAt(0); // 拿到excel模板的sheet页

我们得到excel模板数据后,肯定不是原模原样导出,否则直接io输出就好了。接下来就是操作excel模板数据,将它构造为我们要导出的excel,我这里仅组合一些常用的操作,具体操作根据个人情况自行组合:

	/**
	 * 修改某单元格的值,先获取y行再获取y行的x列,然后修改值
	 *
	 * x(列,从0开始计数)
	 * y(行,从0开始计数)
	 * value(修改值)
	 */
	sheet.getRow(y).getCell(x).setCellValue(value);

	/**
	 * 插入n行,首先用shiftRows方法将插入位置后面的数据都向下移动n行
	 * 然后循环用createRow方法构造当前行,并用setHeightInPoints方法设置行高
	 * 最后循环用createCell方法构造当前行的列
	 *
	 * startRow(插入位置的下一行,从0开始计数)
	 * endRow(excel表末尾行,从0开始计数)
	 * startColumn(插入行的开始列,从0开始计数)
	 * endColumn(插入行的结束列,从0开始计数)
	 * rowNum(插入行数)
	 * rowHeight(插入行高)
	 */
	sheet.shiftRows(startRow, endRow, rowNum, true, false);
	for (int i = 0; i < rowNum; i++) {
		Row itemRow = sheet.createRow(startRow + i);
		itemRow.setHeightInPoints(rowHeight);
		for (int j = startColumn; j < endColumn + 1; j++) {
			itemRow.createCell(j);
		}
	}

	/**
	 * 得到某单元格的样式,先获取y行再获取y行的x列,然后得到样式
	 *
	 * x(列,从0开始计数)
	 * y(行,从0开始计数)
	 */
	 CellStyle style = sheet.getRow(y).getCell(x).getCellStyle();

	/**
	 * 修改某单元格的样式,先获取y行再获取y行的x列,然后修改样式
	 *
	 * x(列,从0开始计数)
	 * y(行,从0开始计数)
	 * style(修改样式)
	 */
	 sheet.getRow(y).getCell(x).setCellStyle(style);

	/**
	 * 合并单元格
	 *
	 * startRow(开始行,从0开始计数)
	 * endRow(结束行,从0开始计数)
	 * startColumn(开始列,从0开始计数)
	 * endColumn(结束列,从0开始计数)
	 */
	 sheet.addMergedRegion(new CellRangeAddress(startRow, endRow, startColumn, endColumn));

最后输出excel:

	 workbook.write(outputStream);

三、总结

  1. 将excel表抽象为xy轴坐标图,更易于理解POI的操作,y轴对应行,x轴对应列,每个单元格都有一个xy坐标。
  2. 单元格才是实际可操作的对象,行和列都只是用来定位单元格位置的。所以新增行后都要根据列数进行循环,来新增单元格。
  3. 新增的单元格都不具备任何样式,可以获取其他单元格的样式进行赋予。
  4. 如果不涉及对模板新增行、新增列等操作,那修改一下单元格的值就够用了,毕竟单元格样式完全可以在wps先设置好。

猜你喜欢

转载自blog.csdn.net/qq_45050480/article/details/128579776
今日推荐