-
2022-05-21 11:40:28
这里导出excel需要使用阿里的EasyExcel组件,项目需要引入EasyExcel依赖,版本可自己选择,博主这里使用2.2.7版本
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.7</version> </dependency>
说到多图片导出,先要说下EasyExel的单图片导出,单图片导出比较简单,
直接使用下EasyExel自带的类UrlImageConverter(Converter的子类)实现,ExcelModel设置如下:@Data @ContentRowHeight(20) @HeadRowHeight(20) @ColumnWidth(25) @HeadStyle(horizontalAlignment = HorizontalAlignment.CENTER) @ContentStyle(horizontalAlignment = HorizontalAlignment.CENTER) public class ExcelDemo { @ExcelProperty(value = "图片", converter = UrlImageConverter.class) private URL imageUrl; }
我们先来看一下UrlImageConverter的实现:
package com.alibaba.excel.converters.url; import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.IoUtils; import java.io.IOException; import java.io.InputStream; import java.net.URL; public class UrlImageConverter implements Converter<URL> { public UrlImageConverter() { } public Class supportJavaTypeKey() { return URL.class; } public CellDataTypeEnum supportExcelTypeKey() { return CellDataTypeEnum.IMAGE; } public URL convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { throw new UnsupportedOperationException("Cannot convert images to url."); } // 核心方法 读取图片url的io流 public CellData convertToExcelData(URL value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws IOException { InputStream inputStream = null; CellData var6; try { inputStream = value.openStream(); byte[] bytes = IoUtils.toByteArray(inputStream); var6 = new CellData(bytes); } finally { if (inputStream != null) { inputStream.close(); } } return var6; } }
其实转化的方法很简单,只是读取图片url的io,写进Excel的cellData对象里,那多图片的转化只需要加个for循环一次读取转化就行里吧?我们来自己实现下多图片的转换器(实现easyexcel的扩展接口Converter)
import com.alibaba.excel.converters.Converter; import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.GlobalConfiguration; import com.alibaba.excel.metadata.property.ExcelContentProperty; import com.alibaba.excel.util.IoUtils; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * @Description: easyecxel多图片导出到单元格转换工具类 * @Author guowang * @Date: 2021/7/7 15:56 * @Version 1.0 */ public class ListUrlConverterUtil implements Converter<List<URL>> { @Override public Class supportJavaTypeKey() { return List.class; } @Override public CellDataTypeEnum supportExcelTypeKey() { /** *这里记得枚举类型为IMAGE */ return CellDataTypeEnum.IMAGE; } @Override public List convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { return null; } @Override public CellData convertToExcelData(List<URL> value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception { // 这里进行对数据实体类URL集合处理 List<CellData> data = new ArrayList<>(); // for 循环一次读取 for (URL url : value) { InputStream inputStream = null; try { inputStream = url.openStream(); byte[] bytes = IoUtils.toByteArray(inputStream); data.add(new CellData(bytes)); } catch (Exception e) { throw new IOException("导出excel图片读取异常"); } finally { if (inputStream != null){ inputStream.close(); } } } // 这种方式并不能返回一个List,所以只好通过CellData cellData = new CellData(data);将这个list对象塞到返回值CellData对象的data属性中; CellData cellData = new CellData(data); cellData.setType(CellDataTypeEnum.IMAGE); return cellData; } }
ExcelModel设置如下:
@Data @ContentRowHeight(20) @HeadRowHeight(20) @ColumnWidth(25) @HeadStyle(horizontalAlignment = HorizontalAlignment.CENTER) @ContentStyle(horizontalAlignment = HorizontalAlignment.CENTER) public class ExcelDemo { @ExcelProperty(value = "图片", converter = ListUrlConverterUtil.class) private List<URL> imageUrls; }
图片统一大小返回, 这里需要实现CellWriteHandler 的afterCellDataConverted 方法,将 CellData 的 type 设置成 EMPTY ,这样 EasyExcel 不会帮忙填充该单元格的数据,然后实现 CellWriteHandler 的 afterCellDispose 方法,将图片信息填充上去
注意:每列的单元格图片张数不确定,单元格宽度需按照张数最多的长度来设置
import com.alibaba.excel.enums.CellDataTypeEnum; import com.alibaba.excel.metadata.CellData; import com.alibaba.excel.metadata.Head; import com.alibaba.excel.write.handler.CellWriteHandler; import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; import com.alibaba.excel.write.metadata.holder.WriteTableHolder; import org.apache.commons.collections.CollectionUtils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.ss.usermodel.*; import org.apache.poi.util.Units; import java.util.ArrayList; import java.util.List; /** * @Description: 图片信息修改拦截器 * @Author GreenArrow * @Date: 2021/7/7 16:05 * @Version 1.0 */ public class CustomImageModifyHandler implements CellWriteHandler { private List<String> repeats = new ArrayList<>(); // 单元格的图片最大张数(每列的单元格图片张数不确定,单元格宽度需按照张数最多的长度来设置) private Integer maxDataSize = 0; @Override public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) { } @Override public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { } @Override public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, CellData cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { // 在 数据转换成功后 不是头就把类型设置成空 if (isHead) { return; } //将要插入图片的单元格的type设置为空,下面再填充图片 if(cellData.getImageValue()!=null||cellData.getData() instanceof ArrayList){ cellData.setType(CellDataTypeEnum.EMPTY); } } @Override public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) { // 在 单元格写入完毕后 ,自己填充图片 if (isHead || CollectionUtils.isEmpty(cellDataList)) { return; } Boolean listFlag = false; ArrayList data = null; Sheet sheet = cell.getSheet(); // 此处为ListUrlConverterUtil的返回值 if (cellDataList.get(0).getData() instanceof ArrayList){ data = (ArrayList) cellDataList.get(0).getData(); if (CollectionUtils.isEmpty(data)) { return; } if (data.get(0) instanceof CellData){ CellData cellData = (CellData) data.get(0); if (cellData.getImageValue() == null){ return; }else { listFlag = true; } } } if (!listFlag && cellDataList.get(0).getImageValue() == null){ return; } String key = cell.getRowIndex() + "_" + cell.getColumnIndex(); if (repeats.contains(key)){ return; } repeats.add(key); if (data.size() > maxDataSize) { maxDataSize = data.size(); } // 默认要导出的图片大小为175*175px,175px的行高大约是900,175px列宽大概是25*256 sheet.getRow(cell.getRowIndex()).setHeight((short)1800); sheet.setColumnWidth(cell.getColumnIndex(),listFlag?25*256*maxDataSize:25*256); if (listFlag){ for (int i = 0; i < data.size(); i++) { CellData cellData= (CellData) data.get(i); if(cellData.getImageValue()==null){ continue; } this.insertImage(sheet,cell,cellData.getImageValue(),i); } }else { // cellDataList 是list的原因是 填充的情况下 可能会多个写到一个单元格 但是如果普通写入 一定只有一个 this.insertImage(sheet,cell,cellDataList.get(0).getImageValue(),0); } } private void insertImage(Sheet sheet,Cell cell,byte[] pictureData,int i){ int picWidth = Units.pixelToEMU(175); int index = sheet.getWorkbook().addPicture(pictureData, HSSFWorkbook.PICTURE_TYPE_PNG); Drawing drawing = sheet.getDrawingPatriarch(); if (drawing == null) { drawing = sheet.createDrawingPatriarch(); } CreationHelper helper = sheet.getWorkbook().getCreationHelper(); ClientAnchor anchor = helper.createClientAnchor(); // 设置图片坐标 anchor.setDx1(picWidth*i); anchor.setDx2(picWidth+picWidth*i); anchor.setDy1(0); anchor.setDy2(0); //设置图片位置 anchor.setCol1(cell.getColumnIndex()); anchor.setCol2(cell.getColumnIndex()); anchor.setRow1(cell.getRowIndex()); anchor.setRow2(cell.getRowIndex() + 1); // 设置图片可以随着单元格移动 anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE); drawing.createPicture(anchor, index); } }
使用EasyExcel的write方法将数据写到excel中,这里比较重要的是需要.registerWriteHandler,这里需要将自己写的图片拦截器注入进去
EasyExcel.write(outputStream, ExcelDemo.class) .registerWriteHandler(new CustomImageModifyHandler()).sheet().doWrite(查询出来并且完成数据转换的Excel数据集合)
导出的excel图片结果如下(博主这里每列的图片张数不固定,单元格宽度按张数最多的那一列长度设置):
更多相关内容 -
C#插入图片到Excel表格单元格代码详解
2020-12-31 19:37:19dll文件获取及引用: 方法1:通过官网下载dll文件包,并解压。解压文件后,将bin文件夹下的Spire.Xls.dll文件引用到C#程序。 方法2:通过Nuget网站获取dll。 C#代码示例 using Spire.Xls; using System.Drawing;... -
导出Excel多个单元格合并及图片插入
2018-01-17 19:38:08一般在导出Excel中,在创建工作表sheet后,初始化的sheet中row都是一行一行的,每个单元格都是最小单位,所以问题1什么时候将单元格合并? 方案:先将数据组装成json格式方便插入Excel时进行遍历,接着以巡检项为每... -
Excel设置图片固定在某个单元格内部
2020-07-06 19:27:32锁定纵横比的,我没有设置锁定,锁定的意思是长宽改变一个,另一个会按照原图比例改变,最下面那个随单元格改变位置和大小等于锁定在那个位置上,你在上方插入一个单元格的话,那个图和它所在单元格位置不变,比如:... -
Excel - 单元格内插入图片,并随单元格变动
2021-07-08 13:33:51文章目录1)插入图片 放到单元格内2)选择大小和属性a) 不随单元格改变位置和大小效果如下:b) 随单元格改变位置,但不改变大小效果如下: 当插入图片后,有时发现在图片上方插入几行后,图片没有跟随之前的单元格动... -
freemarker 生成word,支持一个单元格生成多张图片
2017-05-24 00:10:17freemarker 生成word,支持一个单元格生成多张图片 -
poi实现在同一个单元格插入多个图片
2018-12-05 05:12:55Java导出excel如何使用poi实现在同一个单元格插入多个图片 -
poi导出Excel多张图片导出到一个单元格实现
2019-06-17 12:06:29今天做导出Excel的时候遇到了一个单元格中需要导出多张图片的需求。之前也做过很多的导出Excel,在网上研究了很久,总算导出成功了,但是还是有一点点的小瑕疵,就是根据图片的缩略图计算出单元格的宽高。希望有做过...今天做导出Excel的时候遇到了一个单元格中需要导出多张图片的需求。之前也做过很多的导出Excel,在网上研究了很久,总算导出成功了,但是还是有一点点的小瑕疵,就是根据图片的缩略图计算出单元格的宽高。希望有做过的能告知。需求大概是下面这样的。一个单元格最多能放三张图片。在项目得后期过程中也遇到了很多得问题,比如随着项目中数据得增多,因为每一条都会有截图,所以导致Excel非常得缓慢,以及数据量比较得大对POI小朋友进行了升级使用了SxxfWorkbook,还有就是ImageIo.read()会出现异常。
1.解决思路。目前数据量非常得大然后因为每个里面都会又对应得FileMd5加密得图片,这个目前还没有比较好得解决办法。
(控制用户那边得导出得数量)
对于数据量大,截图多得时候,采用得异步得形式去生成Excel。生成成功会往数据库里写入一条数据,或者发送一个邮件,或发送一条消息,或短信等。通过WebSocket实现服务端生成成功给前端发送一条消息,前端接收到数据调用下载Excel得形式。
最开始也是使用得Aajx 定时器得形式去轮询,但是这种形式每次轮询得时间不太好把握,其次就是占用得资源比较得大。
第一步 导入poi相应的jar
1.导入相应的poi 对应的jar 你们自行去找相关文档,这里不做重点。
第二步 编写测试类,关键代码如下
// 起始行, 终止行, 起始列, 终止列
CellRangeAddress cra =new CellRangeAddress(i+2, i+2, 2, 4);
//设置列宽
sheet.setColumnWidth((short) i, (short) (24 * 256));
//跨行跨列边框线
CellRangeAddress cra =new CellRangeAddress(i+2, i+2, 2, 4); sheet.addMergedRegion(cra); RegionUtil.setBorderBottom(1,cra,sheet,wb); // 下边框 RegionUtil.setBorderLeft(1, cra, sheet,wb); // 左边框 RegionUtil.setBorderRight(1, cra, sheet,wb); // 有边框 RegionUtil.setBorderTop(1, cra, sheet,wb); // 上边框 fillRowValues(i,row, dataMap, columns,sheet, csData,wb);
//设置标题头部字体区域的大小 HSSFRichTextString textString = new HSSFRichTextString(headName);
//设置标题头部字体区域的大小 HSSFRichTextString textString = new HSSFRichTextString(headName); Font font = wb.createFont(); font.setFontName("微软雅黑"); font.setFontHeightInPoints((short) 14); Font font1 = wb.createFont(); font1.setFontName("微软雅黑"); font1.setFontHeightInPoints((short) 12); textString.applyFont(0,7,font); textString.applyFont(7,headName.length(),font1);// 创建两种单元格格式 CellStyle csTitle = wb.createCellStyle(); csTitle.setAlignment(HSSFCellStyle.ALIGN_CENTER); csTitle.setVerticalAlignment(HSSFCellStyle.ALIGN_CENTER); csTitle.setWrapText(true);
说明:在项目得最初得时候数据没有那么大所以还是使用得03版本得HssfWorkbook,并且ImageIo.read()读取截图得时候有时候图片转入PNG得时候会 出现异常,并且会导致整个Excel异常,所以为了防止读取异常,以及异常能进行继续执行处理。 public static void createPictureImage (int j, String filePathList, SXSSFSheet sheet, SXSSFWorkbook wb) { if (StringUtils.isEmpty(filePathList)) { return; } Drawing drawing = sheet.createDrawingPatriarch(); File file = new File(filePathList); if (file.exists()) { try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); FileInputStream inputStream = new FileInputStream(file)) { IOUtils.copy(inputStream, outputStream); XSSFClientAnchor anchor = new XSSFClientAnchor(30, 15, 0, 0, (short) (2), j, (short) (3), j + 1); drawing.createPicture(anchor, wb.addPicture(outputStream.toByteArray(), SXSSFWorkbook.PICTURE_TYPE_PNG)); outputStream.flush(); } catch (IOException e) { logger.error("截图写入失败;截图地址:filePath;",filePathList); } } }
public static boolean createPictureImage(int j,List<String> filePathList,Sheet sheet,Workbook wb){ try { ByteArrayOutputStream byteArrayOut; HSSFPatriarch patriarch = (HSSFPatriarch) sheet.createDrawingPatriarch(); for (int i = 0; i < filePathList.size(); i++) { byteArrayOut = new ByteArrayOutputStream(); //BufferedImage bufferImg = ImageIO.read(new File(filePathList.get(i))); //int height=bufferImg.getHeight(); //int width=bufferImg.getWidth(); ImageIO.write(bufferImg, "png", byteArrayOut); //30 15 0 0 代表上边距和左边距 j代表行 第一行有个标题 第二行是标题头 所以j+2开始 第一列是序号,第二列是位置,所以i+2开始 (i+2), j+2 这代表单元格的起始坐标 (short) (i+3), j+3 代表单元格终点坐标 HSSFClientAnchor anchor = new HSSFClientAnchor(30, 15, 0, 0, (short) (i+2), j+2, (short) (i+3), j+3); patriarch.createPicture(anchor, wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG)); byteArrayOut.flush(); } }catch (IOException e){ return false; } return true; }
主要理解
HSSFClientAnchor anchor = new HSSFClientAnchor(30, 15, 0, 0, (short) (i+2), j+2, (short) (i+3), j+3);
就是一个单元格的起始位置和终止位置 来确定你图片绘制的位置,i+2,j+2 就是你的单元格左边上部的位置 i+3,j+3 就是单元格右边下部的位置,从而两坐标确定你图片的一个区域大小,我这里是一个单元格就放一张图片,这个参数依据你的需求调整, 30 15 0 0 就是这个区域位置的一个偏移
-
Java导出excel如何使用poi实现在同一个单元格既可以插入文字也可以插入多个图片
2017-11-29 06:42:00 注意:是同一个单元格中插入多个图片和文字,而不是不同单元格。 -
table合并单元格与img图片铺满整个td的html
2020-09-28 06:29:38主要介绍了table合并单元格与img图片铺满整个td的html,需要的朋友可以参考下 -
单元格图片自动居中代码
2018-04-04 21:08:24excel中单元格所有图片自动居中代码。谢谢各位观众老爷的路过 -
Excel中让所有图片刚好适应单元格大小,或者让图片也支持排序
2021-12-08 11:49:41千百张图片瞬间对齐,对齐后的图片可以随单元格大小相应的变化,或者让图片也能参与排序 -
java poi 解析excel中单元格内的图片,多张图片按照先后顺序进行排序
2021-09-14 13:53:53需求描述:在excel中一个单元格内,依次从左往右放入多张图片,解析的时候,按照图片的前后 顺序进行解析; 思路: poi提供解析图片的方法,但是同一个单元格内的多张图片,先后顺序没有提供相关方法,查找资料后... -
excel VBA 图片自适应单元格 代码
2015-12-23 17:44:05图片自适应单元格代码 -
Apache POI 在Excel单元格嵌入图片
2021-11-09 14:49:30关键代码如下: ...// fileName为图片完整路径,例:C:\images\EDG.jpg InputStream is = new FileInputStream(fileName); byte[] bytes = IOUtils.toByteArray(is); // 这里根据实际需求选择图片类型 int p -
用VBA自动对齐所有单元格中的图片
2022-05-28 15:32:09可以在左上角,右上角,左下角,右下角,中间等几种对齐方式,循环操作工作表中所有单元格的图片。 -
如何实现图片填满单元格
2020-11-23 04:27:22大家可能经常需要在工作表单元格中插入图片,为了满足OCD领导的要求,图片一定要占满整个单元格, 录制宏得到的代码,会存在过度缩放的问题,不同比率图片需要进一步调整代码。 -
单元格用HTML显示图片
2021-06-12 10:23:403.1 准备数据准备 Base64 编码方式的图片数据,搜索在线图片转码工具上传图片进行转码即可。新建内置数据集Embedded1 ,输入通过工具转码得出的 Base64 形式的图片数据,如下图所示:注:FineReport 内置数据集对... -
Java将png、jpg、bmp等格式图片批量插入到Excel单个单元格内
2018-06-21 20:00:09最近做一个项目,需将多个图片(比如:jpg、bmp、png等图片格式)按实际大小插入同一个单元格,现把它记录下来,供大家参考。由于本人程序员猿一枚,而且处在初期堆砌代码阶段,如果程序有错误的地方,真诚希望大家... -
WPS表格如何实现单元格内粘贴图片
2020-09-11 15:26:25WPS要实现在单元格内粘贴图片有两种方法。 选中要插入图片的单元格,点击插入。 这样就可以把图片嵌入单元格了。 把复制的图片直接粘贴到单元格。 复制的图片在客户端可以直接粘贴到表格内,但是不能直接粘贴到... -
EXCEL表格图片随单元格变更.zip
2019-08-06 16:32:27EXCEL表格内的图片随单元格变更而变更,通常用在人员信息表上的照片或者EXCEL表格内有图片变更需求。 -
Winform在DataGridView中显示图片
2020-12-31 20:06:14首先,要添加图片列,绑定数据的时候会触发CellFormatting事件,在事件中取出图片路径,读取图片赋值给当前单元格。 private void dataGridview1_CellFormatting(object sender, ... -
EasyPOI模板导出图片存在合并单元格只填充一个单元格问题
2019-03-01 13:59:23重写...添加 createImageCell 方法 此方法保证在不设置宽高的情况下 图片会占满合并后的单元格 // // Source code recreated from a .class file by IntelliJ IDEA // (powered b... -
插入图片至单元格comment中
2018-05-20 18:03:51我们有时需要当鼠标移到某单元格内时,显示单元格对应的图片,此小程序可用。要求图片名称与单元格内容一致,方可插入。 -
如何在excel2019指定的单元格中插入图片
2021-01-15 11:23:321、选中一个想要放入的单元格,尽量拉的大一点。 2、把已插入的图拖到这个单元格内,大致调整一下大小,使其和单元格大小差不多。 3、选中图片右键 “ 大小和属性 ” 。 4、作如图设置,将属性选为 “ 随单元格改变... -
EPPLUS图片位置能定位到单元格,图片的大小与单元格列宽行高的0.5倍,图片在单元格内居中。
2019-02-16 17:58:24要用EPPLUS输出一个Excel文档,图片要求居中单元格内,大小是单元格 列宽行高的0.5倍。图片是浮动的,不能固定到某个单元格,但是代码能控制图片的位置,Excel列宽和行高单位是不一致的,思考过转换成像素, 代码... -
VUE+elementui组件在table-cell单元格中绘制微型echarts图
2020-12-28 17:58:33需求效果图示例 ...-在单元格中触发一个方法,传入当前的scope.row数据或者指定其他数据,并且传入 scope.$index 以及一个字符串便于识别当前是哪条数据的charts -在方法中绘制echarts** <div v -
Word表格单元格中放入图片,如何让图片充满整个单元格
2020-12-01 22:06:12原文链接 示例操作步骤如下: 1、首先打开duWORD文档,...6、再在该单元格中,单击鼠标右键选择”表格性“。 7、在弹出的对话框中打开右下方的”选项“。 8、小窗口中再将上下左右边距设置为0,并勾选”.. -
datagridview 一个单元格显示文字和图片
2015-10-21 14:00:48datagridview 一个单元格显示文字和图片 文字超出时显示... private void dgv_Test_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) {/**/ if (e.ColumnIndex >= 0 && e.RowIndex = 0)