javascriptoffice-jsonenote-api

How do I read OneNote indented paragraphs using OneNote Javascript APIs?


I have a notebook that contains these
enter image description here

The docs for OneNote APIs are here (paragraph class selected already) https://learn.microsoft.com/en-us/javascript/api/onenote/onenote.paragraph?view=onenote-js-1.1

If I run this code:

export async function run() {
  try {
    await OneNote.run( async context => {
      var page = context.application.getActivePage();
      var pageContents = page.contents;
      var firstPageContent = pageContents.getItemAt(0);
      var paragraphs=firstPageContent.outline.paragraphs
      //firstPageContent.delete()
      //var out_line=firstPageContent.outline
      paragraphs.load('richText/text');




      // Run the queued commands, and return a promise to indicate task completion.
      return context.sync()
        .then(function () {
              //debugger;
              console.log("Items",paragraphs.items);
              for (var i=0; i < paragraphs.items.length; i++)
                {
                  var paragraph= paragraphs.items[i] 
                  paragraph.load('items')
                  context.sync()   
                  console.log(paragraph.richText.text)
                  show_next_level(paragraph,i)
                }

          });


    });
} catch (error) {
    console.log("Error: " + error);
}
}

export async function show_next_level(paragraph,i) {
  try {
    await OneNote.run( async context => {
      //debugger;
      //var paragraphs=par.paragraphs
      var paragraphs=paragraph.paragraphs
      paragraphs.load('richText/text');
      //console.log("Items",paragraphs.items);


      // Run the queued commands, and return a promise to indicate task completion.
      return context.sync()
        .then(function () {

          console.log("Items",paragraphs.items);
          for (var i=0; i < paragraphs.items.length; i++)
            {
              var paragraph= paragraphs.items[i] 
              paragraph.load()

              context.sync()  
              console.log(paragraph.richText.text)
              debugger;
              //paragraph.richText.text=paragraph.richText.text+'►'
              show_next_level(paragraph,i)
            }

          });


    });
} catch (error) {
    console.log("Error: " + error);
}
}

After multiple iterations I managed to read the next level of indentation but I am still getting an error. The output of the above is now

Items (4) [h, h, h, h]
One line 1 
One line 2
One line 3
One line 4
Items [h]
Two line 0
Items (3) [h, h, h]
Two line 1
Two line 2
Two line 3
Items []
5taskpane.js:192 Error: PropertyNotLoaded: The property 'items' is not available. Before reading the property's value, call the load method on the containing object and call "context.sync()" on the associated request context.

Solution

  • The problem in your code is that your are not waiting for Item Promises, so, It throws PropertyNotLoaded Error. It happens because you are not waiting for the context sync eg. in the line:

    context.sync() // It's a promise, so it requires .then() method
    console.log(paragraph.richText.text)
    debugger;
    

    The following code works for multiple indented lines and uses await/async methods to wait for promises:

    export async function run() {
      try {
        await OneNote.run(async (context) => {
          var page = context.application.getActivePage();
          var pageContents = page.contents;
          var firstPageContent = pageContents.getItemAt(0);
          var paragraphs = firstPageContent.outline.paragraphs;
    
          paragraphs.load('richText/text');
    
          // Run the queued commands, and return a promise to indicate task completion.
          await context.sync();
    
          // Foreach level 0 paragraph
          for (let paragraph of paragraphs.items) {
            // Read the paragraph
            await readParagraph(context, paragraph, 0);
          }
        });
      } catch (error) {
          console.log("Error: " + error);
      }
    }
    
    // Read Paragraph data and Child data
    async function readParagraph(context, paragraph, level) {
      try {
        paragraph.load('items');
    
        await context.sync();
        console.log('Level ' + level + ' > Data:', paragraph.richText.text);
    
        let levelParagraphs = paragraph.paragraphs;
        levelParagraphs.load('richText/text');
    
        await context.sync();
    
        for (let p of levelParagraphs.items) {
          await readParagraph(context, p, level + 1);
        }
      } catch (error) {
        console.log('Error in Level ' + level, error);
      }
    }
    

    I used these data for testing and these were the results.

    I hope it helps you!