使用EasyExcel根据模板导出excel,包含图片、表格
提示:其实使用EasyExcel根据模板导出一个excel并不难,难点在于指定图片的位置
文章目录
使用EasyExcel根据模板导出excel,包含图片、表格前言一、Controller二、ServiceImpl三、TemplateExcelUtils四、xlsx模板路径五、模板内容制作六、导出内容展示总结前言
提示:EasyExcel请使用 3.0 以上版本,我这里使用的是 3.0.2 版本:
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.2</version></dependency>
提示:我的需求是,前端页面有个 echarts 图,需要导出到excel,当然前端也可以直接导出图片;但是我是需要将图片插入到模板指定位置,模板中还有其他内容,所以需要前端先将图片传给我,后台再写入到模板中
一、Controller
@ApiOperation(value = "导出excel")@PostMapping("/export")public void exportExcel(@RequestParam("file") MultipartFile file, HttpServletResponse response, @Valid FwFloodForecastResultExportDto dto) {service.export(file, response, dto);}
二、ServiceImpl
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();}}}
三、TemplateExcelUtils
代码如下(示例):
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 .URLEncoder;import java.util.ArrayList;import java.util.List;/*** @version 1.0* @date -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);}}}
四、xlsx模板路径
五、模板内容制作
六、导出内容展示
总结
提示:对图片操作最重要的类就是 WriteCellData<Void> 如果你的easyexcel没有这个类,说明你的版本太低,请升级到3.0以上:
如果有多张图片需要指定位置的请参考这里:请点击这里