Using my code provided in How to replace <w:sdt> Xml in Word Doc using Apache POI as XWPFSDT and XWPFSDTContent object is read-only one could extend the SDTContentControl
like so:
...
public void setContent(org.apache.poi.xwpf.usermodel.XWPFParagraph paragraph) {
if (this.object instanceof CTSdtBlock) {
CTSdtBlock ctSdtBlock = (CTSdtBlock)this.object;
if (ctSdtBlock.isSetSdtContent()) {
CTSdtContentBlock sdtContentBlock = ctSdtBlock.getSdtContent();
CTP ctP = paragraph.getCTP();
sdtContentBlock.setPArray(new CTP[]{ctP});
}
} else if (this.object instanceof CTSdtRun) {
CTSdtRun ctSdtRun = (CTSdtRun)this.object;
if (ctSdtRun.isSetSdtContent()) {
CTSdtContentRun sdtContentRun = ctSdtRun.getSdtContent();
CTR[] ctRArray = paragraph.getCTP().getRArray();
sdtContentRun.setRArray(ctRArray);
}
} else if (this.object instanceof CTSdtCell) {
CTSdtCell ctSdtCell = (CTSdtCell)this.object;
if (ctSdtCell.isSetSdtContent()) {
CTSdtContentCell sdtContentCell = ctSdtCell.getSdtContent();
for (int c = 0; c < sdtContentCell.getTcList().size(); c++) {
CTTc ctTc = sdtContentCell.getTcList().get(c);
CTP ctP = paragraph.getCTP();
ctTc.setPArray(new CTP[]{ctP});
}
}
}
}
...
public void setContent(Object content) {
if (content instanceof String) {
this.setContent((String)content);
} else if (content instanceof Calendar) {
this.setContent((Calendar)content);
} else if (content instanceof BigDecimal) {
this.setContent((BigDecimal)content);
} else if (content instanceof org.apache.poi.xwpf.usermodel.XWPFParagraph) {
this.setContent((org.apache.poi.xwpf.usermodel.XWPFParagraph)content);
//} else if (content instanceof ...) {
//ToDo
} else {
this.setContent(String.valueOf(content));
}
}
...
After this one of the objects in Object[] contents
in WordFillContentControls
can be a XWPFParagraph
like so:
...
Object[] contents = new Object[]{
"Axel Richter", "male", new GregorianCalendar(2022, 0, 1), BigDecimal.valueOf(1234.56),
"Lorem ipsum semit dolor ... dolor semit ...", "Blah blah", "Blubb blubb",
new GregorianCalendar(1964, 11, 21), "My choice"
};
XWPFParagraph paragraph = new XWPFParagraph(org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP.Factory.newInstance(), new XWPFDocument());
XWPFRun run = paragraph.createRun();
run.setText("Lorem ipsum");
run = paragraph.createRun();
run.setText(" semit dolor ");
run.setColor("FF0000");
run.setFontSize(24);
run = paragraph.createRun();
run.setText("... dolor semit ...");
//contents[0] = paragraph;
contents[4] = paragraph;
//contents[6] = paragraph;
//contents[8] = paragraph;
...
So one is able to use all the formatting possibilities of XWPFRun
.
See complete example in my above linked answer to get what Object[] contents
is for.
The XWPFParagraph paragraph
gets created outside the current used XWPFDocument
in a new XWPFDocument()
because it does not belong to the current used document. It only transports the formatted rich text in its XWPFRuns
to be used in my SDTContentControl
then.
The fully correct way would be to make the block contents of the SDTContentControl
implement IBody
and the inline (run) contents of the SDTContentControl
make implement IRunBody
. Then one could create XWPFparagraph
s respectively XWPFRun
s directly there. But that would lead to too much code to provide it in an answer here.