1

I am writing a Word add-in using office-js that generates an index. It uses the following code to create a section break at the end of the document, and then writes the index there:

function WriteIndex() {
   Word.run(function (context) {
   //
   var html = GenerateIndex(); // generate the index as an html string
   //
   if (html.length > 0) {
      var body = context.document.body;
      body.insertBreak(Word.BreakType.sectionNext, Word.InsertLocation.end);
      body.select("End"); // put it at the end
      return context.sync().then(function () {
         body = context.document.body;
         body.select("End"); // put it at the end
         body.insertHtml(html, Word.InsertLocation.end);
         return context.sync();
      });
    }).catch(handleError);
} 

So far, so good -- it works just as I want it to. But now I want to be able to re-run the function and delete the index that was there before regenerating and rewriting it.

I think I can get the contents of the index into a range and delete it. But I can't find anywhere in the API where you can delete a section break. I found some code at this link that iterates through the document section collection and gathers the contents of all the sections, then replaces the entire contents of the document with only the sections wanted. But this approach feels risky and convoluted to me. Another approach might be to essentially navigate to the end of the document and perform a backspace operation, since that's how you delete a section break using the Word UI, but I can't find anything in the API documentation to do that either.

Is it really the case that the API allows you to create section breaks but doesn't allow you to delete them? Has anyone done anything like this before? Is there a better approach?

Thanks very much.

Ned Balzer
  • 35
  • 6

2 Answers2

2

Yes, it's a bit round-about, but it can be done.

As you intimate, the actual section break appears not to be part of the section.body's Range. So the trick is to get the point immediately before that, at the end of the prior section's range, as demonstrated by the following code snippet. (Tested in ScriptLab.)

    const doc = context.document;
    const secs = doc.sections;
    secs.load("items");
    await context.sync();

    //console.log(secs.items.length.toString());
    const nrSecs = secs.items.length - 1;
    const sect = secs.items[nrSecs];
    const secPrev = secs.items[nrSecs-1];

    //console.log(sect.isNullObject);

   var sectRng = sect.body.getRange("Content");
   const secStart = secPrev.body.getRange("End");
   var sectAll = secStart.expandTo(sectRng);
   sectAll.delete ();

    await context.sync();
Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
  • This works great! Thanks so much. I had to futz around to figure out how to integrate the typescript code into Javascript. I also added a test that secs.items.length was > 1, and will need to add a test that that final section is indeed the index, so that I don't inadvertently delete some other last section, but thanks again. – Ned Balzer Apr 10 '20 at 13:48
0

For future reference, here is my js version (added as an answer only because the code exceeds the comment character limit -- Cindy Meister should get credit for the answer, not me). I incorporated the test of whether the index section exists in the function that calls this one, as it is not generally relevant to others:

     function RemoveLastSection() {
    Word.run(function (context) {
        var doc = context.document;
        var secs = doc.sections;
        secs.load("items");
        context.sync().then(function () {
            if (secs.items.length > 1) {
                var nrSecs = secs.items.length - 1;
                var sect = secs.items[nrSecs];
                var secPrev = secs.items[nrSecs - 1];
                var sectRng = sect.body.getRange("Content");
                var secStart = secPrev.body.getRange("End");
                var sectAll = secStart.expandTo(sectRng);
                sectAll["delete"]();
            }
            return context.sync();
        });
        return context.sync();
    }).catch(handleError)
}
Ned Balzer
  • 35
  • 6