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

解决方法:升级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对象,可能会导致新添加的图片显示异常,原有的图片也无法正常显示。