使用updateFields更新目录存在目录缩进及页码不一致问题

使用updateFields更新目录

public static void main(String[] args) throws Exception {
    com.aspose.words.License wordsLicense=new com.aspose.words.License();
    wordsLicense.setLicense("D:\\Aspose.TotalforJava.lic");
    String fileName1 = "D:\\更新目录.docx";
    String fileName2 = "D:\\更新目录-result.docx";
    Document doc = new Document(fileName1);
    doc.updateFields();
    doc.save(fileName2);
}

问题1:目录缩进,标题序号与标题内容间存在空白、页码没有右对齐,如下图

正确目录应该为:

问题2:部分目录页码与实际页码不一致,如下图

正确目录应该为:

@whitemeen

摘要
Document.updateFields() 只会刷新字段的内容,而不会重新进行页面布局计算。仅调用此方法时,目录(TOC)中的缩进、页码对齐以及页码本身可能与实际页面不匹配。

原因
目录的生成依赖分页信息和制表位。更新字段后,文档的分页和制表位仍保持旧值,导致:

  • 标题序号与标题之间出现多余空白
  • 页码未右对齐
  • 目录页码与实际页码不一致

后续操作

  1. 按顺序调用两次更新
import com.aspose.words.*;

public class UpdateToc {
 public static void main(String[] args) throws Exception {
 License license = new License();
 license.setLicense("D:\\Aspose.TotalforJava.lic");

 Document doc = new Document("D:\\更新目录.docx");

 // ① 更新所有字段(包括 TOC 条目)
 doc.updateFields();

 // ② 重新计算页面布局(分页、制表位等)
 doc.updatePageLayout();

 doc.save("D:\\更新目录-result.docx");
 }
}
  1. 验证生成的文档
  • 重新打开 更新目录-result.docx,检查目录的缩进、页码右对齐以及页码是否与实际页面对应。
  • 如仍有异常,记录 Aspose.Words 版本、TOC 字段代码以及文档中是否存在多个 TOC,以便进一步排查。

注意updateFieldsupdatePageLayout 必须按上述顺序调用,否则可能出现页码不显示或不正确的情况。

我使用的版本是aspose-words 25.7,使用updatePageLayout后依旧错误,这是源文件:
更新目录.docx (202.6 KB)

@whitemeen 对文件的分析表明,10.1和10.2都在同一个20页上,因此更改的页码是正确的。如果更新MS Word中的TOC,它看起来与“Aspose.Words”中的相同,这意味着添加后应用于TOC元素的样式。您应该在文档中配置您的基本TOC样式 Format or customize a table of contents in Word - Microsoft Support

我不想对文档进行手动处理,我希望apose.words能对此做兼容处理。包括我的问题1-目录页码缩进的问题,我希望apose.words对此bug进行修复。

@whitemeen 您可以使用以下代码来解决该问题:

Document doc = new Document("input.docx");

Section section = doc.getFirstSection();
PageSetup pageSetup = section.getPageSetup();
double tabStopPosition = pageSetup.getPageWidth() - pageSetup.getLeftMargin()
        - pageSetup.getRightMargin();

for (int level = 1; level <= 9; level++) {
    Style tocStyle = doc.getStyles().get("TOC " + level);

    if (tocStyle != null) {
        ParagraphFormat format = tocStyle.getParagraphFormat();

        format.getTabStops().clear();
        format.getTabStops().add(new TabStop(tabStopPosition, TabAlignment.RIGHT, TabLeader.DOTS));

        format.setFirstLineIndent(0);
        format.setLeftIndent(0);

        format.setSpaceBefore(5);
        format.setSpaceAfter(5);
    }
}

doc.updateFields();

doc.save("output.docx");

使用该代码执行后依然存在问题:
1.标题序号宇标题内容间距宽度不一致。正确目录的标题序号与标题内容之间使用的是一个空格分隔,目前看起来应该是使用的Tab键。
2.部分目录页码不一致。可能是中文符号的占位问题导致。

@whitemeen 目录中的空格是手动设置的,因此需要更新代码:

Document doc = new Document("input.docx");

Section section = doc.getFirstSection();
PageSetup pageSetup = section.getPageSetup();
double tabStopPosition = pageSetup.getPageWidth() - pageSetup.getLeftMargin()
        - pageSetup.getRightMargin();

for (int level = 1; level <= 9; level++) {
    Style tocStyle = doc.getStyles().get("TOC " + level);

    if (tocStyle != null) {
        ParagraphFormat format = tocStyle.getParagraphFormat();

        format.getTabStops().clear();
        format.getTabStops().add(new TabStop(tabStopPosition, TabAlignment.RIGHT, TabLeader.DOTS));

        format.setFirstLineIndent(0);
        format.setLeftIndent(0);

        format.setSpaceBefore(5);
        format.setSpaceAfter(5);
    }
}

doc.updateFields();

NodeCollection paragraphs = doc.getChildNodes(NodeType.PARAGRAPH, true);
for (Paragraph para : (Iterable<Paragraph>) paragraphs) {
    String styleName = para.getParagraphFormat().getStyle() != null ?
            para.getParagraphFormat().getStyle().getName() : "";

    if (styleName.startsWith("TOC ")) {
        NodeCollection runs = para.getChildNodes(NodeType.RUN, true);

        for (Run run : (Iterable<Run>) runs) {
            String text = run.getText();

            if (text.contains("\t")) {
                run.setText(text.replaceFirst("\t", " "));
                break;
            }
        }
    }
}

doc.save("output.docx");

与该内容在MS Word中所在页面相关的页码。例如:

WPS 显示某些内容的方式可能与 MS Word 不同,但 Aspose.Words 模仿的是 MS Word 的行为,而非 WPS。