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

最近接收了一个做数据报表的一个系统,一堆奇葩的需求。数据报表嘛,都会涉及数据导出各式各样的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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 可以使用Excel的“宏”功能来实现单元格的行合并和合并,具体操作步骤如下:1)打开“开发”选项卡,点击“宏”;2)在宏窗口中输入宏名称,并单击“创建”按钮;3)将以下代码复制并粘贴到宏窗口中:Sub MergeRowColumn ()Dim rng As RangeDim InputRng As RangeDim WorkRng As RangexTitleId = "KutoolsforExcel"Set InputRng = Application.SelectionSet InputRng = Application.InputBox("Range", xTitleId, InputRng.Address, Type:=8)Set WorkRng = Application.InputBox("Range", xTitleId, Type:=8)For Each rng In WorkRngIf rng.Columns.Count >= rng.Rows.Count Thenrng.Columns.MergeElserng.Rows.MergeEnd IfNextEnd Sub4)单击“运行”按钮,然后选择要合并的单元格范围,即可实现单元格的行合并和合并。 ### 回答2: 基于poi导出数据时,可以使用下面的方法来实现单元格的行合并和合并。 对于行合并,我们可以使用`sheet.addMergedRegion()`方法。该方法接收四个参数,分别是起始行、结束行、起始和结束。 ```java // 合并第一行的1到3 sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 2)); ``` 对于合并,我们可以使用`sheet.addMergedRegion()`方法。但需要注意的是,poi默认是按照行来合并单元格的,因此要实现合并需要将合并的单元格依次移到行后面的位置。 ```java // 合并第一的1到3行(实现合并) for (int i = 0; i < 3; i++) { sheet.addMergedRegion(new CellRangeAddress(i, i, 0, 0)); // 移动单元格 sheet.shiftRows(i + 1, sheet.getLastRowNum(), 1, true, false); } ``` 以上是基于poi导出数据实现单元格的行合并和合并的方法。可以根据具体需求调整起始行、结束行、起始和结束的值,来实现更灵活的合并操作。 ### 回答3: 在使用Apache POI导出数据时,可以通过设置单元格的合并来实现行合并和合并的功能。以下是实现这两种合并的基本步骤: 对于行合并: 1. 首先,在创建或获取单元格时,使用 Sheet 对象的 createRow() 方法创建行对象,并使用 Row 对象的 createCell() 方法创建单元格对象。 2. 在某些行中,你可以通过设置相应的单元格值来标示它们要被合并。例如,你可以使用 cell.setCellValue("合并行")。 3. 选取第一个要合并的单元格,使用 CellRangeAddress 对象指定要合并的行范围,然后使用 Sheet 对象的 addMergedRegion() 方法进行行合并。例如,使用 sheet.addMergedRegion(new CellRangeAddress(0, 3, 0, 0)) 将第一的前四行合并。 4. 最后,使用 FileOutputStream 对象保存工作簿,并将数据导出到文件中。例如,使用 FileOutputStream 对象的 write() 方法将工作簿写入到指定的文件。 对于合并: 1. 首先,创建或获取单元格对象,并设置相应的单元格值。 2. 使用 Sheet 对象的 addMergedRegion() 方法指定要合并的范围。例如,使用 sheet.addMergedRegion(new CellRangeAddress(0, 0, 1, 3)) 将第一行的第二到第四合并。 3. 最后,使用 FileOutputStream 对象保存工作簿,并将数据导出到文件中。例如,使用 FileOutputStream 对象的 write() 方法将工作簿写入到指定的文件。 以上是基于Apache POI实现行合并和合并的基本步骤。根据需要,你可以根据上述步骤进行扩展和自定义,以满足特定的数据导出需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值