I use apache.poi create doc, use aspose.words to save the doc but toc page num is error

in local windows dev, the font is not missing;
this is my code

  public static void streamToDocX1(String docFilePath, OutputStream stream) throws Exception {
    document = new Document(docFilePath);

    document.updatePageLayout();
    document.updateFields();
//    document.update();
    document.getRange().getFields().forEach(field -> {
      if (field.getType() == FieldType.FIELD_TOC) {
        FieldToc toc = (FieldToc)field;
        try {
          toc.update();
          toc.updatePageNumbers();
        } catch (Exception e) {
          throw new RuntimeException(e);
        }
      }
    });
    document.save(stream, SaveFormat.DOCX);
  }

myTest.docx (29.7 KB)

this is my doc

@ssj123ssj First of all to update TOC it is enough to use the following code:

document = new Document(docFilePath);
document.updateFields();
document.save(stream, SaveFormat.DOCX);

It is not required to update TOC separately. When you call Document.updateFields() method, all fields are updated including TOC.

The above code properly updates TOC on my side: out.docx (29.5 KB)

As you may know, MS Word documents are flow documents and do not contain any information about document layout. The consumer applications, like MS Word or Open Office builds document layout on the fly. Aspose.Words uses it’s own layout engine to build document layout while rendering the document to fixed page formats (PDF, XPS, Image etc.) and upon updating TOC.
To built proper document layout the fonts used in the original document are required. If Aspose.Words cannot find the fonts used in the document the fonts are substituted . This might lead into the layout difference, since substitution fonts might have different font metrics. This might lead to incorrect pages detection. You can implement IWarningCallback to get a notification when font substitution is performed.

Also, if the fonts used in the document are not installed in the environment where you open your document in MS Word, MS Word also substitutes the fonts and the same document might look differently in environments with different fonts.

document = new Document(docFilePath);
document.updateFields();
document.save(stream, SaveFormat.DOCX);

I have tried updating the toc in this way before, but it didn’t work;
It is correct for me to update the toc again with the downloaded doc;
But the first time the doc create I used this method, the toc is wrong;
I have use IWarningCallback to check the font ,it is right

public static void streamToDocX1(String docFilePath, OutputStream stream) throws Exception {
    document = new Document(docFilePath);
    document.updateFields();
    document.save(stream, SaveFormat.DOCX);
}

the first time I ues this code to try ,but it is wrong

@ssj123ssj Unfortunately, I cannot reproduce the problem on my side. Aspose.Words updates TOC the same way as MS Word does on my side. So I cannot see any inconsistency. Have you tried updating TOC in MS Word on your side?

thanks,how to update TOC in MS Word.
this is my all code:

XWPFDocument document = new XWPFDocument();
// here to create content in XWPFDocument
.......................
            File tempDir = null;
try
{
    // create dir
    tempDir = Files.createTempDirectory("myTemplateTemp").toFile();
    // create temporary file
    File file = new File(tempDir, "临时模板.docx");
    try (FileOutputStream fos = new FileOutputStream(file)) {
        document.write(fos);
    }
    String path = file.getAbsolutePath();

    response.setContentType("application/msword");
    response.addHeader("Content-Disposition", "attachment;filename=" +
            URLEncoder.encode(one.getTemplateName() + ".docx", "UTF-8"));
    ServletOutputStream oStream = response.getOutputStream();
    Document document = new Document(docFilePath);
    document.updateFields();
    document.save(stream, SaveFormat.DOCX);
    oStream.close();
    }
    catch (Exception e)
    {
        log.error("download tempalte error e:{}", e);
    }
    finally
    {
        if (tempDir != null && tempDir.exists())
        {
            // delete template file
            FileUtils.deleteDirectory(tempDir);
        }
    }

I have tried two different ways to generate this document:

  1. Generate file with Toc and page nums in MS Word , then save it using aspose
  2. In MS Word, only the file content is generated, but Toc and page nums are not produced. Aspose saves the file and create TOC adn page nums

@ssj123ssj To update TOC in MS Word you can simply open document in MS Word and press F9 to update all fields in the document. I mean if you open the document generated using your code in MS Word and update TOC in MS Word UI, will the TOC change or not? On my side TOC remains the same, so Aspose.Words updates TOC properly.

sure, open the doc in MS Word the TOC is right。my problem is our custom use WPS Office;
At first, I generated the document only using MS Word . However the document did not have TOC when my custom open it with WPS Office, so we now open it using Aspose and then to use document.updateFields() method to update TOC, in this way I find the TOC page nums is wrong

@ssj123ssj Aspose.Words uses MS Word as an etalon. So if the TOC updated by Aspose.Words looks the same as it looks after updating in MS Word, the result is considered as correct. Looks like this is WPS office issue, not Aspose.Words.

but I open the new generated doc in MS Word, the TOC page nums is also wrong

@ssj123ssj The problem is not reproducible on my side with the document you have attached earlier:

I am the same. It is correct to update the TOC page nums using the downloading file, but the TOC page nums of the downloaded files themselves is indeed incorrect

@ssj123ssj Unfortunately, the problem is still not clear. Page numbers in the TOC updated by Aspose.Words corresponds the appropriate pages in the output document.

thanks. Can you help me look at another question , How to generate page numbers starting from a specified page,wo I want to start page nums after TOC

@ssj123ssj you should create a separate section for the TOC and the content. For example see the following code:

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.insertTableOfContents("\\o \"1-3\" \\h \\z \\u");
// Add another section.
builder.insertBreak(BreakType.SECTION_BREAK_NEW_PAGE);
// Configure page starting number in the section.
builder.getPageSetup().setPageStartingNumber(1);
builder.getPageSetup().setRestartPageNumbering(true);
// Insert some headings.
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.HEADING_1);
builder.writeln("Heading 1");
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.HEADING_2);
builder.writeln("Heading 2");
builder.getParagraphFormat().clearFormatting();
// Insert page numbers in the header
builder.moveToHeaderFooter(HeaderFooterType.HEADER_PRIMARY);
builder.insertField("PAGE");
builder.write(" of ");
builder.insertField("NUMPAGES");

doc.updateFields();
doc.save("C:\\Temp\\out.docx");

How can I replace the FIELD_NUM_PAGES to new calculated value,
this is my code:

// 移动到页脚并添加内容
builder.moveToHeaderFooter(HeaderFooterType.FOOTER_PRIMARY);
//创建页脚 页码
builder.getParagraphFormat().setAlignment(ParagraphAlignment.CENTER);
builder.getFont().setName("宋体");
builder.getFont().setSize(9.0);
builder.write("第 ");
builder.insertField(FieldType.FIELD_PAGE, true); // 插入页码字段

builder.write(" 页,共 ");
builder.insertField(FieldType.FIELD_NUM_PAGES, true);
builder.write(" 页");

// Insert formula field
Field formulaField = builder.insertField(FieldType.FIELD_FORMULA, false);
// Move DocumentBuilder inside formula field code
builder.moveTo(formulaField.getSeparator());
// Insert PAGE field.
builder.insertField(FieldType.FIELD_NUM_PAGES, false);
// Continue writing formula
builder.write("-2");

@ssj123ssj Your code for inserting calculated value is correct. But you insert both NUMPAGE and FORMULA field with calculated value one after another. Please see the following code:

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
builder.insertTableOfContents("\\o \"1-3\" \\h \\z \\u");
// Add another section.
builder.insertBreak(BreakType.SECTION_BREAK_NEW_PAGE);
// Configure page starting number in the section.
builder.getPageSetup().setPageStartingNumber(1);
builder.getPageSetup().setRestartPageNumbering(true);
// Insert some headings.
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.HEADING_1);
builder.writeln("Heading 1");
builder.getParagraphFormat().setStyleIdentifier(StyleIdentifier.HEADING_2);
builder.writeln("Heading 2");
builder.getParagraphFormat().clearFormatting();
// Insert page numbers in the header
builder.moveToHeaderFooter(HeaderFooterType.HEADER_PRIMARY);
builder.insertField("PAGE");
builder.write(" of ");
// Insert formula field
Field formulaField = builder.insertField(FieldType.FIELD_FORMULA, false);
// Move DocumentBuilder inside formula field code
builder.moveTo(formulaField.getSeparator());
// Insert PAGE field.
builder.insertField(FieldType.FIELD_NUM_PAGES, false);
// Continue writing formula
builder.write("-2");

doc.updateFields();
doc.save("C:\\Temp\\out.docx");

thanks, How to add content at the end of the footer, I add use this code but it add at first:

// Insert page numbers in the header
builder.moveToHeaderFooter(HeaderFooterType.HEADER_PRIMARY);
// 添加页眉
builder.getParagraphFormat().setAlignment(ParagraphAlignment.LEFT);
builder.getFont().setSize(9.0);
builder.writeln("页眉");

// 移动到页脚并添加内容
builder.moveToHeaderFooter(HeaderFooterType.FOOTER_PRIMARY);
//创建页脚 页码
builder.getParagraphFormat().setAlignment(ParagraphAlignment.CENTER);
builder.getFont().setName("宋体");
builder.getFont().setSize(9.0);
builder.write("第 ");
builder.insertField("PAGE"); // 插入页码字段

builder.write(" 页,共 ");

// Insert formula field
Field formulaField = builder.insertField(FieldType.FIELD_FORMULA, false);
// Move DocumentBuilder inside formula field code
builder.moveTo(formulaField.getSeparator());
// Insert PAGE field.
builder.insertField("NUMPAGES");
// Continue writing formula
builder.write("-2");

builder.moveToHeaderFooter(HeaderFooterType.FOOTER_PRIMARY);
builder.insertParagraph();
builder.write(" 页");