How to decide the way to update fields on ToC


#1

Hi,

When using Word, I can do ctrl+A and F9 to update fields in the document. And if there’s a Table of Content, Word will automatically pop-up a dialog so that I can choose to update page numbers only or update the entire table (that includes formatting etc.):
image.png (14.7 KB)

However when I use document.UpdateFields() using Aspose.Words, it seems to always update the entire table on Table of Contents. Is there a way to configure this?

Thanks,


#2

@ServerSide527,

Please try using the following code:

Document doc = new Document("D:\\Temp\\in.docx");
           
foreach (Field field in doc.Range.Fields)
{
    if (field.Type == FieldType.FieldTOC)
    {
        FieldToc toc = (FieldToc)field;
        toc.UpdatePageNumbers();
    }
}

doc.Save("D:\\Temp\\18.7.docx");

#3

Hi,

Thanks for your advice.

I suppose in this code we only update ToC numbers but ignore other non-ToC fields? If we need to update other fields at the same time should I use
if (field.Type == FieldType.FieldTOC)
{
FieldToc toc = (FieldToc)field;
toc.UpdatePageNumbers();
}
else
field.Update();
?

Thanks


#4

@ServerSide527,

Yes, please use the following code:

Document doc = new Document("D:\\Temp\\in.docx");

foreach (Field field in doc.Range.Fields)
{
    if (field.Type == FieldType.FieldTOC)
    {
        FieldToc toc = (FieldToc)field;
        toc.UpdatePageNumbers();
    }
    else
    {
        field.Update();
    }
}

doc.Save("D:\\Temp\\18.7.docx");

#5

Hi,

Many thanks for the code, I have tried it and the output is looking fine.

The only question however, is that this seems twice slower than using document.UpdateFields().

I created a for loop that saves the document to pdf for 100 times to compare:

var startTime = DateTime.Now;
for (int i = 0; i < 100; ++i)
{
var document = new Document(@“test.docx”);
document.UpdateFields();
document.Save(@“out.pdf”);
}

var endTime = DateTime.Now;
Console.Write((endTime - startTime).TotalSeconds);

vs.

var startTime = DateTime.Now;
for (int i = 0; i < 100; ++i)
{
var document = new Document(@“test.docx”);
foreach (var field in document.Range.Fields)
{
if (field.Type == FieldType.FieldTOC)
{
FieldToc toc = (FieldToc)field;
toc.UpdatePageNumbers();
}
else
{
field.Update();
}
}
document.Save(@“out.pdf”);
}

var endTime = DateTime.Now;
Console.Write((endTime - startTime).TotalSeconds);

Using document.UpdateFields() took 166s to convert for 100 times that is 1.66s on average. While looping over the fields took 343s that is 3.43s on average.

Do you know why using this is much slower and if there is a way to make it faster but achieve the same output?

Thanks


#6

@ServerSide527,

First of all, please note that the following codes are not 100% equal.

Code 1:

foreach (Field field in doc.Range.Fields)
{
    field.Update();
}

Code 2:

doc.UpdateFields();

When you call doc.UpdateFields(), you update all the fields in the same “session” or “context”. But calling field.Update() in a loop just updates fields one by one. This is similar to MS Word, when you select all the contents then press F9 or when you select each field one by one then update it. In most cases the result will be the same, but for some cases (as far as I remember SEQ fields for example) the result of these two approaches will be different.

So, you may want to improve the code like this:

Document doc = new Document("D:\\Temp\\in.docx");

foreach (Field field in doc.Range.Fields)
{
    if (field.Type == FieldType.FieldTOC)
    {
        FieldToc toc = (FieldToc)field;
        toc.UpdatePageNumbers();
        toc.IsLocked = true;
    }
}

// As the TOC field is locked, the following should not update it
doc.UpdateFields();

PdfSaveOptions opts = new PdfSaveOptions();
opts.UpdateFields = false;

doc.Save("D:\\Temp\\18.7.pdf", opts);

#7

Hi,

Thanks for your sample code and explanation. This is very informative.

I will try applying the code on my project and will let you know if I encountered any issues.

Thanks again,


#8

@ServerSide527,

Sure, please let us know anytime you have any further queries.