【问题标题】:How to change font size in style.xml for docx using apache poi如何使用 apache poi 更改 docx 的 style.xml 中的字体大小
【发布时间】:2018-06-13 17:55:24
【问题描述】:

现在我有一个 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放。

对于如何解决这个问题有什么建议吗?

【问题讨论】:

  • XWPFDocument.getStyle 标记为 @Internal。因此,这不是供公众使用的。为什么不使用XWPFDocument.getStyles 并进一步使用XWPFStyles
  • 嗨,我确实试过了,我可以创建CTHpsMeasure 来使用 XWPFStyles,不幸的是,更改仍然无法返回到原始文档。

标签: java apache-poi docx


【解决方案1】:

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

XWPFDocument.getStyles 获取扩展 POIXMLDocumentPartXWPFStyles 并覆盖 commit 方法。因此,在写出XWPFDocument 时,将提交此XWPFStyles 中的更改。

不幸的是,没有一种方法可以从 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(),这是使用的“复杂脚本”字体的大小,也可能是错误的。

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

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();
 }
}

【讨论】:

  • 我明白了,所以提交我所做更改的唯一方法是写出一个新文档?我稍后会尝试,但感谢您的建议。
猜你喜欢
  • 1970-01-01
  • 2017-10-14
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-12
相关资源
最近更新 更多