Change image layout or wrap in DOCX with Apache POI

送分小仙女□ 提交于 2019-11-30 09:33:06

问题


I paste image into docx programmatically. But in result the layout does not suit me. Faced a lack of documentation. I need to change image wrap (layout). For example now I have this:

But want this:

UPD1: What I do: iterate through the paragraphs, then through the runs and find certain run with special bookmark. In this run I add picture:

XWPFPicture pic =  run.addPicture(
        new ByteArrayInputStream(picSource),
        Document.PICTURE_TYPE_PNG,
        "pic",
        Units.toEMU(100),
        Units.toEMU(30));

UPD2: Investigated something interesting inside this class:

org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor

method setWrapTight(CTWrapTight var1). May be is it. By still don't know how to apply it to my code.

UPD3: Finally I came to this (currentRun - run with our picture):

    CTWrapTight ctWrapTight = currentRun.getCTR().getDrawingList().get(0).addNewAnchor().addNewWrapTight();
 CTWrapPath ctWrapPath = ctWrapTight.addNewWrapPolygon();

 CTPoint2D ctStart = ctWrapPath.addNewStart();
 ctStart.setX(0L);
 ctStart.setY(0L);

 CTPoint2D ctLineTo1 = ctWrapPath.addNewLineTo();
 CTPoint2D ctLineTo2 = ctWrapPath.addNewLineTo();
 CTPoint2D ctLineTo3 = ctWrapPath.addNewLineTo();

 ctLineTo1.setX(21384L);
 ctLineTo1.setY(20520L);

 ctLineTo2.setX(21384L);
 ctLineTo2.setY(0L);

 ctLineTo3.setX(0L);
 ctLineTo3.setY(0L);

ctWrapTight.setWrapText(STWrapText.BOTH_SIDES);

But it's break down document when I try to open it:

We're sorry. We can't open document because we found a problem with its contents.

Dependency are:

<dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.17</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml-schemas</artifactId>
        <version>3.17</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>ooxml-schemas</artifactId>
        <version>1.3</version>
    </dependency>

回答1:


While you already found the right classes to use - CTAnchor and successors - there is also the need considering the XML Schema definition of anchor. And this states there are many more duty elements required than only the ones which are defining wrapping. So using class by class of org.openxmlformats.schemas.drawingml.x2006 you are probably coding page wise code. My preferred solution for such problems is providing XML having all needed elements updated by some variables. This XML then can be parsed to get the needed object.

Example:

import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.util.Units;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;

public class WordInsertPictures {

 private static CTAnchor getAnchorWithGraphic(CTGraphicalObject graphicalobject, 
                                              String drawingDescr, int width, int height,
                                              int left, int top) throws Exception {

  String anchorXML = 
   "<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "
  +"simplePos=\"0\" relativeHeight=\"0\" behindDoc=\"1\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
  +"<wp:simplePos x=\"0\" y=\"0\"/>"
  +"<wp:positionH relativeFrom=\"column\"><wp:posOffset>"+left+"</wp:posOffset></wp:positionH>"
  +"<wp:positionV relativeFrom=\"paragraph\"><wp:posOffset>"+top+"</wp:posOffset></wp:positionV>"
  +"<wp:extent cx=\""+width+"\" cy=\""+height+"\"/>"
  +"<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/>"
  +"<wp:wrapTight wrapText=\"bothSides\">"
  +"<wp:wrapPolygon edited=\"0\">"
  +"<wp:start x=\"0\" y=\"0\"/>"
  +"<wp:lineTo x=\"0\" y=\"21600\"/>" //Square polygon 21600 x 21600 leads to wrap points in fully width x height
  +"<wp:lineTo x=\"21600\" y=\"21600\"/>"// Why? I don't know. Try & error ;-).
  +"<wp:lineTo x=\"21600\" y=\"0\"/>"
  +"<wp:lineTo x=\"0\" y=\"0\"/>"
  +"</wp:wrapPolygon>"
  +"</wp:wrapTight>"
  +"<wp:docPr id=\"1\" name=\"Drawing 0\" descr=\""+drawingDescr+"\"/><wp:cNvGraphicFramePr/>"
  +"</wp:anchor>";

  CTDrawing drawing = CTDrawing.Factory.parse(anchorXML);
  CTAnchor anchor = drawing.getAnchorArray(0);
  anchor.setGraphic(graphicalobject);
  return anchor;  
 }

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument();
  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run = paragraph.createRun();

  run.setText("The picture in line: ");

  InputStream in = new FileInputStream("samplePict.jpeg");
  run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(100), Units.toEMU(30));
  in.close();  

  run.setText(" text after the picture.");

  paragraph = document.createParagraph();

  run = paragraph.createRun();
  in = new FileInputStream("samplePict.jpeg");
  run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(100), Units.toEMU(30));
  in.close();  
  CTDrawing drawing = run.getCTR().getDrawingArray(0);
  CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();
  CTAnchor anchor = getAnchorWithGraphic(graphicalobject, "samplePict.jpeg", 
                                         Units.toEMU(100), Units.toEMU(30), 
                                         Units.toEMU(30), Units.toEMU(0));
  drawing.setAnchorArray(new CTAnchor[]{anchor});
  drawing.removeInline(0);

  run = paragraph.createRun();
  run.setText("The previous picture is anchored wrapTight. The previous picture is anchored wrapTight. The previous picture is anchored wrapTight. The previous picture is anchored wrapTight. The previous picture is anchored wrapTight. The previous picture is anchored wrapTight.");

  document.write(new FileOutputStream("WordInsertPictures.docx"));
  document.close();
 }
}


来源:https://stackoverflow.com/questions/47673133/change-image-layout-or-wrap-in-docx-with-apache-poi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!