The Office Open XML
formats and also *.docx
as such are ZIP
archives containing XML
files and other files in a directory structure. So if we are curious we can simple unzip them and taking a look into.
Using the default code for adding a picture to a text run in /word/document.xml
we find something like:
<w:r>
<w:t>Picture inline with text:</w:t>
<w:drawing>
<wp:inline distT="0" distR="0" distB="0" distL="0">
<wp:extent cx="1905000" cy="254000"/>
<wp:docPr id="0" name="Drawing 0" descr="samplePict.jpeg"/>
<a:graphic>
<a:graphicData ...
If we are opening this usig Word
and changing the text wrap of the picture to behind text, then in /word/document.xml
we find something like:
<w:r>
<w:drawing>
<wp:anchor allowOverlap="1" behindDoc="1" layoutInCell="1" locked="0" relativeHeight="0" simplePos="0">
<wp:simplePos x="0" y="0"/>
<wp:positionH relativeFrom="column"><wp:posOffset>0</wp:posOffset></wp:positionH>
<wp:positionV relativeFrom="paragraph"><wp:posOffset>0</wp:posOffset></wp:positionV>
<wp:extent cx="1905000" cy="508000"/>
<wp:effectExtent b="0" l="0" r="0" t="0"/><wp:wrapNone/>
<wp:docPr descr="samplePict.jpeg" id="1" name="Drawing 0"/><wp:cNvGraphicFramePr/>
<a:graphic>
<a:graphicData ...
As you see, the first is within an wp:inline
element while the second is within an wp:anchor
element.
Unfortunately the wp:anchor
element cannot be applied using apache poi
until now. So we need to know where to find the low level objects, apache poi
bases on. I found http://grepcode.com a good reference.
Now we can coding the needed things based on those low level objects:
import java.io.*;
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 CreateWordImagesBehindAndInFrontText {
private static CTAnchor getAnchorWithGraphic(CTDrawing drawing /*inline drawing*/ ,
String drawingDescr, boolean behind) throws Exception {
CTGraphicalObject graphicalobject = drawing.getInlineArray(0).getGraphic();
long width = drawing.getInlineArray(0).getExtent().getCx();
long height = drawing.getInlineArray(0).getExtent().getCy();
String anchorXML =
"<wp:anchor xmlns:wp=\"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing\" "
+"simplePos=\"0\" relativeHeight=\"0\" behindDoc=\""+((behind)?1:0)+"\" locked=\"0\" layoutInCell=\"1\" allowOverlap=\"1\">"
+"<wp:simplePos x=\"0\" y=\"0\"/>"
+"<wp:positionH relativeFrom=\"column\"><wp:posOffset>0</wp:posOffset></wp:positionH>"
+"<wp:positionV relativeFrom=\"paragraph\"><wp:posOffset>0</wp:posOffset></wp:positionV>"
+"<wp:extent cx=\""+width+"\" cy=\""+height+"\"/>"
+"<wp:effectExtent l=\"0\" t=\"0\" r=\"0\" b=\"0\"/><wp:wrapNone/>"
+"<wp:docPr id=\"1\" name=\"Drawing 0\" descr=\""+drawingDescr+"\"/><wp:cNvGraphicFramePr/>"
+"</wp:anchor>";
drawing = CTDrawing.Factory.parse(anchorXML);
CTAnchor anchor = drawing.getAnchorArray(0);
anchor.setGraphic(graphicalobject);
return anchor;
}
public static void main(String[] args) throws Exception {
XWPFDocument doc= new XWPFDocument();
XWPFParagraph paragraph;
XWPFRun run;
InputStream in;
CTDrawing drawing;
CTAnchor anchor;
//default
paragraph = doc.createParagraph();
run = paragraph.createRun();
run.setText("Picture inline with text:");
in = new FileInputStream("samplePict.jpeg");
run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(150), Units.toEMU(40));
in.close();
paragraph = doc.createParagraph();
//behind text
paragraph = doc.createParagraph();
run = paragraph.createRun();
in = new FileInputStream("samplePict.jpeg");
run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(150), Units.toEMU(40));
in.close();
drawing = run.getCTR().getDrawingArray(0);
anchor = getAnchorWithGraphic(drawing, "samplePict.jpeg", true /*behind text*/);
drawing.setAnchorArray(new CTAnchor[]{anchor});
drawing.removeInline(0);
run = paragraph.createRun();
run.setText("The above picture is behind the text. ");
paragraph = doc.createParagraph();
//in front of text
paragraph = doc.createParagraph();
run = paragraph.createRun();
in = new FileInputStream("samplePict.jpeg");
run.addPicture(in, Document.PICTURE_TYPE_JPEG, "samplePict.jpeg", Units.toEMU(150), Units.toEMU(40));
in.close();
drawing = run.getCTR().getDrawingArray(0);
anchor = getAnchorWithGraphic(drawing, "samplePict.jpeg", false /*not behind text*/);
drawing.setAnchorArray(new CTAnchor[]{anchor});
drawing.removeInline(0);
run = paragraph.createRun();
run.setText("The above picture is in front of the text. ");
paragraph = doc.createParagraph();
doc.write(new FileOutputStream("CreateWordImagesBehindAndInFrontText.docx"));
doc.close();
}
}
XWPFRun
seems to have only simple text formatting. The closest I found is this: stackoverflow.com/q/47673133/2886891 - but it is soooo an ugly solution :) – Honza ZidekOffice Open **XML**
is the new file format forMicrosoft Office
. And answers here, at least my answers, are never thought to be ready-to-use productive code but to be minimal working examples showing the principles. Of course in productive code this should be done more flexible and less based on fixed XML strings. But, as said in my answer, when using class by class oforg.openxmlformats.schemas.drawingml.x2006
you are probably coding page wise code. Not applicable for an answer here. – Axel Richter