如何在Apache POI中设置docx文档的图片浮于文字上方?
在Apache POI中设置图片浮于文字上方的实现方案
我明白你想用Apache POI给docx插入图片并设置浮于文字上方的需求——确实,基础的addPicture方法默认插入的是嵌入式图片,要实现浮动效果得操作POI底层的OOXML对象。下面给你一步步的解决方法:
首先,先把你现有的基础代码贴出来方便对比:
XWPFDocument document = new XWPFDocument(); XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); run.addPicture(new FileInputStream(img), format, img, Units.toEMU(width), Units.toEMU(height)); FileOutputStream outputStream = new FileOutputStream(doc); document.write(outputStream);
这段代码插入的图片是嵌入式的,会跟着文字流走。要让图片浮于文字上方,我们需要把它转换成浮动式图片,核心是操作底层的CTDrawing和锚点对象。下面是完整的实现代码:
完整实现代码
import org.apache.poi.xwpf.usermodel.*; import org.apache.poi.util.Units; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.*; import java.io.*; public class DocxFloatingImageDemo { public static void main(String[] args) throws Exception { String imgPath = "你的图片路径.png"; // 替换成你的图片路径 String docPath = "输出文档.docx"; // 替换成输出文档路径 int imgWidth = 150; // 图片宽度(磅) int imgHeight = 150;// 图片高度(磅) addFloatingImageToDocx(imgPath, docPath, imgWidth, imgHeight); } public static void addFloatingImageToDocx(String imgPath, String docPath, int width, int height) throws Exception { try (XWPFDocument document = new XWPFDocument()) { // 创建段落和Run对象 XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); // 先插入嵌入式图片,这是为了复用POI的资源关联逻辑 int pictureFormat = XWPFDocument.PICTURE_TYPE_PNG; // 图片类型:PNG/JPG对应不同常量 run.addPicture(new FileInputStream(imgPath), pictureFormat, imgPath, Units.toEMU(width), Units.toEMU(height)); // 获取底层的Drawing和Inline对象(嵌入式图片的容器) CTDrawing drawing = run.getCTR().getDrawingArray(0); CTInline inline = drawing.getInlineArray(0); // 创建相对锚点,用于设置浮动图片的位置 CTRelativeAnchor relativeAnchor = CTRelativeAnchor.Factory.newInstance(); // 设置图片相对于页边距的位置(可根据需求调整数值) CTAnchorPos leftMargin = relativeAnchor.addNewLeft(); leftMargin.setRelativeFrom(STRelativeFromMargin.LEFT); leftMargin.setVal(Units.toEMU(50)); // 左边距50磅 CTAnchorPos topMargin = relativeAnchor.addNewTop(); topMargin.setRelativeFrom(STRelativeFromMargin.TOP); topMargin.setVal(Units.toEMU(100)); // 上边距100磅 // 设置图片的尺寸 CTExtent extent = relativeAnchor.addNewExtent(); extent.setCx(Units.toEMU(width)); extent.setCy(Units.toEMU(height)); // 关键:设置环绕方式为"浮于文字上方" CTWrap wrapSetting = relativeAnchor.addNewWrap(); wrapSetting.setType(STWrapType.TOP_AND_BOTTOM); // 上下环绕,实现浮于文字上方的效果 wrapSetting.setAllowOverlap(true); // 允许图片覆盖文字 // 将原嵌入式图片的内容复制到锚点中 relativeAnchor.setGraphic(inline.getGraphic()); // 替换原来的嵌入式容器为浮动锚点 drawing.removeInline(0); drawing.setAnchorArray(0, relativeAnchor); // 写入并保存文档 try (FileOutputStream outputStream = new FileOutputStream(docPath)) { document.write(outputStream); } } } }
关键步骤说明
- 先插嵌入式图片:直接创建浮动图片需要手动处理图片资源的关联,先插入嵌入式再转换会更简便,POI会自动帮我们处理资源的存储。
- 操作底层OOXML对象:POI的高层API没有直接提供设置浮动图片的方法,所以我们需要用到
CTDrawing、CTRelativeAnchor这些底层的OOXML类。 - 设置环绕方式:
wrapSetting.setType(STWrapType.TOP_AND_BOTTOM)配合allowOverlap(true)是实现“浮于文字上方”的核心,这样图片会覆盖在文字层之上,文字从图片的上下方绕过。 - 定位调整:你可以修改
leftMargin和topMargin的数值来调整图片在页面上的位置,单位是磅,通过Units.toEMU转换成POI需要的EMU单位。
额外提示
- 如果需要绝对定位(相对于页面固定位置),可以用
CTAbsoluteAnchor替代CTRelativeAnchor,设置相对于页面的坐标即可。 - 图片类型要对应正确:JPG图片用
XWPFDocument.PICTURE_TYPE_JPEG,PNG用PICTURE_TYPE_PNG,避免格式错误。
内容的提问来源于stack exchange,提问作者JDChi
相关产品推荐
相关产品推荐

