Apache POI:如何在MS Word文档的指定位置插入图片?
实现Word文档中图片的绝对定位
要在Apache POI的XWPF中实现图片的绝对位置(如距左侧5cm、顶部15cm),需要直接操作底层的OOXML对象,因为XWPF的高层API没有提供直接设置绝对定位的方法。以下是具体实现步骤和代码:
核心思路
默认添加的图片是嵌入式(inline)的,会跟随文本流。要设置绝对位置,需要将图片转为浮动式(floating),通过CTDrawing、CTPosH、CTPosV等OOXML对象来定义相对于页面的偏移量。
完整代码示例
import org.apache.poi.util.Units; import org.apache.poi.xwpf.usermodel.*; import org.openxmlformats.schemas.wordprocessingml.x2006.main.*; import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.*; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; public class ImageAbsolutePosition { public static void main(String[] args) throws Exception { XWPFDocument document = new XWPFDocument(); // 1. 创建段落和Run,添加图片 XWPFParagraph paragraph = document.createParagraph(); XWPFRun run = paragraph.createRun(); File imgFile = new File("/Users/mahdi/Downloads/unnamed.jpg"); try (FileInputStream imgStream = new FileInputStream(imgFile)) { run.addPicture(imgStream, PictureType.JPEG, imgFile.getName(), Units.pixelToEMU(400), Units.pixelToEMU(200)); } // 2. 获取图片对应的CTPicture对象 CTPicture ctPicture = run.getCTR().getDrawingArray(0).getInlineArray(0).getGraphic().getGraphicData().getPicArray(0); // 3. 创建浮动式的CTDrawing对象 CTDrawing drawing = CTDrawing.Factory.newInstance(); CTAnchor anchor = drawing.addNewAnchor(); // 设置浮动属性:允许文字环绕,锁定位置 anchor.setAllowOverlap(true); anchor.setLocked(false); anchor.setBehindDoc(false); anchor.setSimplePos(false); // 4. 设置水平位置:距页面左侧5cm CTPosH posH = anchor.addNewPosH(); posH.setVal(STPositionH.RELATIVE_TO_PAGE); posH.setOffset(cmToEmu(5)); // 转换厘米为EMU(1cm=360000 EMU) // 5. 设置垂直位置:距页面顶部15cm CTPosV posV = anchor.addNewPosV(); posV.setVal(STPositionV.RELATIVE_TO_PAGE); posV.setOffset(cmToEmu(15)); // 设置图片大小(和添加时的尺寸一致) CTExtent extent = anchor.addNewExtent(); extent.setCx(Units.pixelToEMU(400)); extent.setCy(Units.pixelToEMU(200)); // 将图片添加到浮动锚点中 anchor.getGraphic().getGraphicData().setPicArray(0, ctPicture); // 6. 替换原来的inline drawing为浮动drawing run.getCTR().setDrawingArray(0, drawing); // 保存文档 try (FileOutputStream out = new FileOutputStream("output.docx")) { document.write(out); } document.close(); } // 辅助方法:厘米转EMU(Apache POI中使用的单位) private static long cmToEmu(double cm) { return Math.round(cm * 360000); } }
关键说明
- 单位转换:OOXML中使用EMU(English Metric Unit)作为尺寸单位,1厘米=360000 EMU,我们通过
cmToEmu方法完成转换。 - 位置参考:
STPositionH.RELATIVE_TO_PAGE和STPositionV.RELATIVE_TO_PAGE表示位置相对于页面边界,你也可以根据需求改为相对于段落、边距等。 - 环绕方式:示例中设置
allowOverlap=true允许文字覆盖图片,若需要文字环绕图片,可以添加CTWrap对象进一步配置。
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

