Automating Excel Reports with Microsoft Graph: Sessions, Tables, Chart Images

5 min read

If someone on your team is still pulling numbers from a database, pasting them into Excel, and refreshing charts for the weekly report, that entire chore can be automated with the tools from Microsoft Graph in Practice. Graph’s workbook API reads and writes Excel files on OneDrive and SharePoint without opening them. This post covers its core: session management, table operations, and chart image extraction. App registration and auth are assumed from Graph in Practice #2.

The entry point: /workbook after the file path #

Workbook API URLs attach /workbook to a drive item address.

Request examples
GET /me/drive/items/{item-id}/workbook/worksheets
GET /sites/{site-id}/drive/items/{item-id}/workbook/tables

Worksheets, tables, ranges, charts, and named items are exposed beneath this path as resources. Uploading and downloading the file itself belongs to the drive API from Graph in Practice #5; the workbook API works inside an open workbook.

Sessions: the switch for performance and persistence #

The first thing to understand about the workbook API is sessions. Calls come in three modes.

ModeHowBehavior
Persistent sessioncreateSession with persistChanges: trueChanges saved to the file. Most efficient — the production default
Non-persistent sessionpersistChanges: falseChanges hit a temporary copy only, discarded when the session ends
Sessionlessomit the headerThe server relocates the workbook on every call. Slow. For one-off requests
Create a session
POST /me/drive/items/{item-id}/workbook/createSession
Content-Type: application/json

{ "persistChanges": true }

Pass the returned session ID on every subsequent call in the workbook-session-id header. If you make more than one call, creating a session is the answer — the server keeps the workbook loaded and per-call latency drops sharply.

Non-persistent sessions shine as a calculator. When you want to feed values into a template workbook, pull out formula results or a chart, and leave the file untouched, working inside a persistChanges: false session gets you the results without ever modifying the source. It is the pattern of using a template Excel file as a computation engine.

Two operational notes. Sessions expire on inactivity (persistent after roughly 5 minutes, non-persistent roughly 7), and calls against an expired session return 404 — long jobs need session-recreation logic. Session creation itself can take a while, so the Prefer: respond-async long-running pattern (polling) is available, and the occasional 504 is simply retried.

Reading: usedRange and tables #

The simplest way to read just the populated area of a sheet is usedRange.

Read usedRange
GET /me/drive/items/{id}/workbook/worksheets/{name}/usedRange

The smallest rectangle containing values or formatting comes back with values (a 2D array), formulas, and text. For a specific area, narrow with range(address='A1:D20').

For report automation, though, tables are a far sturdier anchor than ranges. Range addresses drift when rows grow; tables are addressed by name and expand with the data automatically.

Read tables and append rows
GET  /me/drive/items/{id}/workbook/tables                       # list tables
GET  /me/drive/items/{id}/workbook/tables('SalesTable')/rows    # read rows

POST /me/drive/items/{id}/workbook/tables('SalesTable')/rows
{ "values": [["2026-09-15", "Keyboard", 12, 348.00]] }           # append a row

This is the base shape of a report pipeline: code appends raw data as table rows, and the summary refreshes itself through formulas, pivots, and charts that reference the table. The code owns only the append; Excel owns the aggregation.

Charts: create them, extract them as images #

The finishing move of report automation is charts. You can add charts, repoint an existing chart’s source range, and — most usefully — render one as an image.

Create chart and get image
POST /me/drive/items/{id}/workbook/worksheets('Report')/charts/add
{ "type": "ColumnClustered", "sourceData": "A1:B12", "seriesBy": "Auto" }

GET /me/drive/items/{id}/workbook/worksheets('Report')/charts('Chart 1')/image

The image call returns a base64 string; decode it and you have a PNG, ready to embed in an email (combined with Graph in Practice #4) or drop into a Teams notification — the replacement for “open Excel and screenshot the chart.” One trap: chart IDs contain { and } characters, which must be URL-encoded (%7B, %7D) in the path.

Permissions: the Excel API is delegated-centric #

Here is this API’s biggest practical constraint. Looking at the workbook API permission tables, many endpoints do not support application permissions (usedRange and others list only delegated Files.ReadWrite). That means a fully unattended daemon cannot be built cleanly on a single app permission.

The practical options:

  1. Delegated permissions + an automation account: run under a dedicated account’s delegated token — the same workaround used for Teams notifications in Graph in Practice #6, with the account and token lifecycle management that entails.
  2. Solve it at the data layer: if unattended is the goal, treat Excel as the presentation and calculation layer only, and route data loading through the drive API (full application-permission support) by uploading CSVs or files.
  3. Check the permission table per endpoint: support varies by endpoint and can change, so verifying the documented permission table for each call you plan to use is a mandatory design step.

Summary #

  • The workbook API attaches /workbook to a drive item and works on Excel internals (sheets, tables, ranges, charts). File upload is the drive API’s job.
  • Making more than one call means creating a session. persistChanges: true is the production default; false is calculator mode that never touches the file. Sessions expire after minutes of inactivity, so plan recreation logic.
  • Build report pipelines as table-row appends, and leave aggregation and chart refresh to Excel’s formulas.
  • Charts extract as base64 images ready for email and notifications. Chart-ID braces must be URL-encoded.
  • The Excel API is delegated-centric: check per-endpoint permission tables before designing unattended automation, and lean on automation accounts or a data-layer workaround.
X