Reputation: 49
i am trying insert picture caption using Apache POI, but i dont have any ideas for it. I'm using
doc.createParagraph().createRun().addPicture(input,
Document.PICTURE_TYPE_PNG, "picture.png",
Units.pixelToEMU(603), Units.pixelToEMU(226));
to insert picture and now i would like to add caption for it to be able create Table of Figure. I have tried use some styles paragraph.setStyle("Legends"); but it changes only fonts i doesnt work like with "Header1" (I have template). I have looked into styles.xml (in my template where i inserted picture caption using word) and there is
-<w:style w:type="paragraph" w:styleId="Legenda">
<w:name w:val="caption"/>
<w:basedOn w:val="Normalny"/>
<w:next w:val="Normalny"/>
<w:unhideWhenUsed/>
<w:qFormat/>
so it looks like i just have to set paragraph w:name w:val as "caption". Am i right? How can i reach it?
Upvotes: 0
Views: 1671
Reputation: 1064
right... so in the document xml belonging to a document generated by @AxelRichter 's code, i've manually inserted a table of figures. The resulting xml extracts show that ms word generates this slightly differently...
axel's result:
<w:p w:rsidR="009B13D9" w:rsidRDefault="009B13D9">
<w:pPr>
<w:pStyle w:val="TableofFigures"/>
<w:tabs>
<w:tab w:val="right" w:leader="dot" w:pos="9350"/>
</w:tabs>
<w:rPr>
<w:noProof/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:t>Picture 2: Description of sample picture 2</w:t>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:tab/>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:fldChar w:fldCharType="begin"/>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:instrText xml:space="preserve"> PAGEREF _Toc521591239 \h </w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:fldChar w:fldCharType="separate"/>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:t>1</w:t>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
</w:rPr>
<w:fldChar w:fldCharType="end"/>
</w:r>
</w:p>
manual insert result
<w:p w:rsidR="009B13D9" w:rsidRDefault="009B13D9">
<w:pPr>
<w:pStyle w:val="TableofFigures"/>
<w:tabs>
<w:tab w:val="right" w:leader="dot" w:pos="9350"/>
</w:tabs>
<w:rPr>
<w:noProof/>
</w:rPr>
</w:pPr>
<w:hyperlink w:anchor="_Toc521591266" w:history="1">
<w:r w:rsidRPr="003A5F7D">
<w:rPr>
<w:rStyle w:val="Hyperlink"/>
<w:noProof/>
</w:rPr>
<w:t>Picture 2: Description</w:t>
</w:r>
<w:bookmarkStart w:id="4" w:name="_GoBack"/>
<w:bookmarkEnd w:id="4"/>
<w:r w:rsidRPr="003A5F7D">
<w:rPr>
<w:rStyle w:val="Hyperlink"/>
<w:noProof/>
</w:rPr>
<w:t xml:space="preserve"> of sample picture 2</w:t>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
<w:webHidden/>
</w:rPr>
<w:tab/>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
<w:webHidden/>
</w:rPr>
<w:fldChar w:fldCharType="begin"/>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
<w:webHidden/>
</w:rPr>
<w:instrText xml:space="preserve"> PAGEREF _Toc521591266 \h </w:instrText>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
<w:webHidden/>
</w:rPr>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
<w:webHidden/>
</w:rPr>
<w:fldChar w:fldCharType="separate"/>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
<w:webHidden/>
</w:rPr>
<w:t>1</w:t>
</w:r>
<w:r>
<w:rPr>
<w:noProof/>
<w:webHidden/>
</w:rPr>
<w:fldChar w:fldCharType="end"/>
</w:r>
</w:hyperlink>
</w:p>
Having skimmed this thing, it seems that the run should be enveloped in a hyperlink object. ... and there are several subtle differences just to make things interesting.
Upvotes: 0
Reputation: 416
Taking it a step further, I needed to have the caption figure sequence follow my header sequencing. So for header1/header2 I neeed captions to be 1.1.1, 1.1.2, etc. Then adding another header2 they would restart at 1.2.1, 1.2.2. Here is the code for that. It also does not require you to create a table of contents as the answer from Richter (who I thank for pointing me in the right direction with this).
public void addCaption(String text) {
paragraph = doc.createParagraph();
paragraph.setStyle(STYLE_CAPTION);
paragraph.setSpacingAfter(0); // Set spacing after to 0. So caption will follow immediately under the figure.
run = paragraph.createRun();
run.setText("Figure ");
CTR ctr;
CTRPr ctrpr;
CTText ctText;
CTSimpleField seq = getParagraph().getCTP().addNewFldSimple();
String figureText1 = " STYLEREF 2 \\s ";
seq.setInstr(figureText1);
ctr = seq.addNewR();
ctrpr = ctr.addNewRPr();
ctrpr.addNewNoProof();
ctText = ctr.addNewT();
ctText.setStringValue("1");
ctr = paragraph.getCTP().addNewR();
ctr.addNewNoBreakHyphen();
seq = getParagraph().getCTP().addNewFldSimple();
String figureText = " SEQ Figure \\* ARABIC \\s 2 ";
seq.setInstr(figureText);
ctr = seq.addNewR();
ctrpr = ctr.addNewRPr();
ctrpr.addNewNoProof();
ctText = ctr.addNewT();
ctText.setStringValue("1");
run = paragraph.createRun(); // needed or numbers are at end, ie Figure : some text1.1
run.setText(": " + text);
}
Upvotes: 0
Reputation: 61915
What one should know about how the inserting a table of figures works in Word
:
When we add captions, then each caption paragraph contains a sequence field {SEQ figure \* ARABIC}
. The name "figure" is the name of the sequence field. Then, if a table of figures shall be created, Word
collects all paragraphs which contains such a field to build the table of figures from those.
Until now (apache poi
version 3.17) does not provide adding captions to figures nor inserting or creating a table of figures, at least as far as I know. So we must do it ourself using the low level CTSimpleField.
Example:
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.Units;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSimpleField;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
public class CreateWordTableOfFigures {
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph;
XWPFRun run;
InputStream in;
CTSimpleField seq;
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Document containing figures");
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Lorem ipsum...");
//create paragraph containing figure
paragraph = document.createParagraph();
paragraph.setSpacingAfter(0); //Set spacing after to 0. So caption will follow immediately under the figure.
run = paragraph.createRun();
in = new FileInputStream("samplePict1.png");
run.addPicture(in, Document.PICTURE_TYPE_PNG, "samplePict1.png", Units.toEMU(150), Units.toEMU(100));
in.close();
paragraph = document.createParagraph(); //caption for figure
run = paragraph.createRun();
run.setText("Picture ");
seq = paragraph.getCTP().addNewFldSimple();
seq.setInstr("SEQ figure \\* ARABIC"); //This field is important for creating the table of figures then.
run = paragraph.createRun();
run.setText(": Description of sample picture 1");
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Lorem ipsum...");
paragraph = document.createParagraph();
paragraph.setSpacingAfter(0);
run = paragraph.createRun();
in = new FileInputStream("samplePict2.png");
run.addPicture(in, Document.PICTURE_TYPE_PNG, "samplePict1.png", Units.toEMU(150), Units.toEMU(100));
in.close();
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Picture ");
seq = paragraph.getCTP().addNewFldSimple();
seq.setInstr("SEQ figure \\* ARABIC");
run = paragraph.createRun();
run.setText(": Description of sample picture 2");
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("Index of figures:");
//Create table of figures field. Word will updating that field while opening the file.
paragraph = document.createParagraph();
CTSimpleField toc = paragraph.getCTP().addNewFldSimple();
toc.setInstr("TOC \\c \"figure\" \\* MERGEFORMAT");
toc.setDirty(STOnOff.TRUE); //set dirty to forcing update
FileOutputStream out = new FileOutputStream("CreateWordTableOfFigures.docx");
document.write(out);
document.close();
}
}
Note, the inserted field {TOC \c "figure" \* MERGEFORMAT}
, because it is set dirty, only forces updating that field while opening the file in Word
. Creating the whole table of figures using apache poi
without forcing Word
doing that will be much more effort.
Upvotes: 4