前言: 

需求:根据自定义模板导出Excel,包含图片、表格,采用EasyExcel

提示:EasyExcel请使用 3.0 以上版本,

对图片操作最重要的类就是 WriteCellData<Void> 如果你的easyexcel没有这个类,说明你的版本太低,请升级到3.0以上

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.2.1</version>
</dependency>

实际代码:

Controller

@ApiOperation("excel导出详情")
@PostMapping("excelExport")
public void excelExport(HttpServletResponse response,
@ApiParam("id {\"id\":\"xxx\"}") @RequestBody Map<String, String> data) {
ExcelUitl.templateExport(response, researcherInformationService
.getDetail(data.get("id")));
}

ServiceImpl

public static String templateExport(HttpServletResponse response,ResearchDetailVo researchDetailVo) {
InputStream is = null;
try {
// 取出模板
is = ResourceUtil.getStream("classpath:templates/survey.xlsx");
Map<String, Object> map = new HashMap<>(10);
map.put("goOutDate", researchDetailVo.getGoOutDate());
map.put("userName", researchDetailVo.getUserName());
map.put("visitPlace", researchDetailVo.getVisitPlace());
map.put("marketTrends", researchDetailVo.getMarketTrends());
map.put("marketEnvironment", researchDetailVo.getMarketEnvironment());
map.put("partnerTrends", researchDetailVo.getPartnerTrends());
map.put("companyStatus", researchDetailVo.getCompanyStatus());
map.put("marketCompetition", researchDetailVo.getMarketCompetition());
map.put("feedback", researchDetailVo.getFeedback()); // 文件名称
String fileName = researchDetailVo.getUserName() + researchDetailVo.getGoOutDate()
+ "调研反馈信息表"; if (!ObjectUtils.isEmpty(researchDetailVo.getUrl())) {
//图片url转换为MultipartFile对象
// getUrl 是 List<String>
MultipartFile[] files = downloadImages(researchDetailVo.getUrl());
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
// 图像设置处理
WriteCellData<Void> voidWriteCellData = imageCells(file.getBytes());
map.put("img" + (i + 1), voidWriteCellData);
}
} ExcelWriter excelWriter = EasyExcel.write(getOutputStream(fileName, response)).withTemplate(is).excelType(ExcelTypeEnum.XLSX).build();
WriteSheet writeSheet = EasyExcel.writerSheet().build();
excelWriter.fill(map, writeSheet);
excelWriter.finish();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
} public static WriteCellData<Void> imageCells(byte[] bytes) throws IOException { WriteCellData<Void> writeCellData = new WriteCellData<>(); // 可以放入多个图片
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=CELL_COUNT,column=0。所有图片都基于此位置来设置相对位置
// 第1张图片相对位置
imageData.setRelativeFirstRowIndex(0);
imageData.setRelativeFirstColumnIndex(0);
imageData.setRelativeLastRowIndex(0);
imageData.setRelativeLastColumnIndex(0); return writeCellData;
} ///为什么用线程池去实现 原因:当时项目文件储存用的是minio,由于服务器宽带非常低,导致几百K的图片都需要很久,多图片需要加载资源很久
public static MultipartFile[] downloadImages(List<String> imageUrls) {
// 创建一个固定大小的线程池
int poolSize = 5;
ThreadPoolExecutor executor = new ThreadPoolExecutor(poolSize, poolSize,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
MultipartFile[] files = new MultipartFile[imageUrls.size()]; for (int i = 0; i < imageUrls.size(); i++) {
final int index = i;
executor.submit(() -> {
try {
files[index] = convert(imageUrls.get(index));
} catch (IOException e) {
e.printStackTrace();
}
});
} executor.shutdown(); // 关闭线程池 // 等待所有任务执行完成
while (!executor.isTerminated()) {
// 等待
} return files;
} /**
* 图片地址转换为MultipartFile文件
*
* @param imageUrl
* @return
* @throws IOException
*/
public static MultipartFile convert(String imageUrl) throws IOException {
// 将在线图片地址转换为URL对象
URL url = new URL(imageUrl);
// 打开URL连接 转换为HttpURLConnection对象
URLConnection connection = url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
// 获取输入流 并读取输入流中的数据,并保存到字节数组中
InputStream inputStream = httpURLConnection.getInputStream();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
}
byte[] bytes = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
return new MockMultipartFile("file", "filename.jpg", "image/jpeg", byteArrayInputStream);
}

xlsx模板位置

xlsx模板内容

导出内容展示

java-EasyExcel模板导出的更多相关文章

  1. java根据模板导出PDF详细教程

    原文:https://blog.csdn.net/pengyufight/article/details/75305128 题记:由于业务的需要,需要根据模板定制pdf文档,经测试根据模板导出word ...

  2. Java按模板导出Excel———基于Aspose实现

    目录 开发环境 先看效果 引入jar包 校验许可证 导出方法 测试结果 占位符 开发环境 jdk 1.8 Maven 3.6 SpringBoot 2.1.4.RELEASE aspose-cells ...

  3. Java无模板导出Excel,Apache-POI插件实现

    开发环境 jdk 1.8 Maven 3.6 Tomcat 8.5 SpringBoot 2.1.4.RELEASE Apache-POI 3.6 Idea 注意: 我是在现有的基于SpringBoo ...

  4. java根据模板导出PDF(利用itext)

    一.制作模板     1.下载Adobe Acrobat 9 Pro软件(pdf编辑器),制作模板必须使用该工具. 2.下载itextpdf-5.5.5.jar.itext-asian-5.2.0.j ...

  5. 关于Java中excel表格导出的总结(Java程序导出模板和Java根据模板导出表格两种实现方式)

    导出excel通用模板(程序定义模板导出) 转载原文:https://www.jianshu.com/p/5c7b359a159c 如下代码,本方法主要用于程序定义模板格式,并导出文件.该方法将定义和 ...

  6. Java 根据模板导出PDF

    目录 前言 思路一:直接导出pdf 使用itext模板导出pdf 思路二:先导出word再转成pdf 1)导出word 2)word转pdf 最终方案 docx4j spire.doc.free + ...

  7. java根据模板导出pdf

    在网上看了一些Java生成pdf文件的,写的有点乱,有的不支持写入中文字体,有的不支持模板,有的只是随便把数据放里面生成文件,完全不考虑数据怎样放置的以及以后的维护性,想想还是自己总结一个完全版的导出 ...

  8. java五行代码导出Excel

    目录 先看代码 再看效果 EasyExcel 附: Java按模板导出Excel---基于Aspose实现 Java无模板导出Excel,Apache-POI插件实现 已经写过两种Excel导出插件了 ...

  9. java使用jxls导出Excel

    jxls是基于POI的Excel模板导出导入框架.通过使用类似于jstl的标签,有效较少导出Excel的代码量. 1.pom <!-- https://mvnrepository.com/art ...

  10. java实现excel模板导出

    一. 准备工作 1. 点击此下载相关开发工具 2. 将poi-3.8.jxls-core-1.0两个jar包放到工程中,并引用 3. 将excel模板runRecord.xls放到RunRecordB ...

随机推荐

  1. P2024 [NOI2001] 食物链 || #576. 食物链【NOI2001】 (并查集)

    空降锣鼓 空降OJ 题解: #include<bits/stdc++.h> using namespace std; int n,k; int d,x,y; int ans; int fa ...

  2. legend的用法

    常规使用legend的方法 1. 自动检测 设置title的label标签,随后使用不带参数的legend函数也会自动显示(但不限于一种方式设置图形的label,只要设置了图形的label,使用leg ...

  3. 纯分享:将MySql的建表DDL转为PostgreSql的DDL

    背景 现在信创是搞得如火如荼,在这个浪潮下,数据库也是从之前熟悉的Mysql换到了某国产数据库. 该数据库我倒是想吐槽吐槽,它是基于Postgre 9.x的基础上改的,至于改了啥,我也没去详细了解,当 ...

  4. Solidity-变量和数据类型[基本类型]

    在solidity语言中,变量和数据类型分为三类:基本类型(bool.int.address等),复合类型(array.struct.mapping等)和特殊类型(enum.function.modi ...

  5. 利用SPI实现全自动化——LCD屏与RGB灯

    如果你开启了广告屏蔽,请将博客园加入白名单,帮助博客园渡过难关,谢谢! 前言 在21年做物理实验和23年客串电赛之后,我带着STM32重回电子DIY界.这次的项目是一个电池供电的补光灯,由于用途更偏向 ...

  6. Oracle-判断表上存在高水位线

    表上高水位线:通常一个新建的表,1个8K的数据块存放100行记录,若表上经常插入删除操作,造成表的水位线很高.下面从发现高水位线的办法,及解决高水位的方法说起: 1.发现存在高水位线的表:查看字典表u ...

  7. Springboot实现注解判断权限

    Springboot实现注解判断权限 今天记录一下使用springboot的注解来给方法加权限 避免了每个方法都需要大量的权限判断 超级好用√ @ 目录 Springboot实现注解判断权限 1.创建 ...

  8. java数组的定义和使用规范

    java数组 三种定义方式 1.数组类型[] 数组名字 = new 数组类型[数组长度] String[] str = new String[n]; //这里n代表数组的长度可变 //另外上面这种写法 ...

  9. .Net7自定义GC垃圾回收器

    1.前言 CLR和GC高度耦合,.Net7里面分离CLR和GC,则比较容易实现这件事情.本篇来看下,自定义一个GC垃圾回收器. 2.概述 这里首先演示下自定义GC垃圾回收后的效果. 1.下载Custo ...

  10. 43道Python经典案例题(有答案)

    1.有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? for x in range(0,5): for y in range(0,5): for z in range( ...