【193】Java8调用POI 5.2.5生成带图片的Excel文件

这篇具有很好参考价值的文章主要介绍了【193】Java8调用POI 5.2.5生成带图片的Excel文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文假定 Excel 文件中保存的是员工数据,并且数据中带有员工的头像。代码支持的图片格式有png、bmp、jpg、gif。但是这里需要注意,有些网站上下载的图片虽然后缀名是 jpg,但是文件二进制内容的格式是 WebP 的。Java8 目前官方api不支持 WebP ,本文不涉及webp相关话题,本文代码也不支持 WebP 格式。

另外我还遇到个坑,POI 5.2.5 在处理部分 jpg 格式图片的时候,无法把图片输出到 Excel 文件。为了解决这个问题,我在代码中把所有图片强行转成 png,保存为硬盘上的临时文件,再重新输出到 Excel 文件中。这个问题我没有在 POI 4.1.2 版本遇到过。

POI 的接口是线程不安全的,多个线程同时向一个文件输出会造成错误。如果读者想要在多线程环境(比如网站后端)使用下面的代码,要么使用锁,要么确保各个线程输出不同的文件。

本文的代码计算了图片的缩放比例,并且使用 picture.resize(scaleX, scaleY); 方法来设置图片缩放比例。这也与 POI 4.1.2 版本不同。POI 4.1.2 版本使用 picture.resize(1, 1); 会自动缩放图片调整成合适大小。

pom.xml 文件中添加的依赖:

<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi</artifactId>
     <version>5.2.5</version>
 </dependency>

 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
 <dependency>
     <groupId>org.apache.poi</groupId>
     <artifactId>poi-ooxml</artifactId>
     <version>5.2.5</version>
 </dependency>

员工的 DTO 类:


/**
 * 员工DTO
 */
public class EmployeeDTO {
    // 工号
    private String no;

    // 姓名
    private String name;

    // 性别
    private String gender;

    // 头像
    private String portrait;


    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Employee{");
        sb.append("no='").append(no).append('\'');
        sb.append(", name='").append(name).append('\'');
        sb.append(", gender='").append(gender).append('\'');
        sb.append(", portrait='").append(portrait).append('\'');
        sb.append('}');
        return sb.toString();
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getPortrait() {
        return portrait;
    }

    public void setPortrait(String portrait) {
        this.portrait = portrait;
    }
}

用来生成Excel 文件的 ImageExcelUtils 类


import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
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.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import javax.imageio.ImageIO;

public class ImageExcelUtils {
    /**
     * 读取jpg图片
     * @param path 图片文件路径
     * @return BufferedImage
     */
    public static BufferedImage readBufferedImage(String path) {
        BufferedImage originImage = null;
        BufferedImage result = null;
        try {
            File file = new File(path);
            originImage = ImageIO.read(file);
            // 确保图片颜色只有RGB,没有alpha透明度
            result = new BufferedImage(
                    originImage.getWidth(),
                    originImage.getHeight(),
                    BufferedImage.TYPE_INT_RGB
            );
            result.getGraphics().drawImage(originImage, 0, 0, null);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }


    /**
     * 设置excel文件的图片
     * @param workbook 工作簿
     * @param sheet sheet页
     * @param imgFilePath 图片文件路径
     * @param row1 图片起始的行
     * @param col1 图片起始的列
     * @param tempFilePath 临时文件路径
     */
    public static void setExcelImg(Workbook workbook, Sheet sheet, String imgFilePath,
                                   int row1, int col1, int width, int height, String tempFilePath) {
        File file = new File(imgFilePath);
        if (!file.exists()) {
            return;
        }
        // 临时文件
        File tempFile = new File(tempFilePath);
        if (tempFile.exists()) {
            tempFile.delete();
        }

        FileInputStream inputStream = null;
        boolean isClose = false;
        try {
            BufferedImage bufferedImage = readBufferedImage(imgFilePath);
            int imageWidth = bufferedImage.getWidth();
            int imageHeight = bufferedImage.getHeight();
            ImageIO.write(bufferedImage, "png", tempFile);

            inputStream = new FileInputStream(tempFile);
            //利用POI提供的工具类把文件流转化成二进制数据
            byte[] bytes = IOUtils.toByteArray(inputStream);
            //向POI内存中添加一张图片,返回图片在图片集合中的索引
            int pictureIndex = workbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);//参数一:图片的二进制数据,参数二:图片类型
            //从Workbook中得到绘制图片的工具类
            CreationHelper helper = workbook.getCreationHelper();
            //创建锚点,设置图片坐标
            ClientAnchor clientAnchor = helper.createClientAnchor();
            clientAnchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
            clientAnchor.setRow1(row1); // 设置起始行
            clientAnchor.setCol1(col1); // 设置起始列

            //从sheet对象中得到一个绘图对象
            Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
            //绘制图片,锚点,图片在内存中的位置
            Picture picture = drawingPatriarch.createPicture(clientAnchor, pictureIndex);

            // 使用固定的长宽比例系数
            double scaleX = 1.0;
            double scaleY = 1.0;
            if (imageWidth <= width && imageHeight <= height) {
                scaleX = 1.0;
                scaleY = 1.0;
            } else {
                scaleX = (double) width / (double) imageWidth;
                scaleY = (double) height / (double) imageHeight;
                double min = Math.min(scaleX, scaleY);
                scaleX = scaleY = min;
            }
            picture.resize(scaleX, scaleY);//自适应渲染图片
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStream != null && !isClose) {
                    inputStream.close();
                }
                tempFile.delete();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建Excel文件
     * @param employeeDTOList 员工列表
     * @param file 输出的 Excel 文件
     * @param tempFilePath 临时文件路径
     */
    public static void createExcelFile(List<EmployeeDTO> employeeDTOList, File file, String tempFilePath) {
        //创建工作簿,excel2007版本的,如果是excel2003的话。创建的对象是:HSSFWorkbook
        Workbook workbook = new SXSSFWorkbook();
        //创建sheet
        Sheet sheet = workbook.createSheet("picture sheet");
        // 列宽分别是25个字符和40个字符,一字符等于 6.107 像素
        sheet.setColumnWidth(0, 25 * 256);
        sheet.setColumnWidth(1, 25 * 256);
        sheet.setColumnWidth(2, 25 * 256);
        sheet.setColumnWidth(3, 40 * 256);
        // 行高是 120 磅,1磅是 1.34039 像素
        sheet.setDefaultRowHeightInPoints(120f);

        // 设置字体,黑体
        Font font = workbook.createFont();
        font.setFontName("黑体");
        // 字体加粗
        font.setBold(true);
        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setFont(font);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);

        // 表格标题行
        Row firstRow = sheet.createRow(0);
        Cell r0c0 = firstRow.createCell(0);
        r0c0.setCellValue("工号");
        Cell r0c1 = firstRow.createCell(1);
        r0c1.setCellValue("姓名");
        Cell r0c2 = firstRow.createCell(2);
        r0c2.setCellValue("性别");
        Cell r0c3 = firstRow.createCell(3);
        r0c3.setCellValue("头像");

        r0c0.setCellStyle(cellStyle);
        r0c1.setCellStyle(cellStyle);
        r0c2.setCellStyle(cellStyle);
        r0c3.setCellStyle(cellStyle);

        int size = employeeDTOList.size();
        for (int i = 0; i < size; i++) {
            EmployeeDTO dto = employeeDTOList.get(i);
            int rowIndex = i + 1;
            Row row = sheet.createRow(rowIndex);
            Cell c0 = row.createCell(0);
            Cell c1 = row.createCell(1);
            Cell c2 = row.createCell(2);
            Cell c3 = row.createCell(3);

            // 向excel中输入图片
            String portrait = dto.getPortrait();
            if (null != portrait && portrait.trim().length() > 0) {
                portrait = portrait.trim();
                setExcelImg(workbook, sheet, portrait, rowIndex, 3, 244, 160, tempFilePath);
            }

            c0.setCellValue(dto.getNo());
            c1.setCellValue(dto.getName());
            c2.setCellValue(dto.getGender());
        }

        //创建文件输入流
        FileOutputStream out = null;
        //创建文件输出流
        try {
            out = new FileOutputStream(file);
            //调用工作簿的write创建excel
            workbook.write(out);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                    out = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } // end finally

    }
}

包含 main 方法的 Test 类,测试具体效果文章来源地址https://www.toymoban.com/news/detail-756057.html


import java.io.File;
import java.util.List;
import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        List<EmployeeDTO> employeeDTOList = new ArrayList<>();

        EmployeeDTO emp_1 = new EmployeeDTO();
        emp_1.setNo("1");
        emp_1.setName("张三");
        emp_1.setGender("男");
        emp_1.setPortrait("D:/1715284526222417922.jpg");

        EmployeeDTO emp_2 = new EmployeeDTO();
        emp_2.setNo("2");
        emp_2.setName("李四");
        emp_2.setGender("男");
        emp_2.setPortrait("D:\\bmptest.bmp");

        EmployeeDTO emp_3 = new EmployeeDTO();
        emp_3.setNo("3");
        emp_3.setName("王二");
        emp_3.setGender("女");
        emp_3.setPortrait("D:\\113.jpg");


        EmployeeDTO emp_4 = new EmployeeDTO();
        emp_4.setNo("4");
        emp_4.setName("涂军");
        emp_4.setGender("男");
        emp_4.setPortrait("D:\\309446533.gif");

        employeeDTOList.add(emp_1);
        employeeDTOList.add(emp_2);
        employeeDTOList.add(emp_3);
        employeeDTOList.add(emp_4);

        File file = new File("D:\\ws\\tmpdir\\out.xlsx");
        String tempFilePath = "D:\\ws\\tmpdir\\temp.png";
        ImageExcelUtils.createExcelFile(employeeDTOList, file, tempFilePath);
    }
}

到了这里,关于【193】Java8调用POI 5.2.5生成带图片的Excel文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java使用POI解析带图片的excel,简洁好用

            这天遇到这个这样的需求,需要导入表格中的数据,还得支持带图片;这应该难不倒咱阿里的EasyExcel,打开官网文档一看哦豁,明确表示暂时不支持解析带图片的Excel...... 好了,这下只能看POI了,然后想起来项目里引入的HuTools工具类,它应该封装好了吧;于是决定用

    2024年02月11日
    浏览(28)
  • JAVA POI的excel中包含图片进行读取保存,单张图片,多张图片

    ---------------------------------------------效果---------------------------------------------------------- 1.单张图片 2.多张图片

    2024年02月11日
    浏览(30)
  • java调用poi根据模板生成ppt

    吐槽:像这种需求半年碰不到一个 O.o 可以多去poi官网翻一下官方文档虽然很难理解但有用  所有代码基于个人习惯编写,懒得贴图了相信兄弟们的理解能力,有问题可以留言我尽量解决。 本文所有代码生成都基于pptx文件编写,可根据具体业务修改代码 1.打开模板文件 2.创建

    2024年02月21日
    浏览(38)
  • java poi 获取excel中的图片(包含wps中嵌入单元格图片)

    项目中有excel导入功能,并且需要导入excel中的图片;模板如图: 已知office中插入的图片为浮动形式;如图: wps中可以插入浮动图片,也可以插入嵌入单元格图片;如图: 并且在wps嵌入单元格形式的图片可以看到使用的是公式;如图:  问题来了,如何获取图片  并且将图片与单元格进行对

    2024年02月07日
    浏览(37)
  • java poi生成excel折线图、柱状图、饼图、动态列表

    实现效果   测试类 实体类  工具类 完整代码地址:https://gitee.com/Szw99/create-excel.git

    2024年02月13日
    浏览(28)
  • Apache POI | Java操作Excel文件

    目录 1、介绍 2、代码示例 2.1、将数据写入Excel文件 2.2、读取Excel文件中的数据 🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习,擅长web应用开发、数据结构和算法,初步涉猎Python人工智能开发和前端开发。 🦅主页:@逐梦苍穹 📕您的一

    2024年02月20日
    浏览(36)
  • 使用POI实现JAVA操作Excel文件

    https://poi.apache.org/components/index.html xls最大支持65536行、256列 xlsx最大支持1048576行、16384列 poi 操作xls poi-ooml操作xlsx 优点:过程中写入缓存,不操作磁盘,最后再一次性导入磁盘,速度快+ 缺点:但是只能写入65535条数据,超过就会报异常 优点:可以写较大数据量(超过655135条)

    2024年02月14日
    浏览(30)
  • Java中Excel文件解析(POI简介及基本使用)

    在Java技术生态圈中,可以进行Excel文件处理的主流技术包括: Apache POI 、 JXL 、 Alibaba EasyExcel 等。 其中各个技术都有最适合的场景 Apache POI 基于 DOM 方式进行解析,将文件直接加载内存,所以速度较快,适合 Excel 文件数据量不大的应用场景。 JXL 只支持Excel 2003以下版本,所以

    2024年02月08日
    浏览(32)
  • Java POI (2)—— Excel文件的上传与导出(实例演示)

             这里是一个demo的流程图,下面按照这个流程图做了一个简单的实现,有部分判断没有加上,实际操作中,可以根据自己的需求进行增加或者修改。并且此处还是在接受文件传入后将文件进行了下载,保存到本地的操作,这个要按照具体情况具体分析,看需求是否

    2024年02月11日
    浏览(33)
  • JAVA:使用POI SXSSFWorkbook方式导出Excel大数据文件

    Apache POI 是用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java对Microsoft Office格式档案读和写的功能。POI组件可以提供Java操作Microsoft Office的API,导出格式为Office 2003时POI调用的HSSF包,导出格式为Office 2007时,调用XSSF包,而SXSSF包是POI3.8版本之上对XSSF的一个扩展,用

    2024年02月11日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包