poi导出excel,批量,批量插入图片功能,合并单元格,往已存在的数据列后面插入数据

这篇博客详细讲解了如何使用Apache POI库处理Excel数据,包括创建、设置样式、自定义列宽、合并单元格以及根据业务需求动态插入数据。此外,还介绍了如何在Excel中插入图片,包括图片的位置调整和大小设置。内容涵盖了数据处理的技巧和图片功能的实现,适合需要生成复杂Excel报表的开发者参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近接收了一个做数据报表的一个系统,一堆奇葩的需求。数据报表嘛,都会涉及数据导出各式各样的excel,话不多说,上教程

1,poi的XSSFWorkbook

XSSFWorkbook:是操作Excel2007的版本,扩展名是.xlsx,千万不要用错了如果你用的是HSSFWorkbook扩展名不是.xl会报错;

上代码:

XSSFWorkbook wb = new XSSFWorkbook();
			// sheet页名称
			XSSFSheet sheet = wb.createSheet(sheetName);
			sheet.autoSizeColumn(1, true);
			sheet.createRow(0).setHeight((short) 800);// 首行高度
			XSSFRow row = sheet.createRow(0);
			//row.setHeightInPoints(40);

			XSSFCellStyle style = this.getColumnTopStyle(wb);
			// 第一个参数代表列id(从0开始),第2个参数代表宽度值
			sheet = ExcelTemplate.getHeadSheet(sheet, heads.length);
			// 冻结首行
			sheet.createFreezePane(0, 1, 0, 1);
			// 获取模板
			///XSSFCell cell = ExcelTemplate.getHeadCall(row, style, heads);
//这里我进行了数据处理的一个封装
		ExcelTemplate.exportTemplateImg( row, sheet,heads, style,this.getStyle(wb), collect , multipartfiles,courseIds,wb);

封装段里面的数据处理是根据我的业务需求来设计的可以与其他的人的不符合:

XSSFCell cell = row.createCell(0);
		Integer count = 0;
		for (Integer courseId : courseIds) {
			for (int j = 0; j < heads.length; j++) {
				row = sheet.getRow(1);
				if (null == row) {
					//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
					//否则会出现空指针异常
					row = sheet.createRow(1);
				}
				cell = row.createCell(count + j);
				cell.setCellValue(heads[j]);
				cell.setCellStyle(style);
			}
			List<PlanImgExcelVO> list = collect.get(courseId);
			for (int i = 0; i < list.size(); i++) {
				PlanImgExcelVO vo = list.get(i);
				if (!VerifyUtil.isEmpty(vo.getAimName())) {
					row = sheet.getRow(0);
					cell = row.createCell(count + 0);
					cell.setCellValue(vo.getAimName());
					cell.setCellStyle(style);
				}
				row = sheet.getRow(i + 2);
				if (null == row) {
					//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
					//否则会出现空指针异常
					row = sheet.createRow(i + 2);
				}
				cell = row.createCell(count + 0);
				cell.setCellValue(vo.getFinishDate());
				cell.setCellStyle(style1);

				cell = row.createCell(count + 1);
				cell.setCellValue(vo.getPlanNum());
				cell.setCellStyle(style1);

				cell = row.createCell(count + 2);
				cell.setCellValue(vo.getFinishNum());
				cell.setCellStyle(style1);


			}
//合并数据格(首行,末行,首列,末列)
			CellRangeAddress region = new CellRangeAddress(0, 0, count + 0, count + 2);
			sheet.addMergedRegion(region);
			count += 4;
		}

这里有一个小提示,是否有需要生成数据是根据数据类型进行导入excel,就是在一个数据列的后面列再去插入数据,如图:       这样的数据格式

首先我们来看,一般我们插入都是一个list集合,

for (int i = 1; i < list.size() + 1; i++) {
			row = sheet.createRow((int) i);
			TestVO vo = list.get(i - 1);

			cell = row.createCell(0);
			cell.setCellValue(i);
			cell.setCellStyle(style);

			cell = row.createCell(1);
			cell.setCellValue(vo.getProjectNum());
			cell.setCellStyle(style);

			cell = row.createCell(2);
			cell.setCellValue(vo.getProjectName());
			cell.setCellStyle(style);

			cell = row.createCell(3);
			cell.setCellValue(vo.getName());
			cell.setCellStyle(style);

row = sheet.createRow((int) i);这个代码就是创建单元行,这样的方式试用与单个list且数据横向添加,我们现在是要的纵向的如上图那样,我是这样设计的,既然我们都创建的行,我在获取出来行不,row = sheet.getRow(i);获取行的代码,这样获取它的行再添加就不会出现重复行创建之前的数据没有了的情况,

row = sheet.getRow(i + 2);
				if (null == row) {
					//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
					//否则会出现空指针异常
					row = sheet.createRow(i + 2);
				}
如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内,否则会出现空指针异常。

以上是数据处理,接下来图片功能。

public void exportExcelImg(HttpServletRequest request, HttpServletResponse response,@RequestBody PlanImgFindExcelDTO dto) throws IOException {

        
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        List<MultipartFile> multipartfiles = multipartRequest.getFiles("images");
        
        //先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
        // String imageUrlHead = PropertiesUtils.getProperty("IMAGE_URL_HEAD");

        //创建一个excel文件,名称为:
        XSSFWorkbook workbook = new XSSFWorkbook();
        //创建一个sheet,名称为工作簿1
        XSSFSheet sheet = workbook.createSheet("工作簿1");

        //画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
        XSSFDrawing patriarch = sheet.createDrawingPatriarch();
        //anchor主要用于设置图片的属性
       /* XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 2, 2, (short) 4, 4);
        anchor.setAnchorType(ClientAnchor.MOVE_AND_RESIZE);*/

        Integer col1 = 0;
       if (multipartfiles != null)) {
			//先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
			ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
			//画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
			XSSFDrawing patriarch = sheet.createDrawingPatriarch();
			Integer col1 = 0;
			for (MultipartFile file : multipartfiles) {
				Map<String, Object> map = new HashMap<String, Object>();
				// 文件名
				String originalFilename = file.getOriginalFilename();
				// 文件扩展名
				String fileExtName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
				// 文件流
				InputStream inputStream = file.getInputStream();
				XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, col1, 8, col1 + 4, 12);
				patriarch.createPicture(anchor, wb.addPicture(inputStream, XSSFWorkbook.PICTURE_TYPE_PNG));
				col1 = col1 + 2;
			}
           /* FileOutputStream fileOutputStream = new FileOutputStream("F://demo2.xlsx");
            workbook.write(fileOutputStream);*/
            OutputStream output = response.getOutputStream();
            response.reset();
            response.setHeader("Content-Type", "application/vnd.ms-excel;charset=UTF-8");
            response.setContentType("application/msexcel");
            response.setHeader("Content-disposition", "attachment; filename=" + "demo2.xlsx" );
            workbook.write(output);
            output.flush();
            output.close();
        }

没有啥难点介绍,就是前段传入的图片我们转成文件流在写入,这个逻辑相对不复杂易上手,主要的要主要: new XSSFClientAnchor(0, 0, 0, 0, col1, 0, col1+2, 4); 这个是处理图片位置和大小的。

图片加数据两者合起来的样子就是

XSSFCell cell = row.createCell(0);
		Integer count = 0;
		for (Integer courseId : courseIds) {
			for (int j = 0; j < heads.length; j++) {
				row = sheet.getRow(1);
				if (null == row) {
					//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
					//否则会出现空指针异常
					row = sheet.createRow(1);
				}
				cell = row.createCell(count + j);
				cell.setCellValue(heads[j]);
				cell.setCellStyle(style);
			}
			List<PlanImgExcelVO> list = collect.get(courseId);
			for (int i = 0; i < list.size(); i++) {
				PlanImgExcelVO vo = list.get(i);
				if (!VerifyUtil.isEmpty(vo.getAimName())) {
					row = sheet.getRow(0);
					cell = row.createCell(count + 0);
					cell.setCellValue(vo.getAimName());
					cell.setCellStyle(style);
				}
				row = sheet.getRow(i + 2);
				if (null == row) {
					//如果不做空判断,你必须让你的模板文件画好边框,beginRow和beginCell必须在边框最大值以内
					//否则会出现空指针异常
					row = sheet.createRow(i + 2);
				}
				cell = row.createCell(count + 0);
				cell.setCellValue(vo.getFinishDate());
				cell.setCellStyle(style1);

				cell = row.createCell(count + 1);
				cell.setCellValue(vo.getPlanNum());
				cell.setCellStyle(style1);

				cell = row.createCell(count + 2);
				cell.setCellValue(vo.getFinishNum());
				cell.setCellStyle(style1);


			}
			CellRangeAddress region = new CellRangeAddress(0, 0, count + 0, count + 2);
			sheet.addMergedRegion(region);
			count += 4;
		}
		if (!VerifyUtil.isEmpty(multipartfiles)) {

			//先把读进来的图片放到一个ByteArrayOutputStream中,以便产生ByteArray
			ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
			// String imageUrlHead = PropertiesUtils.getProperty("IMAGE_URL_HEAD");

			//画图的顶级管理器,一个sheet只能获取一个(一定要注意这点)
			XSSFDrawing patriarch = sheet.createDrawingPatriarch();
			//anchor主要用于设置图片的属性
       /* XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) 2, 2, (short) 4, 4);
        anchor.setAnchorType(ClientAnchor.MOVE_AND_RESIZE);*/
			Integer col1 = 0;
			for (MultipartFile file : multipartfiles) {
				Map<String, Object> map = new HashMap<String, Object>();
				// 文件名
				String originalFilename = file.getOriginalFilename();
				// 文件扩展名
				String fileExtName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
				// 文件流
				InputStream inputStream = file.getInputStream();
				BufferedImage bufferedImage = ImageIO.read(inputStream);
				ImageIO.write(bufferedImage, fileExtName, byteArrayOut);

				XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, col1, 8, col1 + 4, 12);
				anchor.setAnchorType(ClientAnchor.MOVE_AND_RESIZE);
				col1 = col1 + 2;
				//插入图片
				patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_JPEG));
			}
		}

	}

这个就不介绍了。就这样了

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值