使用POI操作Excel,用OLE对象的形式插入文件附件--细糠版

本文介绍了如何使用ApachePOI库在Excel中插入文件对象,如PDF,作为OLE对象,并详细展示了创建表格、上传文件、设置图标和锚点的过程。作者还分享了代码示例,特别提到了HSSFWorkbook和XSSFWorkbook的区别以及HSSFWorkbook意外支持.xlsx格式的情况。
摘要由CSDN通过智能技术生成

首先展示一下需要的效果:

在Excel内插入文件对象,其实就是关联到另一个文件,可以在这里点击图标直接打开文件进行编辑。
在Excel内操作的话是点击工具栏的插入--》附件--》对象/附件

首先了解好创建流程后其实我们在套用到代码里面就比较好理解了,我们这里是使用了POI包去操作Excel。
大概的步骤就是:
创建表格--》上传文件--》获取文件视图管理器(获取文件图标用)--》写入文件图标--》写入文件--》创建画布锚点坐标(就是文件放在哪里)--》最后将图标、文件、锚点设置进去--》最后输出

上代码
这里也借鉴了CSDN上面一些老哥的代码,我只是把我的理解更加详细的标注出来,为了给小白更好的理解很学习。

package com.gsr.Excel;

import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
import org.apache.poi.hssf.usermodel.HSSFObjectData;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileSystemView;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;

public class InsertTxtFileAsOleObject {


    public static void main(String[] args) throws IOException {
        //只有HSSFWorkbook才能使用OLE对象,并且poi需要在4.0之上
        // 创建工作簿和工作表对象
        Workbook workbook = new HSSFWorkbook ();
        Sheet sheet = workbook.createSheet("Sheet1");


        /** 这里是为了图标方便看,实际应用可以不管 */
        sheet.setColumnWidth(0, 10000);//设置单元格的宽度
        //设置单元格高度
        Row row = sheet.createRow(0);
        row.setHeightInPoints(1000);


        // 读取需要添加的文件,如果有需要添加多个文件的需求,可以循环表格来添加
        File pdfFile = new File("C:\\Users\\阿辉\\Desktop\\111.zip");
        FileInputStream fis = new FileInputStream(pdfFile);
        byte[] pdfBytes = new byte[(int) pdfFile.length()];
        fis.read(pdfBytes);
        fis.close();

        /** 这一步是获取文件图标 */
        // 获取文件系统视图
        FileSystemView view = FileSystemView.getFileSystemView();
        Icon systemIcon = view.getSystemIcon(pdfFile);
        // 将 Icon 对象转换为 Image 对象
        Image image = iconToImage(systemIcon);
        // 将 Image 对象转换为字节数组
        byte[] imageBytes = imageToByteArray(image);


        /**  自定义文件的展示图标 */
        // String imagePath = "C:\\Users\\阿辉\\Desktop\\Snipaste_2024-04-01_12-04-43.png"; // 图片文件路径 这个是excel中单元格中pdf文件对应展示出来的图片,可以自定义
        // BufferedImage image = ImageIO.read(new File(imagePath));
        // ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // ImageIO.write(image, "png", baos);
        // byte[] imageBytes = baos.toByteArray();
        // baos.close();


        //将文件的图标添加进入到Excel文件内
        int iconid = workbook.addPicture(imageBytes, HSSFWorkbook.PICTURE_TYPE_JPEG);
        // 在工作表中创建OLE对象,就是将文件插入到Excel文件中
        int pdfIdx = workbook.addOlePackage(pdfBytes, "222.zip", "333.zip", "111.zip");

         /**
          pdfBytes: 表示 PDF 文件的字节数组。您需要将 PDF 文件的内容以字节数组的形式传递给此参数。
          "222.zip": 表示 OLE 对象的类型。如果导出之后,在excel中操作另存文件,这个名称就是新保存文件的默认名称【文件标签】
          "333.zip": 这指定了要在OLE Package中使用的类名。在此示例中,你可以将其设置为任何你想要的类名,因为它不会对后续的操作产生影响。它也只是用于标识特定的OLE Package【文件名】。
          "111.zip":这是在Excel工作簿中显示的OLE Package的名称,如果需要在excel中打开pdf文档,命名一定要以.pdf结尾,不然在excel中打不开!!!。
          */

        // 创建画布和锚点
        Drawing<?> drawing = sheet.createDrawingPatriarch();
        ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 1, 1, 0, 0);//这里的参数后续根据传过来的信息来变化。row,col
        anchor.setAnchorType(HSSFClientAnchor.AnchorType.MOVE_AND_RESIZE);
        //文件略缩图会占据整个单元格,锚点随单元格大小的改变而自动调整。这意味着当单元格的大小发生变化时,图片的大小也会相应地进行调整。
        //在后续应用业务的时候,可以给单元格固定的高度和宽度,让略缩图更加美观
        //参数1:起始列的偏移量(单位为字符宽度的 1/256)
        //参数2:起始行的偏移量(单位为字符高度的 1/256)
        //参数3:结束列的偏移量(单位为字符宽度的 1/256)
        //参数4:结束行的偏移量(单位为字符高度的 1/256)
        //参数5:起始列
        //参数6:起始行
        //参数7:结束列
        //参数8:结束行


        // 创建图片并将它关联到OLE对象
        /**
         * 这里参数是:
         * 文件放在Excel表格内的位置:anchor
         * 文件在Excel表格内的索引:pdfIdx(文件本身,文件能否打开的关键)
         * 文件在Excel表格内的图标:iconid(文件的图标)
         * */
         drawing.createObjectData(anchor, pdfIdx, iconid);


        //输出
        try (OutputStream outputStream = new FileOutputStream("C:\\Users\\阿辉\\Desktop\\未命名1.xlsx")) {
            workbook.write(outputStream);
            System.out.println("文件写入成功!");
        }
        workbook.close();
    }



    // 将 Icon 对象转换为 Image 对象
    private static Image iconToImage(Icon icon) {
        if (icon instanceof ImageIcon) {
            return ((ImageIcon) icon).getImage();
        } else {
            int width = icon.getIconWidth();
            int height = icon.getIconHeight();
            BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
            Graphics graphics = image.createGraphics();
            icon.paintIcon(null, graphics, 0, 0);
            graphics.dispose();
            return image;
        }
    }

    // 将 Image 对象转换为字节数组
    private static byte[] imageToByteArray(Image image) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ImageIO.write(imageToBufferedImage(image), "png", byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }

    // 将 Image 对象转换为 BufferedImage 对象
    private static BufferedImage imageToBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }

        BufferedImage bufferedImage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D graphics2D = bufferedImage.createGraphics();
        graphics2D.drawImage(image, 0, 0, null);
        graphics2D.dispose();
        return bufferedImage;
    }

}

这里单独解释一下设置文件的几个参数在哪里,不然小白会很懵逼。

另外画布锚点的设置和最后的保存锚点关系在代码注释里都标明了,可以封装成方法去调用。

上图补充一下,参数2的标签名字就是附在excel上面那个图标下面的名称

OLE:
OLE,全称Object Linking and Embedding,意为“对象链接和嵌入”,是一种实现应用程序间数据共享和交互的技术。通过OLE,用户可以在一个应用程序中使用另一个应用程序的功能和数据,而无需离开当前应用程序。

OLE不仅是桌面应用程序集成,而且还定义和实现了一种允许应用程序作为软件“对象”(数据集合和操作数据的函数)彼此进行“连接”的机制,这种连接机制和协议称为组件对象模型(COM)。OLE可以用来创建复合文档,这种文档包含了来自不同源应用程序的、具有不同类型的数据,因此它可以将文字、声音、图像、表格、应用程序等组合在一起。

另外
HSSFWorkbook 类是 . xls 格式(Excel 97-2003版本)
XSSFWorkbook 类是 .xlsx 格式(Excel 2007 及以后版本)

但是我这里输出是 .xlsx 格式格式,我使用XSSFWorkbook 类去创建工作表输出的时候并没有看到设置的文件。

然而!!!我用HSSFWorkbook 类去创建的时候居然成了,并且输出都没问题,不知道为啥,有知道的可以评论区踢一下。

使用POI-OOXML导入Excel时,您可以使用注解或XML配置来将Excel列与Java对象字段对应起来。 1. 使用注解 您可以在Java对象的字段上使用注解来指定Excel列的名称或索引。例如,假设您有一个名为Employee的Java类,其中包含id、name和age字段。您可以在该类中使用以下注解: ```java public class Employee { @ExcelColumn("ID") private int id; @ExcelColumn("Name") private String name; @ExcelColumn("Age") private int age; // 省略getter和setter方法 } ``` 在这个例子中,@ExcelColumn注解告诉POIExcel列“ID”映射到id字段,将Excel列“Name”映射到name字段,将Excel列“Age”映射到age字段。 2. 使用XML配置 如果您不想在Java类中使用注解,您可以使用XML配置文件来指定Excel列与Java对象字段之间的映射关系。例如,假设您有一个名为employee.xml的配置文件,其中包含以下内容: ```xml <?xml version="1.0" encoding="UTF-8"?> <excel-mapping> <class name="com.example.Employee"> <column name="ID" field="id" /> <column name="Name" field="name" /> <column name="Age" field="age" /> </class> </excel-mapping> ``` 在这个例子中,<column>元素指定Excel列的名称和Java对象字段的名称。您可以在使用POI-OOXML导入Excel时指定这个配置文件,如下所示: ```java ExcelReader reader = new ExcelReader(new FileInputStream("path/to/excel/file.xlsx"), "Sheet1", "employee.xml"); List<Employee> employees = reader.read(Employee.class); ``` 在这个例子中,ExcelReader类使用employee.xml配置文件Excel列映射到Employee类的字段。您可以根据需要创建多个配置文件,每个文件都可以映射不同的Excel列到不同的Java对象
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值