赞
踩
提示:其实使用EasyExcel根据模板导出一个excel并不难,难点在于指定图片的位置
提示:EasyExcel请使用 3.0 以上版本,我这里使用的是 3.0.2 版本:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.2</version>
</dependency>
提示:我的需求是,前端页面有个 echarts 图,需要导出到excel,当然前端也可以直接导出图片;但是我是需要将图片插入到模板指定位置,模板中还有其他内容,所以需要前端先将图片传给我,后台再写入到模板中
@ApiOperation(value = "导出excel")
@PostMapping("/export")
public void exportExcel(@RequestParam("file") MultipartFile file, HttpServletResponse response, @Valid FwFloodForecastResultExportDto dto) {
service.export(file, response, dto);
}
ResourceUtil工具类使用的是开源的java工具包cn.hutool,具体的pom中的maven依赖坐标,自行百度
Map<String, Object> map = new HashMap<>(); map.put("startW", 33); map.put("avgRain", 35); map.put("pa", 36); map.put("forecastTime", "12月10日12时03分"); map.put("maxFlow", 37); map.put("maxFlowTime", "11月27日20时"); map.put("maxOtq", 38); map.put("maxOtqTime", "11月29日2时"); map.put("maxW", 39); map.put("maxWTime", "11月27日20时"); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> m1 = new HashMap<>(); m1.put("month", "11"); m1.put("day", "3"); m1.put("hour", "10"); m1.put("rain", 40); m1.put("inq", 41); m1.put("otq", 42); Map<String, Object> m2 = new HashMap<>(); m2.put("month", "12"); m2.put("day", "3"); m2.put("hour", "10"); m2.put("rain", 40); m2.put("inq", 41); m2.put("otq", 42); Map<String, Object> m3 = new HashMap<>(); m3.put("month", "1"); m3.put("day", "3"); m3.put("hour", "10"); m3.put("rain", 40); m3.put("inq", 41); m3.put("otq", 42); Map<String, Object> m4 = new HashMap<>(); m4.put("month", "2"); m4.put("day", "3"); m4.put("hour", "10"); m4.put("rain", 40); m4.put("inq", 41); m4.put("otq", 42); Map<String, Object> m5 = new HashMap<>(); m5.put("month", "3"); m5.put("day", "3"); m5.put("hour", "10"); m5.put("rain", 40); m5.put("inq", 41); m5.put("otq", 42); list.add(m1); list.add(m2); list.add(m3); list.add(m4); list.add(m5); InputStream is = null; // 取出模板 try { is = ResourceUtil.getStream("classpath:templates/forecastTemp.xlsx"); // 这里定义最终导出的文件名称 String fileName = "xxxx.xlsx"; // 这里的 file 就是 Controller 中传过来的 MultipartFile 文件对象;TemplateExcelUtils.imageCells()里面有图片的一些参数,可以根据自己需要调整图片的起始位置,边框等 WriteCellData<Void> voidWriteCellData = TemplateExcelUtils.imageCells(file.getBytes()); // 这个 img 就是你在模板中文件图片所在位置的占位符 ,需要提前在模板中定义好 => {img} map.put("img", voidWriteCellData); ExcelWriter excelWriter = EasyExcel.write(TemplateExcelUtils.getOutputStream(fileName, response)).withTemplate(is).excelType(ExcelTypeEnum.XLSX).build(); WriteSheet writeSheet = EasyExcel.writerSheet().build(); // 这个传进去的 map 就是非表格数据,详见我定义的模板中图片位置上方那部分 excelWriter.fill(map, writeSheet); // 这个 data 是官方约定就这么写, 传进去的 list 就是要遍历的表格数据,详见我定义的模板中图片位置右侧那部分 excelWriter.fill(new FillWrapper("data", list), writeSheet); excelWriter.finish(); } catch (Exception e) { e.printStackTrace(); } finally { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } }
代码如下(示例):
package com.jxstjh.xjwpsm.forecastWarning.app.utils; import com.alibaba.excel.metadata.data.ImageData; import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.util.FileUtils; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; /** * @version 1.0 * @date 2022-12-11 18:00 */ public class TemplateExcelUtils { /** * Excel所有图片设置 * * @param bytes * @return * @throws IOException */ public static WriteCellData<Void> imageCells(byte[] bytes) throws IOException { WriteCellData<Void> writeCellData = new WriteCellData<>(); // 这里可以设置为 EMPTY 则代表不需要其他数据了 //writeCellData.setType(CellDataTypeEnum.EMPTY); // 可以放入多个图片 List<ImageData> imageDataList = new ArrayList<>(); writeCellData.setImageDataList(imageDataList); ImageData imageData = new ImageData(); imageDataList.add(imageData); // 设置图片 imageData.setImage(bytes); // 图片类型 //imageData.setImageType(ImageData.ImageType.PICTURE_TYPE_PNG); // 上 右 下 左 需要留空,这个类似于 css 的 margin;这里实测 不能设置太大 超过单元格原始大小后 打开会提示修复。暂时未找到很好的解法。 imageData.setTop(10); imageData.setRight(10); imageData.setBottom(10); imageData.setLeft(10); // * 设置图片的位置。Relative表示相对于当前的单元格index。first是左上点,last是对角线的右下点,这样确定一个图片的位置和大小。 // 目前填充模板的图片变量是images,index:row=7,column=0。所有图片都基于此位置来设置相对位置 // 第1张图片相对位置 imageData.setRelativeFirstRowIndex(0); imageData.setRelativeFirstColumnIndex(0); imageData.setRelativeLastRowIndex(20); imageData.setRelativeLastColumnIndex(5); return writeCellData; } /** * 导出文件时为Writer生成OutputStream. * * @param fileName 文件名 * @param response response * @return "" */ public static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception { try { fileName = URLEncoder.encode(fileName, "UTF-8"); response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("utf8"); response.setHeader("Content-Disposition", "attachment; filename=" + fileName); response.setHeader("Pragma", "public"); response.setHeader("Cache-Control", "no-store"); response.addHeader("Cache-Control", "max-age=0"); return response.getOutputStream(); } catch (IOException e) { throw new Exception("导出excel表格失败!", e); } } }
提示:对图片操作最重要的类就是 WriteCellData<Void> 如果你的easyexcel没有这个类,说明你的版本太低,请升级到3.0以上:
如果有多张图片需要指定位置的请参考这里:请点击这里
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。