Apache组件POI,将图片下载到Excel文件中并导出。

news2024/9/20 16:35:59

      在日常的工作中,有时我们会遇到需要将数据库表中图片字段下载到Excel中的需求,为方便各位小伙伴今后的开发工作,我将分享出自己写的代码,在文章末尾有我上传到 Gitee 上的 Demo案例,希望大家喜欢。

      将图片下载到Excel文件中并导出,先看一下效果。

1、使用的 POI 依赖

     需要说明的是: commons-io 依赖必须有,不然在编写代码的过程中会异常。由于 POI 组件版本升级的问题,本文分享的代码适合 3.17 版本的依赖,版本太高的jar包可能不适合。

     在我自己学习、测试过程中,5.2.0版本的POI组件Jar包就不适合本文的代码。 

<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.11.0</version>
</dependency>

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.17</version>
	<!--<version>5.2.0</version>-->
</dependency>

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>3.17</version>
	<!--<version>5.2.0</version>-->
</dependency>



2、关键部分代码展示

      在以下的函数中,大体分为以下几步:

      2-1、查询获取结果值:userVOList ,并将其转成导出 exportVOS ;

      2-2、创建工作簿对象workbook,并因此创建工作表对象 sheet ;

      2-3、对工作表 sheet工作表对象 设置头部标题数据、头部标题样式;

      2-4、对 sheet工作表对象 填充数据,这些数据分为普通文本数据、图片数据。

      2-5、将工作簿对象 workbook 输出。  


/***
     * 用户信息 导出
     *
     * @param paramDTO  用户入参DTO
     * @param response  response请求
     *
     * @return
     * @author moon  2023/6/27 10:31
     */
    @Override
    public void exportUser(UserParamDTO paramDTO, HttpServletResponse response) throws Exception {

        // 1-1、获取列表查询数据
        List<UserVO> userVOList = userMapperExt.selectUserByParamDTO(paramDTO);

        // 1-2、将 UserVO 转成 UserExportVO
        List<UserExportVO> exportVOS = userVOList.stream().map(infoVO -> BeanUtils.convert(infoVO, UserExportVO.class)).collect(Collectors.toList());

        //空数据导出不了标题 需要放一个空对象
        if (CollectionUtils.isEmpty(exportVOS)) {
            exportVOS = new ArrayList<>();
        }

        // Map<'英文名', '中文名'> 组合形式.
        Map<String, String> aliasMap = ExcelUtils.getDTOAliasTitle(UserExportVO.class, Constant.BooleanFlag.FALSE);

        List<String> headerList = new ArrayList<>(aliasMap.keySet());
        // 2-1、创建 工作簿 对象.
        Workbook workbook = new XSSFWorkbook();
        // 2-2、创建工作表对象
        Sheet sheet = workbook.createSheet();
        // 设置标题行,第0行.
        Row headerRow = sheet.createRow(Constant.Digital.ZERO);

        // 获取头部单元格样式
        CellStyle headerCellStyle = ExcelUtils.getCellStyle(workbook, HorizontalAlignment.CENTER, VerticalAlignment.CENTER, Constant.Digital.ONE);
        // 2-3、设置头部单元格样式
        for (int i = 0; i < headerList.size(); i++) {
            // 获取中文值
            String value = aliasMap.get(headerList.get(i));
            Cell cell = headerRow.createCell(i);
            // 设置 样式
            cell.setCellStyle(headerCellStyle);
            // 设置 值
            cell.setCellValue(value);
        }

        
        // 2-4、填充单元格数据
        for (int i = 0; i < exportVOS.size(); i++) {

            // 创建行对象,从第1行开始。
            int rowNum = i + 1;
            Row row = sheet.createRow(rowNum);
            UserExportVO tempVO = exportVOS.get(i);

            // 创建单元格对象(列)并设置值
            for (int j = 0; j < headerList.size(); j++) {
                Cell cell = row.createCell(j);
                Field field = UserExportVO.class.getDeclaredField(headerList.get(j));
                // 若属性为私有,需要设置可访问。
                field.setAccessible(Constant.BooleanFlag.TRUE);
                String fieldName = field.getName();
                String fieldValue;
                if (Objects.isNull(field.get(tempVO))) {
                    fieldValue = Constant.CommonlySymbols.EMPTY;
                } else {
                    fieldValue = field.get(tempVO).toString();
                }

                if (StringUtils.equalsAny(fieldName, UserVO.FIELD_HEAD_PHOTO, UserVO.FIELD_SCHOOL_PHOTO)
                        && StringUtils.isNotBlank(fieldValue)) {  // 2个图片字段,需要特殊处理.

                    // 构造 URL
                    String path = field.get(tempVO).toString();
                    URL url = new URL(path);
                    // 打开连接
                    URLConnection con = url.openConnection();
                    //设置请求超时为5s
                    con.setConnectTimeout(8 * 1000);
                    // 输入流
                    InputStream is = con.getInputStream();
                    byte[] bytes = IOUtils.toByteArray(is);
                    @SuppressWarnings("static-access")
                    int pictureIdx = workbook.addPicture(bytes, workbook.PICTURE_TYPE_PNG);  // 添加图片到工作簿中

                    CreationHelper helper = workbook.getCreationHelper();  // 获取创建帮助类
                    Drawing drawing = sheet.createDrawingPatriarch();   // 获取绘图父对象
                    ClientAnchor anchor = helper.createClientAnchor();  // 创建客户端锚点
                    // 图片插入坐标
                    anchor.setCol1(j);  // 设置图片左上角的列数
                    anchor.setRow1(rowNum);  // 设置图片左上角的行数
                    // 插入图片
                    Picture pict = drawing.createPicture(anchor, pictureIdx);  // 在指定位置插入图片

                    // 设置 单元格高度
                    cell.getRow().setHeight((short) 1000);  // 将单元格所在行的高度设置为1000
                    // 设置 单元格宽度
                    sheet.setColumnWidth(cell.getColumnIndex(), 2600);  // 将单元格所在列的宽度设置为2600
                    // 设置图片宽、高放缩比例
                    pict.resize(1, 1);  // 这行代码,可以将值设置成 pict.resize(0.5, 0.5)、pict.resize(2, 2),看看效果如何。

                } else {
                    cell.setCellValue(fieldValue);
                }
            }
        }

        
        // 将工作簿写入文件中
        try {

            response = ExcelUtils.getHttpServletResponse(response, Constant.ExcelProperty.USER_EXPORT_NAME);
            ServletOutputStream outputStream = response.getOutputStream();
            workbook.write(outputStream);
        } finally {
            workbook.close();
        }

    }




3、使用Postman进行测试

3-1、测试的URL:http://localhost:8080/user/exportUser

3-2、入参参数:

{
  "age": "",
  "createDate": "",
  "distinct": true,
  "id": "",
  "isDeleted": "",
  "name": ""
}


3-3、返回结果:

 

    在之后的时间里,我将还会分享 Excel勾选导出 代码案例,希望能够帮到大家。

Gitee上的Demo案例:  apache-poi-demo   ,项目名称:apache-poi-demo .             

入口函数:com.moon.poi.service.impl.UserServiceImpl#exportUser(...)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/705015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[CKA]考试之Deployment管理pod扩缩容

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 扩容 deployment guestbook 为 6个pod 注意&#xff0c;如果题目要求先切换K8…

低价高品质的头戴式降噪耳机,还支持主动降噪,QCY H4体验

每天办公的时候&#xff0c;我都喜欢戴上耳机听音乐&#xff0c;开会的时候也会方便一些。以前我用过无线入耳式耳机&#xff0c;但是戴时间长了会让耳朵很痛苦&#xff0c;因为室内也不算热&#xff0c;所以我觉得头戴式蓝牙耳机很合适&#xff0c;目前我用的是这款QCY H4头戴…

Laravel 多字段去重count计数

Laravel 多字段去重count计数 背景&#xff1a;需要统计数据列表总条数&#xff08;字段1、字段2去重统计&#xff09; table&#xff1a;policy_view,去重字段admin_id和permission 期望结果&#xff1a;count不含重复统计数据 解决思路&#xff1a; 语法&#xff1a;DISTI…

appium下载安装及环境配置及夜神模拟器下载、nodejs安装

appium所需要的环境有&#xff1a;jdk、android sdk、Nodejs、appium客户端 此次教程只针对于windows jdk、Android sdk已下载安装配置好环境&#xff0c;此次教程不再重复记录 jdk可看这篇博文jdk安装及环境配置 Android sdk 可看这篇 Android SDK下载与安装 一、Nodejs安装 …

有哪些做任务赚佣金的平台 做任务挣钱的app

科思创业汇 大家好&#xff0c;这里是科思创业汇&#xff0c;一个轻资产创业孵化平台。赚钱的方式有很多种&#xff0c;我希望在科思创业汇能够给你带来最快乐的那一种&#xff01; 做任务赚佣金的平台&#xff1f;做任务赚钱一直是一种流行的赚钱方式。现在有无数的app可以通…

优化细节令人惊叹,用户体验直接拉满!你的App也能如此丝滑!

启动时间是App使用者的第一体验&#xff0c;很多大厂都通过A/B实验论证启动速度的优化可以带来用户留存的显著收益&#xff0c;尤其是体量大的用户&#xff0c;启动时间缩短一点&#xff0c;留存增长一点&#xff0c;那就带来了非常大的收益。因此&#xff0c;启动性能优化一直…

济南中医风湿病医院受邀参加北坦街道“学习二十大 奋进新征程”主题党日活动

为学习贯彻党的二十大精神&#xff0c;中共天桥区北坦街道工作委员会于近日特组织开展“学习贯彻二十大精神 凝心聚力奋进新征程”联合主题党日活动&#xff0c;济南中医风湿病医院党支部预备党员卢雪梅同志受邀参加。 活动第一站&#xff0c;参观济南黄河文化展览馆。这是一部…

Microsoft Edge插件推荐:CSDN·浏览器助手

文章目录 1.简介2.安装3.总结 今天来给大家分享一个超级好用的Microsoft Edge插件&#xff0c;名为CSDN浏览器助手 1.简介 CSDN浏览器助手是一款集成本地书签、历史记录与 CSDN搜索(so.csdn.net) 的搜索工具&#xff0c;可以自定义Microsoft Edge的新标签页&#xff0c;还可以…

LangChain-Evaluation—如何评估LLM及其应用(三)

省流&#xff1a;目前没有真正完美的解决方案&#xff0c;比如分类有精度这样接近完美的评估方案&#xff0c;但LLM目前没有 This section of documentation covers how we approach and think about evaluation in LangChain. Both evaluation of internal chains/agents, b…

十五周算法训练营——背包问题

今天是十五周算法训练营的第十三周&#xff0c;主要讲背包问题专题。&#xff08;欢迎加入十五周算法训练营&#xff0c;与小伙伴一起卷算法&#xff09; 「背包问题&#xff1a;给你一个可装载重量为W的背包和N个物品&#xff0c;每个物品有重量和价值两个属性。其中第i个物品…

以加快工程和科学发展为使命,MathWorks 创新步履不止

一直以来&#xff0c;人类对于宇宙苍穹、高山峻岭的探索永不止步。今年是人类首次登月54周年&#xff0c;毋庸置疑&#xff0c;“登月计划”激发了全世界所有人的想象力。正由于这项计划&#xff0c;让耐高温的金属和合金防火面料、冻干食品及光伏电池、集成电路、计算机以及备…

解密Linux内核神器:内存屏障的秘密功效与应用方法

一、内存屏障简介 现在大多数现代计算机为了提高性能而采取乱序执行&#xff0c;这可能会导致程序运行不符合我们预期&#xff0c;内存屏障就是一类同步屏障指令&#xff0c;是CPU或者编译器在对内存随机访问的操作中的一个同步点&#xff0c;只有在此点之前的所有读写操作都执…

信号链噪声分析14

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 提示&#xff1a;这里可以添加技术概要 虽然噪声的均方根值可通过 q/√12 计算精确近似值&#xff0c;但在某些条件下&#xff0c;频域成分可能 与交流输入信号高度相关。例如&#xff0c;低幅度周期性信号的相关度大…

智慧厕所系统:革新公厕管理的智能解决方案

公厕是城市基础设施的重要组成部分&#xff0c;但由于管理难度大、人员分散等问题&#xff0c;公厕的管理一直是一个难题。智慧公厕系统通过智能化的监控设备和传感器&#xff0c;实时监测公厕的使用情况和卫生状况&#xff0c;并将数据传输到中央控制系统。管理员可以通过该系…

C++学习笔记-第8单元 运算符重载

第8单元 运算符重载 文章目录 第8单元 运算符重载单元导读单元导读1&#xff1a;深度学习与C单元导读2&#xff1a;向量、矩阵、张量 8.1 运算符重载与平面向量类8.1.1 运算符与函数的关系8.1.2 平面向量类8.1.3 C运算符函数8.1.4 [C11]左值、纯右值、将亡值 8.2 重载二元运算符…

极致呈现系列之终章:Vue3中封装Echarts组件

经过前面一系列博文的介绍&#xff0c;我已经详细地讲解了Echarts中涉及的各种图表类型。所以&#xff0c;我认为极致呈现系列文章到此基本告一段落了。作为这个系列文章的终章&#xff0c;我想探讨最后一个问题&#xff1a;如何封装Echarts组件。我觉得这是一个很好的结尾&…

黑马程序员-从0到1学习Linux-第一章 初识Linux

视频学习地址&#xff1a;黑马程序员新版Linux零基础快速入门到精通&#xff0c;全涵盖linux系统知识、常用软件环境部署、Shell脚本、云平台实践、大数据集群项目实战等_哔哩哔哩_bilibili 目录 操作系统概述 初识Linux系统 虚拟机介绍 VMware WorkStation安装 在VMware上…

【Langchain】GPT的高效插件

功能1&#xff1a;让模型具有memory 可以看到&#xff0c;langchain作为访问gpt的一个插件&#xff0c;可以让gpt模型通过memory变量将之前的对话记录下来&#xff0c;从而使模型具有记忆&#xff08;在不改变模型参数的情况下&#xff09;。 查看memory变量包含了什么&#…

在blender中使用python程序化建模

blender中&#xff0c;所有可以在Blender软件中的手动操作&#xff0c;基本都可以通过Python API 完成 那么就可以用这个完成程序化生成 下面我给出一个简单的方块建模程序&#xff1a; 在scripting中&#xff0c;可以添加file&#xff0c;然后向场景中心放置一个正方体 首…

前端面试题Vue答案

1.vue的原理? image.png 关键词: 虚拟DOM树访问器属性 解释一下:响应式原理? 当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项&#xff0c;Vue 将遍历此对象所有的 property&#xff0c;并使用 Object.defineProperty把这些 property 全部转为 getter/setter…