Reputation: 46
I need to create a WedgeRectCallout
shape in a Word document using Apache POI. I am not able to find any reference to this in Apache POI
Using the link you can see the WedgeRectCallout image
Also, the link shows how to add a textbox in a Word document, but not a shape.
In C#, I can do the same using Spire.Doc
library and writing below code:
ShapeObject Shape1 = para1.AppendShape(30, 50, ShapeType.WedgeRectCallout);
Upvotes: 0
Views: 1298
Reputation: 61945
The newest Word
versions are using wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape"
for shapes. But this it not supported by neither the low level ooxml-schemas
nor apache poi
. It would only be possible by manipulating the XML directly on very low level base.
But Word
also uses Vector Markup Language (VML)
as a fallback. And this could be done as ooxml-schemas-1.4
provides com.microsoft.schemas.vml
. This also will be the most compatible way.
You can read about Vector Markup Language (VML). The simplest callout shape will be the following XML
<w:pict>
<v:shape coordsize="21600,21600" adj="7200,21600" path="m 1,1 l 1,14400, 7200,14400, @0,@1, 14400,14400, 21600,14400, 21600,1 x e" style="position:absolute;margin-left:1in;margin-top:-150px;width:100px;height:150px;z-index:251659264;visibility:visible;rotation:0;" strokecolor="#0000FF" fillcolor="yellow">
<v:formulas>
<v:f eqn="val #0"/>
<v:f eqn="val #1"/>
</v:formulas>
<v:handles><v:h position="#0,#1"/></v:handles>
<v:path textboxrect="1,1,21600,14400"/>
<v:textbox>
<w:txbxContent><w:p><w:r><w:t>The callout</w:t><w:br/></w:r><w:r><w:t>text...</w:t><w:br/></w:r></w:p>
</w:txbxContent>
</v:textbox>
</v:shape>
</w:pict>
As you see, the outline of the shape is determined by a path
. So creating other shapes will also be possible if one has understand how the path
works.
Example code for creating callout shapes:
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTxbxContent;
import com.microsoft.schemas.vml.CTGroup;
import com.microsoft.schemas.vml.CTShape;
import com.microsoft.schemas.vml.CTFormulas;
import com.microsoft.schemas.vml.CTTextbox;
import org.w3c.dom.Node;
public class CreateWordShapes {
public static void appendCalloutShape(XWPFRun run, String left, String top, String width, String height,
String strokecolor, String fillcolor, String calloutext, boolean hashandles) throws Exception {
CTGroup ctGroup = CTGroup.Factory.newInstance();
CTShape ctShape = ctGroup.addNewShape();
ctShape.setCoordsize("21600,21600");
if (hashandles) { //is not Libreoffice Writer compatible
ctShape.setAdj("" + 21600*1/3 + ",21600");
CTFormulas cTFormulas = ctShape.addNewFormulas();
cTFormulas.addNewF().setEqn("val #0");
cTFormulas.addNewF().setEqn("val #1");
ctShape.setPath2("m 1,1 l 1," + 21600*2/3 + ", " + 21600*1/3 + "," + 21600*2/3 + ", @0,@1, " + 21600*2/3 + "," + 21600*2/3 + ", 21600," + 21600*2/3 + ", 21600,1 x e");
ctShape.addNewHandles().addNewH().setPosition("#0,#1");
} else { // is Libreoffice Writer compatible
ctShape.setPath2("m 1,1 l 1," + 21600*2/3 + ", " + 21600*1/3 + "," + 21600*2/3 + ", " + 21600*1/3 + ",21600, " + 21600*2/3 + "," + 21600*2/3 + ", 21600," + 21600*2/3 + ", 21600,1 x e");
}
ctShape.addNewPath().setTextboxrect("1,1,21600," + 21600*2/3);
ctShape.setStyle("position:absolute;margin-left:" + left + ";margin-top:" + top + ";width:" + width + ";height:" + height + ";z-index:251659264;visibility:visible;rotation:0;");
ctShape.setStrokecolor(strokecolor);
ctShape.setFillcolor(fillcolor);
CTTextbox cTTextbox = ctShape.addNewTextbox();
CTTxbxContent ctTxbxContent = cTTextbox.addNewTxbxContent();
XWPFParagraph textboxparagraph = new XWPFParagraph(ctTxbxContent.addNewP(), run.getDocument());
XWPFRun textboxrun = null;
String[] lines = calloutext.split("\n");
for (int i = 0; i < lines.length; i++) {
textboxrun = textboxparagraph.createRun();
textboxrun.setText(lines[i]);
textboxrun.addBreak();
}
Node ctGroupNode = ctGroup.getDomNode();
CTPicture ctPicture = CTPicture.Factory.parse(ctGroupNode);
CTR cTR = run.getCTR();
cTR.addNewPict();
cTR.setPictArray(0, ctPicture);
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("Callout shape over text: Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor Lorem ipsum semit dolor.");
appendCalloutShape(run, "200pt", "0", "1in", "1in", "black", "#00FF00", "The callout\ntext...", false);
paragraph = document.createParagraph();
paragraph = document.createParagraph();
paragraph = document.createParagraph();
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Callout shape:");
appendCalloutShape(run, "1in", "-150px", "100px", "150px", "#0000FF", "yellow", "The callout\ntext...", true);
FileOutputStream out = new FileOutputStream("test.docx");
document.write(out);
out.close();
document.close();
}
}
Result:
Note: This needs apache poi 4.0.1
and ooxml-schemas-1.4.jar
to be in the class path.
Upvotes: 1