Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

apache poi - How to set table of content's font style including font color, font size and bold in poi word?

I using doc.createTOC(); to generate table of content in poi word(XWPF), and using addCustomHeadingStyle(doc, ChapterLvl.LVL_1.style, 1); to generate headings Content, dotted line and page number. But I want to set different heading level's headings Content have different font size,font color, bold, and dotted line and page number have same style with its corresponding heading content, like the picture attachment, can someone give me some advice how to do that?

private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {
        CTStyle ctStyle = CTStyle.Factory.newInstance();
        ctStyle.setStyleId(strStyleId);
        CTString styleName = CTString.Factory.newInstance();
        styleName.setVal(strStyleId);
        ctStyle.setName(styleName);
        CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
        indentNumber.setVal(BigInteger.valueOf(headingLevel));
        ctStyle.setUiPriority(indentNumber);
        CTOnOff onoffnull = CTOnOff.Factory.newInstance();
        ctStyle.setUnhideWhenUsed(onoffnull);
        ctStyle.setQFormat(onoffnull);
        CTPPr ppr = CTPPr.Factory.newInstance();
        ppr.setOutlineLvl(indentNumber);
        ctStyle.setPPr(ppr);
        XWPFStyle style = new XWPFStyle(ctStyle);
        XWPFStyles styles = docxDocument.createStyles();
        style.setType(STStyleType.PARAGRAPH);
        styles.addStyle(style);
    }

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I even cannot get valuable results using XWPFDocument.createTOC() (fields for page numbers are wrong for example). So I have never used that. What I can say is that XWPFDocument.createTOC() currently not creates a "Table of Contents" like Word itself will do. So after opening in Word it will not be recognized as TOC from Word GUI.

But if the question is only about the styles, then that can be answered. There must be styles named "toc 1", "toc 2", "toc 3", ..., "toc n" present for each heading level. This can be achieved using XML like:

<w:style w:styleId="TOC1" w:type="paragraph">
 <w:name w:val="toc 1"/>
 <w:basedOn w:val="Normal"/>
 <w:next w:val="Normal"/>
 <w:autoRedefine/><w:unhideWhenUsed/>
 <w:rPr>
  <w:b/><w:bCs/><w:caps/><w:sz w:val="32"/><w:szCs w:val="32"/>
 </w:rPr>
</w:style>

The most formatting is done within the rPr (Run Properties) element and it's children.

Example:

import java.io.File;
import java.io.FileOutputStream;

import org.apache.poi.xwpf.usermodel.*;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTNumbering;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSimpleField;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;

import java.math.BigInteger;

public class CreateWordNumberedHeadings {

 static String cTAbstractNumDecimalXML = 
  "<w:abstractNum xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" w:abstractNumId="0">"
+ "<w:multiLevelType w:val="hybridMultilevel"/>"
+ "<w:lvl w:ilvl="0"><w:start w:val="1"/><w:numFmt w:val="decimal"/><w:lvlText w:val="%1"/><w:lvlJc w:val="left"/><w:pPr><w:ind w:left="360" w:hanging="360"/></w:pPr></w:lvl>"
+ "<w:lvl w:ilvl="1" w:tentative="1"><w:start w:val="1"/><w:numFmt w:val="decimal"/><w:lvlText w:val="%1.%2"/><w:lvlJc w:val="left"/><w:pPr><w:ind w:left="720" w:hanging="360"/></w:pPr></w:lvl>"
+ "<w:lvl w:ilvl="2" w:tentative="1"><w:start w:val="1"/><w:numFmt w:val="decimal"/><w:lvlText w:val="%1.%2.%3"/><w:lvlJc w:val="left"/><w:pPr><w:ind w:left="1440" w:hanging="360"/></w:pPr></w:lvl>"
+ "</w:abstractNum>";

 static String cTStyleNormal =
  "<w:style xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" w:type="paragraph" w:default="1" w:styleId="Normal">" 
+ "<w:name w:val="Normal"/>"
+ "<w:qFormat/>"
+ "</w:style>";
 static String cTStyleH1XML =
  "<w:style xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" w:type="paragraph" w:styleId="Heading1">"
+ "<w:name w:val="heading 1"/>"
+ "<w:basedOn w:val="Normal"/>"
+ "<w:next w:val="Normal"/>"
+ "<w:unhideWhenUsed/>"
+ "<w:qFormat/>"
+ "<w:rPr><w:b/><w:sz w:val="36"/></w:rPr>"
+ "</w:style>";
 static String cTStyleH2XML =
  "<w:style xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" w:type="paragraph" w:styleId="Heading2">"
+ "<w:name w:val="heading 2"/>"
+ "<w:basedOn w:val="Normal"/>"
+ "<w:next w:val="Normal"/>"
+ "<w:unhideWhenUsed/>"
+ "<w:qFormat/>"
+ "<w:rPr><w:sz w:val="32"/></w:rPr>"
+ "</w:style>";
 static String cTStyleH3XML =
  "<w:style xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" w:type="paragraph" w:styleId="Heading3">"
+ "<w:name w:val="heading 3"/>"
+ "<w:basedOn w:val="Normal"/>"
+ "<w:next w:val="Normal"/>"
+ "<w:unhideWhenUsed/>"
+ "<w:qFormat/>"
+ "<w:rPr><w:i/><w:sz w:val="28"/></w:rPr>"
+ "</w:style>";

static String cTStyleTOC1 =
  "<w:style xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" w:type="paragraph" w:styleId="TOC1">"
+ "<w:name w:val="toc 1"/>"
+ "<w:basedOn w:val="Normal"/>"
+ "<w:next w:val="Normal"/>"
+ "<w:autoRedefine/><w:unhideWhenUsed/>"
+ "<w:rPr><w:b/><w:bCs/><w:caps/><w:color w:val="C00000"/><w:sz w:val="32"/><w:szCs w:val="32"/></w:rPr>"
+ "</w:style>";

static String cTStyleTOC2 =
  "<w:style xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" w:type="paragraph" w:styleId="TOC2">"
+ "<w:name w:val="toc 2"/>"
+ "<w:basedOn w:val="Normal"/>"
+ "<w:next w:val="Normal"/>"
+ "<w:autoRedefine/><w:unhideWhenUsed/>"
+ "<w:rPr><w:i/><w:iCs/><w:sz w:val="28"/><w:szCs w:val="28"/></w:rPr>"
+ "</w:style>";

 public static void main(String[] args) throws Exception {

  XWPFDocument document = new XWPFDocument();       

  XWPFNumbering numbering = document.createNumbering();
  CTNumbering cTNumbering = CTNumbering.Factory.parse(cTAbstractNumDecimalXML);
  CTAbstractNum cTAbstractNum = cTNumbering.getAbstractNumArray(0);
  XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);

  BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);
  BigInteger numID = numbering.addNum(abstractNumID);

  XWPFStyles styles = document.createStyles();
  CTStyles cTStyles = CTStyles.Factory.parse(cTStyleNormal);
  CTStyle cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));
  cTStyles = CTStyles.Factory.parse(cTStyleH1XML);
  cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));
  cTStyles = CTStyles.Factory.parse(cTStyleH2XML);
  cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));
  cTStyles = CTStyles.Factory.parse(cTStyleH3XML);
  cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));

  cTStyles = CTStyles.Factory.parse(cTStyleTOC1);
  cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));
  cTStyles = CTStyles.Factory.parse(cTStyleTOC2);
  cTStyle = cTStyles.getStyleArray(0);
  styles.addStyle(new XWPFStyle(cTStyle));

  createParagraphs(document, numID, 
   new String[] {"First Level",
                 "Second Level",
                 "First Level",
                 "Second Level",
                 "Third Level",
                 "Second Level",
                 "Third Level",
                 "Second Level",
                 "First Level"}
  );

  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run=paragraph.createRun();
  run.setText("Table of contents:");

  paragraph = document.createParagraph();

  CTSimpleField toc = paragraph.getCTP().addNewFldSimple();
  toc.setInstr("TOC \* MERGEFORMAT");
  toc.setDirty(STOnOff.TRUE);

  FileOutputStream out = new FileOutputStream("CreateWordNumberedHeadings.docx");   
  document.write(out);
  out.close();
  document.close();

 }

 public static void createParagraphs(XWPFDocument doc, BigInteger numID, String[] content) {
  for (String value : content) {
   XWPFParagraph para = doc.createParagraph();
   para.setVerticalAlignment(TextAlignment.CENTER);
   para.setNumID(numID);
   para.setStyle("Heading1");
   if (value.contains("Second")) {
    para.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(1));
    para.setStyle("Heading2");
   }
   if(value.contains("Third")) {
    para.getCTP().getPPr().getNumPr().addNewIlvl().setVal(BigInteger.valueOf(2));
    para.setStyle("Heading3");
   }
   XWPFRun run = para.createRun();
   run.setText(value);
   para = doc.createParagraph();
   run = para.createRun();
   run.setText("Lorem ipsum semit dolor ...");
   run.addBreak(BreakType.PAGE); 
  } 
 }
}

Note: I do not use XWPFDocument.createTOC() for mentioned reasons. Instead I am inserting a field which must be refreshed while opening the document in Word. This leads to a confirm dialog while opening which must be answered with Yes.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...