简体   繁体   English

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

[英]Setting a style on an XWPFRun by style ID

I am trying to apply named styles to individual runs in an XWPFDocument, and I am seeing strange results. 我正在尝试将命名样式应用于XWPFDocument中的单个运行,并且看到奇怪的结果。

The javadoc for XWPFRun describes the setStyle method , but the style appears to not be applied in the final document. XWPFRunjavadoc描述了setStyle方法 ,但该样式似乎未在最终文档中应用。 I say appears , because in the QuickLook preview in Finder, the style does appear on the run as expected. 我说出现 ,是因为在Finder中的QuickLook预览中,样式确实按预期出现在运行中。 In the example below, I am applying a named style to the hyperlink, which appears as expected in the preview on the right, but not in Word on the left. 在下面的示例中,我将命名样式应用于超链接,该样式将按预期显示在右侧的预览中,而不是出现在左侧的Word中。

在此处输入图片说明

So clearly POI is actually doing something to apply the style, but Word is not rendering the style. 显然,POI实际上正在做一些应用样式的操作,但是Word并未呈现样式。 I tried several other .docx readers, all of which produced similar results. 我尝试了其他几种.docx阅读器,所有阅读器均产生相似的结果。

So I started peeling apart the style and applying the attributes to the run individually, which does work in Word. 因此,我开始剥离样式并将属性分别应用于运行,这在Word中确实有效。 This is one of those things that seems like I must just be missing something. 这似乎是我必须丢失的东西之一。 I can of course write a routine that can read in an existing style and apply it to a run like this, but I would much rather not. 我当然可以编写一个例程,该例程可以读取现有样式并将其应用于这样的运行,但是我宁愿不这样做。 I have searched for answers, but this part of POI seems to be very much a work in progress. 我一直在寻找答案,但是POI的这一部分似乎正在开发中。

So am I just missing something obvious, or am I going to just have to suck it up and do this the painful way? 那么,我只是错过了明显的东西,还是只是不得不吸吮它并以痛苦的方式做到这一点?

//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");
}

If the XWPfDocument is created from a template, then this template must contain the named style "Hyperlink" already. 如果XWPfDocument是从模板创建的,则此模板必须已经包含命名样式“ Hyperlink”。 That means, it must contain in /word/styles.xml the entry in latent styles 这意味着,它必须在/word/styles.xml包含潜在样式的条目

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

as well as the style definition 以及样式定义

...
<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>
...

If that is true then the following code works for me using apache poi 4.0.0 : 如果是这样,那么以下代码将使用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();

 }
}

Note there is not any possibility for creating XWPFHyperlinkRun except using the low level org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink class. 请注意,除了使用较低级别的org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink类之外,无法创建XWPFHyperlinkRun

It produces: 它产生:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM