通过样式ID在XWPF上设置样式

时间:2018-10-26 22:05:09

标签: java apache-poi

我正在尝试将命名样式应用于XWPFDocument中的各个运行,并且看到奇怪的结果。

javadoc for XWPFRun describes the setStyle method,但是样式出现不会在最终文档中应用。我说出现,是因为在Finder的QuickLook预览中,确实样式会按预期出现在运行中。在下面的示例中,我将命名样式应用于超链接,该样式将按预期显示在右侧的预览中,而不是出现在左侧的Word中。

enter image description here

因此,很明显,POI实际上正在做一些应用样式的操作,但是Word没有呈现样式。我尝试了其他几种.docx阅读器,所有阅读器均产生相似的结果。

因此,我开始剥离样式并将属性分别应用于运行,这在Word中是有效的。这似乎是我必须丢失的东西之一。我可以当然可以编写一个例程,该例程可以读取现有样式并将其应用于这样的运行,但是我宁愿不这样做。我一直在寻找答案,但是POI的这一部分似乎正在处理中。

那么我是否只是想念一些明显的东西,还是只需要把它吸起来并以痛苦的方式来做?

//This does not work.
run.setStyle(styleId);

if(docStyles.styleExist(styleId))
{

    /*
        In order to set the style on the run, we need to manually
        determine the properties of the style, and set them on the
        run individually.

        This makes no sense.
     */
    XWPFStyle style = docStyles.getStyle(styleId);

    CTStyle ctStyle = style.getCTStyle();
    CTRPr ctRpr = ctStyle.getRPr();

    if (ctRpr.isSetB())
    {
        CTOnOff onOff = ctRpr.getB();
        STOnOff.Enum stOnOff = onOff.getVal();

        boolean bold = (stOnOff == STOnOff.TRUE);

        run.setBold(bold);
    }
    if(ctRpr.isSetU())
    {
        CTUnderline underline = ctRpr.getU();
        STUnderline.Enum val = underline.getVal();

        UnderlinePatterns underlinePattern = UnderlinePatterns.valueOf(val.intValue());

        run.setUnderline(underlinePattern);
    }
    // ... //
}
else
{
    System.out.println("404: Style not found");
}

1 个答案:

答案 0 :(得分:1)

如果XWPfDocument是从模板创建的,则此模板必须已经包含命名样式“ Hyperlink”。也就是说,它必须在/word/styles.xml中包含潜在样式的条目

...
<w:latentStyles...
...
 <w:lsdException w:name="Hyperlink" w:qFormat="1"/>
...

以及样式定义

...
<w:style w:type="character" w:styleId="Hyperlink">
 <w:name w:val="Hyperlink"/>
 <w:basedOn w:val="..."/>
 <w:uiPriority w:val="99"/>
 <w:unhideWhenUsed/>
 <w:qFormat/>
 <w:rsid w:val="00072FE4"/>
 <w:rPr>
  <w:color w:val="0000FF" w:themeColor="hyperlink"/>
  <w:u w:val="single"/>
 </w:rPr>
</w:style>
...

如果是这样,那么以下代码将使用apache poi 4.0.0为我工作:

import java.io.FileInputStream;
import java.io.FileOutputStream;

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

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;

public class CreateWordStyledHyperlinkRunFromTemplate {

 static XWPFHyperlinkRun createHyperlinkRun(XWPFParagraph paragraph, String uri) throws Exception {
  String rId = paragraph.getPart().getPackagePart().addExternalRelationship(
    uri, 
    XWPFRelation.HYPERLINK.getRelation()
   ).getId();

  CTHyperlink cthyperLink=paragraph.getCTP().addNewHyperlink();
  cthyperLink.setId(rId);
  cthyperLink.addNewR();

  return new XWPFHyperlinkRun(
    cthyperLink,
    cthyperLink.getRArray(0),
    paragraph
   );
 }

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

  XWPFDocument document = new XWPFDocument(new FileInputStream("Template.docx"));

  XWPFParagraph paragraph = document.createParagraph();
  XWPFRun run = paragraph.createRun();
  run.setText("This is a text paragraph having a link to Google ");

  XWPFHyperlinkRun hyperlinkrun = createHyperlinkRun(paragraph, "https://www.google.de");
  hyperlinkrun.setText("https://www.google.de");
  XWPFStyles styles = document.getStyles();
  if (styles.styleExist("Hyperlink")) {
   System.out.println("Style Hyperlink exists."); //Template must contain named style "Hyperlink" already
   hyperlinkrun.setStyle("Hyperlink");
  } else {
   hyperlinkrun.setColor("0000FF");
   hyperlinkrun.setUnderline(UnderlinePatterns.SINGLE);
  }

  run = paragraph.createRun();
  run.setText(" in it.");

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

 }
}

请注意,除非使用低级org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink类,否则无法创建XWPFHyperlinkRun

它产生:

enter image description here