【问题标题】:Change image layout or wrap in DOCX with Apache POI使用 Apache POI 更改图像布局或在 DOCX 中换行
【发布时间】:2017-12-08 22:45:04
【问题描述】:

我以编程方式将图像粘贴到 docx 中。但结果布局不适合我。面临缺乏文件。 我需要更改图像换行(布局)。例如现在我有这个:

但是想要这个:

UPD1:我所做的:遍历段落,然后遍历运行并找到带有特殊书签的特定运行。在这次运行中,我添加了图片:

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

UPD2:在这个类中调查了一些有趣的东西:

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

方法setWrapTight(CTWrapTight var1)。可能是它。仍然不知道如何将它应用到我的代码中。

UPD3:最后我想到了这个(currentRun - 用我们的图片运行):

    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);

但是当我尝试打开它时它会分解文档:

我们很抱歉。我们无法打开文档,因为我们发现了一个问题 它的内容。

依赖是:

<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>

【问题讨论】:

  • “但我仍然不知道如何将它应用到我的代码中。”:在那一行代码中?这是不可能的。那时你将需要更多的代码。展示一个完整的示例,说明如何添加与文本一致的图片。然后我将向您展示如何添加带有文字换行的图片。
  • @AxelRichter 我更新了问题

标签: java apache-poi docx


【解决方案1】:

虽然您已经找到要使用的正确类 - CTAnchor 和后继类 - 还需要考虑 XML Schema definition of anchor。这表明除了定义包装的那些之外,还需要更多的职责元素。因此,逐个使用org.openxmlformats.schemas.drawingml.x2006,您可能正在编写页面代码。对于此类问题,我首选的解决方案是提供XML,其中所有需要的元素都由一些变量更新。然后可以解析这个XML,得到需要的对象。

例子:

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();
 }
}

【讨论】:

  • 感谢您的瓦里安,我一定会在我休假后尝试这个。但现在我找到了临时解决方案。我在制作.addPicture() 之前添加了break,并且需要图像布局。但之前有休息。
  • @Optio:您的问题是关于将布局选项从“与文本对齐”更改为“文本环绕 - 紧”。这绝对不能通过在图片运行之前添加换行符来实现。
  • 正如我所说 - 这是临时解决方案。但没有这个 - 图像的高度等于线的高度(运行)。在以某种方式帮助之前添加一些休息时间。我在第一次评论时没有说对 - 当然布局没有改变,但它在视觉上产生了预期的效果。
猜你喜欢
  • 1970-01-01
  • 2020-12-13
  • 2017-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-16
相关资源
最近更新 更多