EasyExcel 單元格根據圖片數量動態設置寬度

在使用 EasyExcel 導出 Excel 時,如果某個單元格是圖片內容,且存在多張圖片,此時就需要單元格根據圖片數量動態設置寬度。
經過自己的研究和實驗,導出效果如下:
image.png
具體代碼如下:

  1. EasyExcel 版本
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.2</version>
</dependency>
  1. 定義Excel圖片鏈接轉換工具
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;
import com.alibaba.excel.util.IoUtils;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;/*** Excel圖片鏈接轉換工具** @author 天航星* @date 2024-07-05 15:03*/
public class ExcelImageUrlConverterUtils implements Converter<List<String>> {@Overridepublic CellDataTypeEnum supportExcelTypeKey() {return CellDataTypeEnum.STRING;}@Overridepublic WriteCellData<?> convertToExcelData(List<String> value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {List<ImageData> imageDataList = new ArrayList<>();for (String url : value) {try {URL imageUrl = new URL(url);byte[] bytes = IoUtils.toByteArray(imageUrl.openConnection().getInputStream());ImageData imageData = new ImageData();imageData.setImage(bytes);imageDataList.add(imageData);} catch (Exception e) {e.printStackTrace();}}WriteCellData writeCellData = new WriteCellData();writeCellData.setImageDataList(imageDataList);writeCellData.setType(CellDataTypeEnum.STRING);return writeCellData;}
}
  1. 定義圖片屬性
@ExcelProperty(value = "現場圖片(模擬機器人視角)", converter = ExcelImageUrlConverterUtils.class)
private List<String> images;
  1. 定義單元格圖片寫入攔截器
import cn.hutool.core.util.ObjUtil;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
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.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.util.Units;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;/*** 單元格圖片寫入攔截器* * @author 天航星* @date 2024-07-05 15:03*/
public class ImageCellWriteHandler implements CellWriteHandler {private final Map<String,List<ImageData>> imageDataMap = new HashMap<>();/*** 單元格的圖片最大張數(每列的單元格圖片張數不確定,單元格寬度需按照張數最多的長度來設置)*/private final AtomicReference<Integer> MAX_IMAGE_SIZE = new AtomicReference<>(0);@Overridepublic void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {if (isHead) {return;}// 將單元格圖片數據復制出來,清空單元格圖片數據if (!ObjUtil.isEmpty(cellData.getImageDataList())) {imageDataMap.put(cell.getRowIndex() + "_" + cell.getColumnIndex(), cellData.getImageDataList());cellData.setType(CellDataTypeEnum.EMPTY);cellData.setImageDataList(new ArrayList<>());}}@Overridepublic void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {if (isHead || ObjUtil.isEmpty(cellDataList)) {return;}String key = cell.getRowIndex() + "_" + cell.getColumnIndex();List<ImageData> imageDataList = imageDataMap.get(key);if (ObjUtil.isEmpty(imageDataList)) {return;}if (imageDataList.size() > MAX_IMAGE_SIZE.get()) {MAX_IMAGE_SIZE.set(imageDataList.size());}Sheet sheet = cell.getSheet();// 設置單元格行高sheet.getRow(cell.getRowIndex()).setHeight((short) 900);// 設置單元格列寬(乘多少代表容納多少張圖片)sheet.setColumnWidth(cell.getColumnIndex(), MAX_IMAGE_SIZE.get() > 0 ? 3493 * MAX_IMAGE_SIZE.get() : 3493);// 插入圖片for (int i = 0; i < imageDataList.size(); i++) {ImageData imageData = imageDataList.get(i);if (ObjUtil.isEmpty(imageData)) {continue;}byte[] image = imageData.getImage();this.insertImage(sheet, cell, image, i);}imageDataMap.remove(key);}private void insertImage(Sheet sheet, Cell cell, byte[] pictureData, int i) {// 圖片寬度int pictureWidth = Units.pixelToEMU(100);int index = sheet.getWorkbook().addPicture(pictureData, HSSFWorkbook.PICTURE_TYPE_PNG);Drawing<?> drawing = sheet.getDrawingPatriarch();if (ObjUtil.isEmpty(drawing)) {drawing = sheet.createDrawingPatriarch();}CreationHelper helper = sheet.getWorkbook().getCreationHelper();ClientAnchor anchor = helper.createClientAnchor();// 設置圖片在哪個單元格中anchor.setCol1(cell.getColumnIndex());anchor.setCol2(cell.getColumnIndex());anchor.setRow1(cell.getRowIndex());anchor.setRow2(cell.getRowIndex() + 1);// 設置圖片在單元格中的位置anchor.setDx1(pictureWidth * i);anchor.setDx2(pictureWidth + pictureWidth * i);anchor.setDy1(0);anchor.setDy2(0);// 設置圖片可以隨著單元格移動anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);drawing.createPicture(anchor, index);}
}
  1. 寫入時引用
EasyExcel.write("Excel文件名稱.xlsx", DemoData.class).sheet("測試").registerWriteHandler(new ImageCellWriteHandler()).doWrite(new DemoData());

環境:

  • JDK:1.8.0_202
  • SpringBoot:2.7.17
  • EasyExcel:3.3.2

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41520.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41520.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41520.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Haxm安裝失敗的解決辦法

確認你的處理器是否是Intel的&#xff0c;如果是AMD那就無法安裝&#xff0c;如果是Intel的&#xff0c;再確認是否支持V1T 如果處理器是Intel的且支持VT&#xff0c;在開機時進入BIOS界面&#xff0c;不同的品牌進入BIOS的方法各不相同&#xff0c;通常是F2/F12/delete些&…

Python爬蟲零基礎實戰,簡潔實用!

1.爬蟲簡介 簡單來講&#xff0c;爬蟲就是一個探測機器&#xff0c;它的基本操作就是模擬人的行為去各個網站溜達&#xff0c;點點按鈕&#xff0c;查查數據&#xff0c;或者把看到的信息背回來。就像一只蟲子在一幢樓里不知疲倦地爬來爬去。 你可以簡單地想象&#xff1a;每個…

論文學習 --- RL Maximumdiffusion reinforcement learning

前言 個人拙見,如果我的理解有問題歡迎討論 (●′ω`●) 文章出處:https://techxplore.com/news/2024-05-random-robots-reliable-ai-algorithm.html 研究背景 最大擴散強化學習(MaxDiff RL)是一種創新的強化學習方法,借鑒了統計力學中的擴散過程和最大熵原理。該方法在…

Hadoop的namenode啟動不起來

1、 排查原因 Initialization failed for Block pool (Datanode Uuid a5d441af-d074-4758-a3ff-e1563b709267) service to node1/192.168.88.101:8020. Exiting. java.io.IOException: Incompatible clusterIDs in /data/dn: namenode clusterID CID-674c5515-3fe1-4a9c-881d…

AIGC技術加持,英智法律智能體來了!

法律行業作為一個由大量文件積累的領域&#xff0c;非常適合由數據驅動的AI智能體。人工智能在法律領域的應用已經成為不可逆轉的趨勢。根據最高人民法院發布的《關于規范和加強人工智能司法應用的意見》&#xff0c;國家鼓勵在司法領域廣泛應用人工智能技術&#xff0c;以提高…

四端口千兆以太網交換機與 SFP 擴展功能

在數字化時代&#xff0c;網絡基礎設施的重要性日益凸顯&#xff0c;它是企業和個人取得成功的關鍵支撐。配備 SFP 插槽的 4 端口千兆以太網交換機提供了一種靈活且可擴展的網絡解決方案&#xff0c;能夠應對快速的數據傳輸、低延遲以及不斷增長的帶寬需求。本篇文章深入探討了…

IP地址配置

1.為虛擬機配置IP地址&#xff0c;網關&#xff0c;DNS 例如&#xff1a;手動給虛擬機配置IP地址為 192.168.5.50/24&#xff1b;網關地址為&#xff1a;192.168.5.2&#xff1b;DNS地址為&#xff1a;192.168.5.2 解題步驟如下&#xff1a; #配置IP地址 [rootlocalhost ~]#…

大廠都在加急招人的大模型LLM,到底怎么學?

大模型如何入坑&#xff1f; 想要完全了解大模型&#xff0c;你首先要了解市面上的LLM大模型現狀&#xff0c;學習Python語言、Prompt提示工程&#xff0c;然后深入理解Function Calling、RAG、LangChain 、Agents等 很多人不知道想要自學大模型&#xff0c;要按什么路線學&a…

【網絡安全】第4講 身份認證技術(筆記)

一、身份認證技術概述 1、身份認證 是網絡安全的第一道防線。是最基本的安全服務&#xff0c;其他的安全服務都依賴于它。在物聯網應用系統中&#xff0c;身份認證也是整個物聯網應用層信息安全體系的基礎。 2、基本身份認證技術 &#xff08;1&#xff09;雙方認證 是一種雙…

人員定位系統在監獄中的應用也同樣重要!

監獄管理應用人員定位系統怎么樣&#xff1f;新銳科創告訴你&#xff0c;人員定位系統在監獄中的應用也是很重要的&#xff0c;運用這種新型的定位系統&#xff0c;來起到管理監獄人員的作用。 人員定位系統 在監獄中&#xff0c;關押著大量的犯人&#xff0c;所以&#xff0c…

拓撲Transformer模型TopoFormer:革新藥物研發的智能鑰匙

在藥物研發的浩瀚征途中&#xff0c;每一步都充滿了挑戰與未知。從發現潛在的治療靶點&#xff0c;到篩選出有效的藥物分子&#xff0c;再到通過臨床試驗驗證其安全性和有效性&#xff0c;這一過程往往耗時漫長且成本高昂。然而&#xff0c;隨著人工智能技術的飛速發展&#xf…

昇思25天學習打卡營第15天|ResNet50圖像分類

學AI還能贏獎品&#xff1f;每天30分鐘&#xff0c;25天打通AI任督二脈 (qq.com) ResNet50圖像分類 圖像分類是最基礎的計算機視覺應用&#xff0c;屬于有監督學習類別&#xff0c;如給定一張圖像(貓、狗、飛機、汽車等等)&#xff0c;判斷圖像所屬的類別。本章將介紹使用ResN…

【JAVA入門】Day13 - 代碼塊

【JAVA入門】Day13 - 代碼塊 文章目錄 【JAVA入門】Day13 - 代碼塊一、局部代碼塊二、構造代碼塊三、靜態代碼塊 在 Java 中&#xff0c;兩個大括號 { } 中間的部分叫一個代碼塊&#xff0c;代碼塊又分為&#xff1a;局部代碼塊、構造代碼塊、靜態代碼塊三種。 一、局部代碼塊…

c++11新特性-3-自動類型推導

文章目錄 自動類型推導1.auto1.1 const修飾1.2 auto不能使用的場景1.3 auto應用場景 2.decltype1.1 基本語法 自動類型推導 1.auto 注意&#xff0c;auto必須進行初始化 auto i 10; //int類型auto k 3.14; //double類型auto db; //錯誤1.1 const修飾 當const修改指針或者…

C++:構造函數是什么東西

一、構造函數是什么 在C中&#xff0c;構造函數是一種特殊成員函數&#xff0c;它有一下幾個明顯的特征&#xff1a; 1、它自動在創建新對象時被調用。 2、其名稱與類名相同&#xff0c; 3、沒有返回類型&#xff0c; 4、通常沒有參數&#xff08;除了默認情況下的隱式thi…

跟《經濟學人》學英文:2024年06月01日這期 The side-effects of the TikTok tussle

The side-effects of the TikTok tussle tussle&#xff1a;美 [?t?s?l] 激烈扭打&#xff1b;爭奪 注意發音 side-effects&#xff1a;副作用&#xff1b;&#xff08;side-effect的復數&#xff09; As the app’s future hangs in the balance, the ramifications of …

MySQL的并發控制、事務、日志

目錄 一.并發控制 1.鎖機制 2.加鎖與釋放鎖 二.事務&#xff08;transactions&#xff09; 1.事物的概念 2.ACID特性 3.事務隔離級別 三.日志 1.事務日志 2.錯誤日志 3.通用日志 4.慢查詢日志 5.二進制日志 備份 一.并發控制 在 MySQL 中&#xff0c;并發控制是確…

都有哪些離線翻譯器軟件?沒網就用這4個

經歷完痛苦的期末考&#xff0c;可算是千盼萬盼等來了日思夜想的暑假&#xff01;趁著這大好時光&#xff0c;怎么能不來一場出國游呢~ 不知道有多少小伙伴和我一樣&#xff0c;出國玩最怕的就是語言不通&#xff0c;不管是吃飯還是游玩體驗感都會大受影響~好在多出國玩了幾趟…

ES6模塊化學習

1. 回顧&#xff1a;node.js 中如何實現模塊化 node.js 遵循了 CommonJS 的模塊化規范。其中&#xff1a; 導入其它模塊使用 require() 方法 模塊對外共享成員使用 module.exports 對象 模塊化的好處&#xff1a; 大家都遵守同樣的模塊化規范寫代碼&#xff…

Linux 時區文件格式【man 5 tzfile】

時區文件格式標準&#xff1a;https://datatracker.ietf.org/doc/html/rfc8536 1. NAME&#xff08;名&#xff09; tzfile - 時區文件。&#xff08;非文本文件&#xff09; 2. DESCRIPTION&#xff08;描述&#xff09; 本頁介紹被 tzset(3) 函數使用的時區文件的結構。這…