HCRM博客

如何解决Apache POI中addPicture方法报错问题?

一、常见错误及原因

1、图片无法显示

原因:可能是POI版本问题,如使用3.7等低版本时,插入Excel中的图片在重新打开文件时可能不显示,也可能是在向Word中插入图片时,部分XML没有正确生成,导致图片框为透明。

如何解决Apache POI中addPicture方法报错问题?-图1
(图片来源网络,侵权删除)

解决方法:升级POI版本至3.16及以上;对于Word插入图片XML未正确生成的问题,可自定义XWPFDocument类来完善缺陷XML内容的添加。

2、图片显示异常或与预期不符

原因:在Excel中插入图片时,如果多次创建HSSFPatriarch对象来添加图片,可能导致新添加的图片显示异常,原有的图片也无法正常显示,这可能是由于引用了sheet的patriarch对象中已存在的图片对象,造成新增图片显示为已存在图片,而对应的已存在图片无法显示。

解决方法:始终使用同一个HSSFPatriarch对象来添加图片,避免重复创建。

二、代码示例及说明

1、在Word中添加图片

以下是一个使用POI在Word文档中添加图片的示例代码:

  • import org.apache.poi.xwpf.usermodel.*;
  • import java.io.FileInputStream;
  • import java.io.FileOutputStream;
  • import java.io.IOException;
  • public class WordAddPictureExample {
  • public static void main(String[] args) throws IOException {
  • // 创建新的Word文档
  • XWPFDocument document = new XWPFDocument();
  • // 添加一个段落
  • XWPFParagraph paragraph = document.createParagraph();
  • XWPFRun run = paragraph.createRun();
  • run.setText("这是一个包含图片的段落");
  • // 添加图片到段落中
  • String picId = document.addPictureData(new FileInputStream("path/to/your/image.jpg"), XWPFDocument.PICTURE_TYPE_JPEG);
  • addPictureToRun(run, picId, XWPFDocument.PICTURE_TYPE_JPEG, 200, 200);
  • // 将文档写入文件
  • try (FileOutputStream out = new FileOutputStream("example.docx")) {
  • document.write(out);
  • }
  • document.close();
  • }
  • private static void addPictureToRun(XWPFRun run, String picId, int pictureType, int width, int height) {
  • final int EMU = 9525;
  • width *= EMU;
  • height *= EMU;
  • String picXml = "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
  • " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
  • " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
  • " <pic:nvPicPr>" +
  • " <pic:cNvPr id=\"" + 1 + "\" name=\"Generated\"/>" +
  • " <pic:cNvPicPr/>" +
  • " </pic:nvPicPr>" +
  • " <pic:blipFill>" +
  • " <a:blip r:embed=\"" + picId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
  • " <a:stretch>" +
  • " <a:fillRect/>" +
  • " </a:stretch>" +
  • " </pic:blipFill>" +
  • " <pic:spPr>" +
  • " <a:xfrm>" +
  • " <a:off x=\"0\" y=\"0\"/>" +
  • " <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" +
  • " </a:xfrm>" +
  • " <a:prstGeom prst=\"rect\">" +
  • " <a:avLst/>" +
  • " </a:prstGeom>" +
  • " </pic:spPr>" +
  • " </pic:pic>" +
  • " </a:graphicData>" +
  • "</a:graphic>";
  • // 创建自定义的XWPFDocument类并添加图片
  • CustomXWPFDocument doc = new CustomXWPFDocument(document);
  • doc.createPic(picId, 1, 200, 200, run.getCTR().addNewDrawing().addNewInline());
  • }
  • }

说明:上述代码首先创建了一个Word文档,然后在其中添加了一个段落和一个图片。addPictureToRun方法用于将图片添加到段落的指定位置,并设置了图片的宽度和高度,这里使用了自定义的CustomXWPFDocument类来解决低版本POI插入图片显示异常的问题。

2、在Excel中添加图片

以下是一个在Excel中使用POI添加图片的示例代码:

  • import org.apache.poi.hssf.usermodel.*;
  • import org.apache.poi.ss.usermodel.*;
  • import java.io.ByteArrayOutputStream;
  • import java.io.IOException;
  • import javax.imageio.ImageIO;
  • import java.awt.image.BufferedImage;
  • import java.sql.Blob;
  • import java.sql.Connection;
  • import java.sql.DriverManager;
  • import java.sql.PreparedStatement;
  • import java.sql.ResultSet;
  • public class ExcelAddPictureExample {
  • public static void main(String[] args) throws IOException {
  • // 创建工作簿和工作表
  • Workbook workbook = new HSSFWorkbook();
  • Sheet sheet = workbook.createSheet("Sheet1");
  • // 从数据库中获取图片数据(假设图片存储在数据库的blob字段中)
  • Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdatabase", "username", "password");
  • String sql = "SELECT image_blob FROM your_table WHERE id = ?";
  • PreparedStatement pstmt = conn.prepareStatement(sql);
  • pstmt.setInt(1, 1); // 假设要获取id为1的图片
  • ResultSet rs = pstmt.executeQuery();
  • if (rs.next()) {
  • Blob blob = rs.getBlob("image_blob");
  • byte[] data = blob.getBytes(1, (int) blob.length());
  • BufferedImage image = ImageIO.read(new ByteArrayInputStream(data));
  • ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  • ImageIO.write(image, "jpg", outputStream);
  • byte[] imageBytes = outputStream.toByteArray();
  • // 插入图片到工作表中
  • int pictureIndex = workbook.addPicture(imageBytes, HSSFWorkbook.PICTURE_TYPE_JPEG);
  • CreationHelper helper = workbook.getCreationHelper();
  • Drawing drawing = sheet.createDrawingPatriarch();
  • ClientAnchor anchor = helper.createClientAnchor();
  • anchor.setCol1(1); // 设置图片所在列
  • anchor.setRow1(1); // 设置图片所在行
  • anchor.setCol2(3); // 设置图片结束列
  • anchor.setRow2(3); // 设置图片结束行
  • Picture picture = drawing.createPicture(anchor, pictureIndex);
  • picture.resize();
  • }
  • // 将工作簿写入文件
  • try (FileOutputStream fileOut = new FileOutputStream("example.xls")) {
  • workbook.write(fileOut);
  • }
  • workbook.close();
  • conn.close();
  • }
  • }

说明:该代码首先创建了一个Excel工作簿和工作表,然后从数据库中获取图片数据,并将其转换为字节数组,接着使用workbook.addPicture方法将图片添加到工作簿中,并创建一个Drawing对象来设置图片的位置和大小,最后将工作簿写入文件,需要注意的是,这里的代码假设图片存储在数据库的image_blob字段中,并且使用的是MySQL数据库,实际应用中需要根据具体情况进行修改。

三、相关FAQs

1、问:为什么使用POI插入图片后,Word文档中的图片无法显示?

答:这种情况可能是由于POI版本问题导致的,建议升级POI至3.16及以上版本,也可能是在插入图片时,Word文档中关于图片的部分XML没有正确生成,可以尝试自定义XWPFDocument类来解决该问题。

2、问:在Excel中插入图片时,如何避免新添加的图片覆盖原有的图片?

答:在Excel中插入图片时,应始终使用同一个HSSFPatriarch对象来添加图片,避免重复创建HSSFPatriarch对象,如果每次都创建新的HSSFPatriarch对象,可能会导致新添加的图片显示异常,原有的图片也无法正常显示。

本站部分图片及内容来源网络,版权归原作者所有,转载目的为传递知识,不代表本站立场。若侵权或违规联系Email:zjx77377423@163.com 核实后第一时间删除。 转载请注明出处:https://blog.huochengrm.cn/gz/22728.html

分享:
扫描分享到社交APP
上一篇
下一篇