前言: 

需求:根据自定义模板导出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. 【译】摇摆你的调试游戏:你需要知道的 Parallel Stack Window 小知识!

    在 Visual Studio 2022 17.6和17.7中,我们在 Parallel Stack 窗口中添加了大量新功能,可以将您的多线程调试提升到一个新的水平. 但是 Parallel Stac ...

  2. 让 GPT-4 给开源项目 GoPool Review 社区贡献者的 PR - 每天5分钟玩转 GPT 编程系列(5)

    目录 1. 嘚瑟一下 2. 言归正传 2.1 GoPool 的第一个 PR 2.2 祭出 GPT-4 2.3 问问 GPT-4 怎么看这个 PR 2.4 让 GPT-4 重构代码 3. 打完收工 1. ...

  3. [Arch小贴士]在这里记录一些自己使用的小技巧

    哈喽!Arch 目录 0x00 设置开机自启动软件 首先 最后 0x01 ASLR开关 0x00 设置开机自启动软件 首先 首先进入目录/usr/share/applications,找到你要的那个软 ...

  4. 网络请求-Android篇(Okhttp和Retrofit)

    一.OkHttp的介绍和基本用法 OkHttp是一个流行的开源Java和Android应用程序的HTTP客户端.它由Square Inc.开发,提供了一种简单高效的方式来进行应用程序中的HTTP请求. ...

  5. 《SQL与数据库基础》18. MySQL管理

    目录 MySQL管理 系统数据库 常用工具 mysql mysqladmin mysqlbinlog mysqlshow mysqldump mysqlimport source 本文以 MySQL ...

  6. MySQL系列2:InnoDB存储引擎

    1. 架构回顾 上一篇我们讲解了MySQL的逻辑架构,重新回顾一下,用一张新的图来认识一下该架构. 整体架构分为service层与存储引擎层,请求交给连接池后,由后台线程处理,并将请求转发给SQL接口 ...

  7. PYQT5学习(12)Qtabwidget 选项卡及其窗口,Qstackedwidget和Qtabwidget的效果类似,以及系统托盘QsystemtrayIcon

    参考博文:https://blog.csdn.net/jia666666/article/details/81669092QTabWidget控件提供一个选项卡和一个页面区域,默认显示第一个选项卡的页 ...

  8. SpringBoot WebSocket STOMP

    SpringBoot WebSocket STOMP 关键词:Springboot, WebSocket, STOMP, broadcast, sendToUser, MessageMapping, ...

  9. Go 基础之基本数据类型

    Go 基础之基本数据类型 目录 Go 基础之基本数据类型 一.整型 1.1 平台无关整型 1.1.1 基本概念 1.1.2 分类 有符号整型(int8~int64) 无符号整型(uint8~uint6 ...

  10. 调节LED的亮度

    虽然Devices Plus已经介绍过Arduino的多种应用和作品示例,但是了解相关基础知识对于任何项目的构建仍然是非常重要的!这次,我们将为您介绍Arduino电子制作的基础知识.此次的分享嘉宾是 ...