简体   繁体   中英

Sort Table of Contents in alphabetical order

I'm using GemBox.Document to create a Word document that's generated from combining multiple documents and I'm inserting the TOC element (Table of Content) at the beginning. Now I need to alphabetize that TOC element.

I'm aware that this option doesn't exist in Microsoft Word, the TOC is always sorted in page order, not in alphabetical order, and that the TableOfEntries.Update() method behaves like that by default.

Nevertheless, I'm hoping there is a way to do that. I did check those TOC switches and if I'm not missing something, there is no switch for this, right?

Last, I'm aware of index tables, but that's not what I'm looking for. The TOC element is a much better fit to what I'm trying to get, but I need it sorted alphabetically.

You can "manually" sort the TOC entries after updating the TOC element, like this:

var document = DocumentModel.Load("input.docx");

var toc = (TableOfEntries)document.GetChildElements(true, ElementType.TableOfEntries).First();
toc.Update();

// Take current TOC entries.
var entries = toc.Entries.ToList();

// Remove them.
toc.Entries.Clear();

// Then place them back in sorted order.
entries.Sort((e1, e2) => e1.Content.ToString().CompareTo(e2.Content.ToString()));
entries.ForEach(e => toc.Entries.Add(e));

document.Save("output.docx");

But note that when the TOC element is updated again, either with GemBox.Document or with some Word application, you will get unsorted entries.

The only thing you can do here is to prevent others from updating your TOC element, for example by removing the TOC and keeping just its entries (aka unlinking the Table of Content):

toc.Content.Set(toc.Entries.Content);

Or you could place the TOC in a protected Section and thus prevent TOC update from Word applications (note that you'll still be able to update it with GemBox.Document):

// You mentioned that you're inserting the TOC element at the beginning
// which means that the "toc.Parent" should be document's first Section.
var section = document.Sections[0];

// If TOC is not the only element in a section then place it inside its own section.
if (section.Blocks.Count > 1)
{
    var tocSection = new Section(document);
    tocSection.PageSetup = section.PageSetup.Clone();
    tocSection.Blocks.Add(toc.Clone(true));

    document.Sections.Insert(0, tocSection);
    section.PageSetup.SectionStart = SectionStart.Continuous;
    toc.Content.Delete();
}

document.Protection.StartEnforcingProtection(EditingRestrictionType.FillingForms, "optional password");

// Unprotect all other Sections except the on that contains TOC element.
foreach (var otherSection in document.Sections.Skip(1))
    otherSection.ProtectedForForms = false;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM