POI插word图片居右

XWPFRun的addPicture()经常用于图片插入,然而设置图片布局选项的时候却不好使(除非你是用模板来替换生成word)。因为XWPFRun提供的addPicture()方法插入的是inline类型的图片,而支持设置水平居右,环绕型,四周型,上下型等板式的是anchor的图片如下图所示结构:
<w:r>
				<w:rPr>
					<w:rFonts w:hint="eastAsia" w:eastAsiaTheme="minorEastAsia"/>
					<w:lang w:eastAsia="zh-CN"/>
				</w:rPr>
				<w:drawing>
					<wp:anchor distT="0" distB="0" distL="114935" distR="114935" simplePos="0" relativeHeight="251658240" behindDoc="0" locked="0" layoutInCell="1" allowOverlap="1">
						<wp:simplePos x="0" y="0"/>
						<wp:positionH relativeFrom="column">
							<wp:align>right</wp:align>
						</wp:positionH>
						<wp:positionV relativeFrom="paragraph">
							<wp:posOffset>28575</wp:posOffset>
						</wp:positionV>
						<wp:extent cx="1599565" cy="2513965"/>
						<wp:effectExtent l="0" t="0" r="635" b="635"/>
						<wp:wrapSquare wrapText="bothSides"/>
						<wp:docPr id="1" name="图片 1" descr="一拳"/>
						<wp:cNvGraphicFramePr>
							<a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
						</wp:cNvGraphicFramePr>
						<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="图片 1" descr="一拳"/>
										<pic:cNvPicPr>
											<a:picLocks noChangeAspect="1"/>
										</pic:cNvPicPr>
									</pic:nvPicPr>
									<pic:blipFill>
										<a:blip r:embed="rId4"/>
										<a:stretch>
											<a:fillRect/>
										</a:stretch>
									</pic:blipFill>
									<pic:spPr>
										<a:xfrm>
											<a:off x="0" y="0"/>
											<a:ext cx="1599565" cy="2513965"/>
										</a:xfrm>
										<a:prstGeom prst="rect">
											<a:avLst/>
										</a:prstGeom>
									</pic:spPr>
								</pic:pic>
							</a:graphicData>
						</a:graphic>
					</wp:anchor>
				</w:drawing>
			</w:r>

不知道为什么POI没有提供anchor类的图片插入功能,那手动撸一个:重写org.apache.poi.xwpf.usermodel.XWPFRun类,新增addAnchorPicture方法:

/**
     * Adds a picture to the run. This method handles
     * attaching the picture data to the overall file.
     *
     * @param pictureData The raw picture data
     * @param pictureType The type of the picture, eg {@link Document#PICTURE_TYPE_JPEG}
     * @param width       width in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
     * @param height      height in EMUs. To convert to / from points use {@link org.apache.poi.util.Units}
     * @throws InvalidFormatException If the format of the picture is not known.
     * @throws IOException            If reading the picture-data from the stream fails.
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_EMF
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_WMF
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PICT
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_JPEG
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_PNG
     * @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB
     */
    public XWPFPicture addAnchorPicture(InputStream pictureData, int pictureType, String filename, int width, int height)
            throws InvalidFormatException, IOException {
        String relationId;
        XWPFPictureData picData;

        // Work out what to add the picture to, then add both the
        //  picture and the relationship for it
        // TODO Should we have an interface for this sort of thing?
        if (parent.getPart() instanceof XWPFHeaderFooter) {
            XWPFHeaderFooter headerFooter = (XWPFHeaderFooter) parent.getPart();
            relationId = headerFooter.addPictureData(pictureData, pictureType);
            picData = (XWPFPictureData) headerFooter.getRelationById(relationId);
        } else {
            @SuppressWarnings("resource")
            XWPFDocument doc = parent.getDocument();
            relationId = doc.addPictureData(pictureData, pictureType);
            picData = (XWPFPictureData) doc.getRelationById(relationId);
        }

        // Create the drawing entry for it
        try {
            CTDrawing drawing = run.addNewDrawing();
            final CTAnchor anchor = drawing.addNewAnchor();

            // Do the fiddly namespace bits on the inline
            // (We need full control of what goes where and as what)
            String xml =
                    "<a:graphic xmlns:a=\"" + CTGraphicalObject.type.getName().getNamespaceURI() + "\">" +
                            "<a:graphicData uri=\"" + CTPicture.type.getName().getNamespaceURI() + "\">" +
                            "<pic:pic xmlns:pic=\"" + CTPicture.type.getName().getNamespaceURI() + "\" />" +
                            "</a:graphicData>" +
                            "</a:graphic>";
            InputSource is = new InputSource(new StringReader(xml));
            org.w3c.dom.Document doc = DocumentHelper.readDocument(is);
            anchor.set(XmlToken.Factory.parse(doc.getDocumentElement(), DEFAULT_XML_OPTIONS));

            // Setup the inline
            anchor.setDistT(0);
            anchor.setDistR(0);
            anchor.setDistB(0);
            anchor.setDistL(0);

            CTNonVisualDrawingProps docPr = anchor.addNewDocPr();
            long id = getParent().getDocument().getDrawingIdManager().reserveNew();
            docPr.setId(id);
            /* This name is not visible in Word 2010 anywhere. */
            docPr.setName("Drawing " + id);
            docPr.setDescr(filename);

            CTPositiveSize2D extent = anchor.addNewExtent();
            extent.setCx(width);
            extent.setCy(height);

            // Grab the picture object
            CTGraphicalObject graphic = anchor.getGraphic();
            CTGraphicalObjectData graphicData = graphic.getGraphicData();
            CTPicture pic = getCTPictures(graphicData).get(0);

            // Set it up
            CTPictureNonVisual nvPicPr = pic.addNewNvPicPr();

            CTNonVisualDrawingProps cNvPr = nvPicPr.addNewCNvPr();
            /* use "0" for the id. See ECM-576, 20.2.2.3 */
            cNvPr.setId(0L);
            /* This name is not visible in Word 2010 anywhere */
            cNvPr.setName("Picture " + id);
            cNvPr.setDescr(filename);

            CTNonVisualPictureProperties cNvPicPr = nvPicPr.addNewCNvPicPr();
            cNvPicPr.addNewPicLocks().setNoChangeAspect(true);

            CTBlipFillProperties blipFill = pic.addNewBlipFill();
            CTBlip blip = blipFill.addNewBlip();
            blip.setEmbed(parent.getPart().getRelationId(picData));
            blipFill.addNewStretch().addNewFillRect();

            CTShapeProperties spPr = pic.addNewSpPr();
            CTTransform2D xfrm = spPr.addNewXfrm();

            CTPoint2D off = xfrm.addNewOff();
            off.setX(0);
            off.setY(0);

            CTPositiveSize2D ext = xfrm.addNewExt();
            ext.setCx(width);
            ext.setCy(height);

            CTPresetGeometry2D prstGeom = spPr.addNewPrstGeom();
            prstGeom.setPrst(STShapeType.RECT);
            prstGeom.addNewAvLst();

            // Finish up
            XWPFPicture xwpfPicture = new XWPFPicture(pic, this);
            pictures.add(xwpfPicture);
            return xwpfPicture;
        } catch (XmlException | SAXException e) {
            throw new IllegalStateException(e);
        }
    }

好了这个方法新增的图片可以设置各种版式了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值