java - Apache POI XWPFRun isBold 未检测到粗体

标签 java apache-poi

我有一个 doxc 文档,其中有一些粗体文本。由于某种原因,尽管运行本身以粗体显示,但 run.isBold() 返回 false。这里可能存在什么问题?

我用来读取文件的代码:

XWPFDocument document = new XWPFDocument(fis);
        for(XWPFParagraph paragraphs: document.getParagraphs()){

            for(XWPFRun run: paragraphs.getRuns()){
                System.out.println(run.isBold());

                System.out.println(run.text());
        }

文件内容如下所示:

  • 莫斯特

    2.1。一些文字

    2.1.1。 合并 - 一些文字

  • 奇怪的是,文件开头的标题(HANKELEPINGU ÜLDTINGIMUSED)是粗体的,但之后就没有任何粗体了。

    最佳答案

    在检查了您的 test.docx 文件后,我可以告诉您以下内容:

    文本“Üldosa”和“Mõisted”不是粗体,因为它们的格式是粗体,而是因为整个段落的样式为“Heading2”。并且文本“Pooled”也没有采用粗体格式,而是应用了特殊的字符样式“Paks”。所以有人用过Word Styles广泛地。一点也不差。正如 HTML 应该使用 CSS 样式表而不是直接格式化一样,在 Word 中也应该优先使用样式。但当然解析时的问题也是相同的。如果不额外解析样式表,就无法确定如何呈现文本。不幸的是 apache poi 直到现在才不太关心样式。

    如何获得这种洞察力? *.docx 文件只是一个 ZIP 存档。所以我们可以解压它,会发现:

    /word/document.xml:

    <w:r ...>
     <w:rPr>
      ...
      <w:b/>
      ...
     </w:rPr>
     <w:t>HANKELEPINGU ÜLDTINGIMUSED</w:t>
    </w:r>
    

    这是直接以粗体格式运行的文本。

    但是

    <w:p ...>
     <w:pPr>
      <w:pStyle w:val="Heading2"/>
      <w:numPr><w:ilvl w:val="0"/><w:numId w:val="2"/></w:numPr> 
      ...
     </w:pPr>
     <w:r ...>
      <w:t>Üldosa</w:t>
     </w:r>
    </w:p>
    

    这是一个样式为“Heading2”的段落,并且自动编号。

    那么为什么该文本是粗体的?在 /word/styles.xml 中我们发现:

    <w:style w:type="paragraph" w:styleId="Heading2">
     <w:name w:val="heading 2"/>
     <w:basedOn w:val="Normal"/>
     ...
     <w:link w:val="Heading2Char"/>
     ...
    </w:style>
    

    这是链接到字符样式“Heading2Char”的段落样式“Heading2”。

    <w:style w:type="character" w:customStyle="1" w:styleId="Heading2Char">
     <w:name w:val="Heading 2 Char"/>
     ...
     <w:link w:val="Heading2"/>
     ...
     <w:rPr>
      ...
      <w:b/>
      ...
     </w:rPr>
    </w:style>
    

    这是字符样式“Heading2Char”,设置为粗体。

    要回答如何使用 apache poi 进行此操作的问题,必须知道 apache poi XWPF 基于 org. openxmlformats.schemas.wordprocessingml.x2006.main.* 类来自 ooxml-schemas.*.jar。所以我们需要这方面的信息。不幸的是,没有任何公开的 API 文档。因此,我们需要下载源代码并自行执行javadoc

    那么下一步该做什么呢?像您已经完成的那样迭代段落并运行。但对于每个段落,还要尝试获取该段落的样式。如果有,获取它及其字符样式,并检查它提供了哪些设置。另外,对于每次运行,尝试获取本次运行的字符样式。如果有,获取它并检查它提供了哪些设置。

    下面的代码就是这样做的,但只是检查样式是否提供粗体设置。所以它确实不完整,而且完成它的成本确实会很高。

    import java.io.FileInputStream;
    
    import org.apache.poi.xwpf.usermodel.*;
    
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
    
    public class ReadWordHavingStyles {
    
     public static void main(String[] args) throws Exception {
    
      XWPFDocument document = new XWPFDocument(new FileInputStream("test.docx"));
    
      XWPFStyles styles = document.getStyles();
      XWPFStyle style = null;
      boolean isPBold = false;
      boolean isRBold = false;
      String boldReasonP = "";
      String boldReasonR = "";
      CTRPr cTRPr = null;
    
      for(XWPFParagraph paragraph : document.getParagraphs()) {
       isPBold = false;
       boldReasonP = "";
       String pStyleId = paragraph.getStyleID();
       if (pStyleId != null) {
        style = styles.getStyle(pStyleId);
        if (style != null) {
         String linkStyleId = style.getLinkStyleID();
         style = styles.getStyle(linkStyleId);
         if (style != null) {
          cTRPr = style.getCTStyle().getRPr();
          if (cTRPr != null) {
           if (!cTRPr.isSetB()) {
            isPBold = false;
           } else {
            STOnOff.Enum val = cTRPr.getB().getVal();
            isPBold = !((STOnOff.FALSE == val) || (STOnOff.X_0 == val) || (STOnOff.OFF == val));
           }
          }
          boldReasonP = " whole P is " + ((isPBold)?"":"not ") + "bold because of style " + linkStyleId;
         }
        }
       }
    
       if (!isPBold) boldReasonP = " P is not bold";
    
       for(XWPFRun run : paragraph.getRuns()){
        isRBold = isPBold;
        boldReasonR = "";
        cTRPr = run.getCTR().getRPr();
        if (cTRPr != null) {
         CTString rStyle = cTRPr.getRStyle();
         if (rStyle != null) {
          String rStyleId = rStyle.getVal();
          style = styles.getStyle(rStyleId);
          if (style != null) {
           cTRPr = style.getCTStyle().getRPr();
           if (cTRPr != null) {
            if (!cTRPr.isSetB()) {
             isRBold = false;
            } else {
             STOnOff.Enum val = cTRPr.getB().getVal();
             isRBold = !((STOnOff.FALSE == val) || (STOnOff.X_0 == val) || (STOnOff.OFF == val));
            }      
           }
           boldReasonR = " run is " + ((isRBold)?"":"not ") + "bold because of style " + rStyleId;
          }
         }
        }
    
        if (!isRBold) boldReasonR = " run is not bold";
    
        cTRPr = run.getCTR().getRPr();
        if (cTRPr != null) {
         if (cTRPr.isSetB()) {
          STOnOff.Enum val = cTRPr.getB().getVal();
          isRBold = !((STOnOff.FALSE == val) || (STOnOff.X_0 == val) || (STOnOff.OFF == val));
          boldReasonR = " run is " + ((isRBold)?"":"not ") + "bold because of direct formatting";
         }      
        }
    
        System.out.println(run.text() + " isBold:" + isRBold + ":" + boldReasonP + boldReasonR);
    
       }
      }
    
      document.close();
     }
    }
    

    关于java - Apache POI XWPFRun isBold 未检测到粗体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54516225/

    相关文章:

    java - 我如何使用 Java 从 excel 中检索整数值

    java - Apache POI - HSSF 单元格格式的垂直单元格对齐

    java - 如何使用 Apache POI 查找/替换 .docx 文件中的占位符?

    java - 使用 Java 设置 App Engine 数据存储区的光标

    java - 解析大约 700 行文本,将这些行拆分并将它们用作变量?

    java - 将项目写入 Excel 单元格

    java - POI条形图生成一系列有问题

    java - 如何在 BottomSheetDialogFragment 中设置最大高度?

    java - 如何在Java中创建动态数组?

    java - 从 USB 端口读取数据