Skip to content

Create a rich OneNote page from input HTML.

A page is submitted as HTML: headings, paragraphs, bullet and numbered lists, tables and styled spans all translate into OneNote content. The page goes into a section, so this script finds (or creates) a SDK Examples section in a dedicated SDK OneNote Tour notebook, creates the page there, then deletes it again so the notebook is left as it was — pass --keep to keep the page.

python create.py
python create.py --keep

Permissions

Requires delegated permission Notes.ReadWrite.

Reference

View source

from __future__ import annotations

import argparse
import time

from office365.graph_client import GraphClient
from office365.runtime.client_request_exception import ClientRequestException
from tests.settings import client_id, password, tenant, username

NOTES_WRITE = ("Notes.Create", "Notes.ReadWrite", "Notes.ReadWrite.All")
EXAMPLE_NOTEBOOK = "SDK OneNote Tour"
EXAMPLE_SECTION = "SDK Examples"

PAGE_HTML = """<!DOCTYPE html>
<html>
<head>
    <title>Project status</title>
    <style>
        h1 { color: #0078d4; }
        .done { background: #dff6dd; }
        .wip { background: #fff3ce; }
    </style>
</head>
<body>
    <h1>Project status</h1>
    <p>Generated through the <strong>Microsoft Graph API</strong>.</p>

    <h2>Team</h2>
    <ul>
        <li><b>Alice</b> — engineering lead</li>
        <li><b>Bob</b> — product manager</li>
        <li><b>Carol</b> — designer</li>
    </ul>

    <h2>Milestones</h2>
    <ol>
        <li>Design review <span class="done">done</span></li>
        <li>API integration <span class="wip">in progress</span></li>
        <li>User testing</li>
    </ol>

    <h2>Budget</h2>
    <table>
        <thead>
            <tr><th>Category</th><th>Budget</th><th>Spent</th></tr>
        </thead>
        <tbody>
            <tr><td>Engineering</td><td>$50,000</td><td>$32,000</td></tr>
            <tr><td>Design</td><td>$15,000</td><td>$8,500</td></tr>
            <tr><td>Operations</td><td>$10,000</td><td>$9,200</td></tr>
        </tbody>
    </table>
</body>
</html>"""


def _client() -> GraphClient:
    return GraphClient(tenant=tenant).with_username_and_password(client_id, username, password)


def _ensure_section(client: GraphClient):
    """Return the dedicated ``SDK Examples`` section of the tour notebook, creating it if needed."""
    notebook = client.me.onenote.notebooks.ensure(EXAMPLE_NOTEBOOK).execute_query()
    return notebook.sections.ensure(EXAMPLE_SECTION).execute_query()


def _delete_page(page) -> None:
    """Delete a page, retrying briefly: OneNote needs a moment to settle a just-created page."""
    retries = 2
    for attempt in range(retries + 1):
        try:
            page.delete_object().execute_query()
            return
        except ClientRequestException as ex:
            if attempt == retries or ex.code != "20102":
                raise
            time.sleep(1)


def main() -> None:
    parser = argparse.ArgumentParser(description="Create a rich OneNote page from HTML")
    parser.add_argument("--keep", action="store_true", help="keep the page instead of deleting it")
    args = parser.parse_args()

    client = _client().require_delegated_permission(*NOTES_WRITE)
    section = _ensure_section(client)

    page = section.pages.add(presentation_file=PAGE_HTML).execute_query()
    print(f"Created page {page.title or '(untitled)'!r} in {section.display_name!r}")
    print(f"  {page.links.oneNoteWebUrl.href}")

    if not args.keep:
        _delete_page(page)
        print("Deleted the page again (pass --keep to keep it).")


if __name__ == "__main__":
    main()

← Back to Pages