如何使用apache poi更改stylex的style.xml中的字体大小

时间:2018-06-13 17:55:25

标签: java apache-poi docx

现在我有一个docx文件,我加载到XWPFDocument

XWPFDocument doc = new XWPFDocument(InputStream)

通过执行

,我可以看到它存储在style.xml中的不同样式的当前字体大小
for (CTStyle ctstyle : doc.getStyle().getStyleList())
{
    if (ctstyle.isSetRPr())
    {
        if (ctstyle.getRPr().isSetSz())
        {
            CTHpsMeasure size = ctstyle.getRPr().getSz();
            System.out.println(size.getVal());
        }
    }
}

我想用poi更新字体大小,所以我试过

for (CTStyle ctstyle : doc.getStyle().getStyleList())
{
    if (ctstyle.isSetRPr())
    {
        if (ctstyle.getRPr().isSetSz())
        {
            CTHpsMeasure size = ctstyle.getRPr().getSz();
            size.setVal(BigInteger.valueOf(12));
            ctstyle.getRPr().setSz(size);
        }
    }
}

然而,在完成上面的代码之后,如果我使用第一段代码检查我的文档(XWPFDocument doc对象)的字体大小,字体大小仍然是原始值,而不是12 I打算设定。

有关于如何解决这个问题的建议吗?

1 个答案:

答案 0 :(得分:0)

XWPFDocument.getStyle获取org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles但不获取文档部分/word/styles.xml。因此,在写出CTStyles时,不会提交此XWPFDocument中的更改。

XWPFDocument.getStyles获取XWPFStyles扩展POIXMLDocumentPart并覆盖commit方法。因此,在写出XWPFStyles时,将在XWPFDocument中进行更改。

不幸的是,没有一种方法可以从这个XWPFStyles中获取所有单一样式。有一个字段private CTStyles ctStyles,也在protected void commit()中提交,但不可公开访问。所以我用反射来得到它。

根据您之前的问题,我知道您在解析*.docx文件时遇到问题,该文件的字体大小被错误地设置为双精度<w:sz w:val="24.0"/>,这绝对是错误的,导致size.getVal()投掷org.apache.xmlbeans.impl.values.XmlValueOutOfRangeException: Invalid integer value: 24.0 }。

ctstyle.getRPr().getSz()无崩溃也有<w:sz w:val="24.0"/>。在这里你可以得到真实的大小。为此,直接解析CTHpsMeasure size的XML,然后将从那里得到的值设置为BigIntegerBigDecimal为此提供了一种方法。

另外你还应该得到并纠正ctstyle.getRPr().getSzCs(),这是&#34;复杂脚本的大小&#34;使用的字体也可能是错误的。

以下适用于我,之后所有具有字体大小的样式都设置了整数字体大小。例如,<w:sz w:val="24.0"/><w:szCs w:val="24.0"/><w:sz w:val="24"/><w:szCs w:val="24"/>。注意这里的测量单位是半点24半点= 12点。

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

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

import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyle;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTStyles;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHpsMeasure;

import java.math.BigInteger;
import java.math.BigDecimal;

import java.lang.reflect.Field;

public class WordChangeStyles {

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

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

  XWPFStyles styles = document.getStyles(); //XWPFStyles extends POIXMLDocumentPart and overwrites commit method
  Field _ctStyles = XWPFStyles.class.getDeclaredField("ctStyles");
  _ctStyles.setAccessible(true); 
  CTStyles ctStyles = (CTStyles)_ctStyles.get(styles);

  CTHpsMeasure size;
  String sz;
  for (CTStyle ctstyle : ctStyles.getStyleList()) {
   if (ctstyle.isSetRPr()) {
    if (ctstyle.getRPr().isSetSz()) {
     size = ctstyle.getRPr().getSz();
     if (size != null) {
      sz = size.selectAttribute("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "val").newCursor().getTextValue();
      System.out.println(sz); //here you could get the real meant size out of
      size.setVal(new BigDecimal(sz).toBigInteger()); //sets the sz got from size truncated to BigInteger
      ctstyle.getRPr().setSz(size); //after that the font size should be integer

      System.out.println(ctstyle.getRPr().getSz().getVal());
     }

     size = ctstyle.getRPr().getSzCs();
     if (size != null) {
      sz = size.selectAttribute("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "val").newCursor().getTextValue();
      System.out.println(sz); //here you could get the real meant size out of
      size.setVal(new BigDecimal(sz).toBigInteger()); //sets the sz got from size truncated to BigInteger
      ctstyle.getRPr().setSzCs(size); //after that the font size should be integer

      System.out.println(ctstyle.getRPr().getSzCs().getVal());
     }
    }
   }
  } 

  document.write(new FileOutputStream("WordUsingStyles.docx")); //while writing out XWPFStyles will be committed
  document.close();
 }
}