Skip to content

feat: add SharePoint / OneDrive Excel exporter - #1730

Open
singhankur wants to merge 1 commit into
pinterest:masterfrom
singhankur:feat/sharepoint-exporter
Open

feat: add SharePoint / OneDrive Excel exporter#1730
singhankur wants to merge 1 commit into
pinterest:masterfrom
singhankur:feat/sharepoint-exporter

Conversation

@singhankur

Copy link
Copy Markdown

Summary

Adds a new SharePointExporter that exports query results to an Excel workbook on SharePoint or OneDrive via the Microsoft Graph API.

  • Joins the existing Google Sheets and CSV exporters as a first-class result export target
  • Works for both personal OneDrive and team SharePoint site document libraries
  • Creates the workbook automatically if it doesn't exist
  • Streams results in batches, so large result sets don't hit a single-request ceiling
  • Returns the workbook's webUrl so users can open it directly from the Querybook UI

Files changed

File Description
querybook/server/lib/export/exporters/sharepoint_exporter.py New SharePointExporter class
requirements/exporter/sharepoint.txt msal + openpyxl dependencies
plugins/exporter_plugin/__init__.py Usage example (commented out)

How it works

  1. Auth — MSAL Authorization Code flow. On first export the user is redirected to Microsoft login; the token (including refresh token via offline_access) is stored in user properties and refreshed transparently on subsequent calls.

  2. Drive resolution — defaults to the user's OneDrive. If a SharePoint site URL is provided, the Graph API resolves the site's default document library.

  3. Workbook lifecycle — checks for an existing file at the specified path; if absent, uploads a minimal openpyxl-generated .xlsx as the initial content.

  4. Writing data — uses the Graph API Excel workbook range PATCH endpoint (/workbook/worksheets/{name}/range(address='A1:Z1000')), batching rows in chunks of 1,000 to stay within API limits.

Configuration

An Azure AD app registration is required. Set three environment variables:

SHAREPOINT_CLIENT_ID     # Azure AD application (client) ID
SHAREPOINT_TENANT_ID     # Tenant ID, or "common" for multi-tenant
SHAREPOINT_CLIENT_SECRET # Client secret

Then register the exporter in plugins/exporter_plugin/__init__.py:

from lib.export.exporters.sharepoint_exporter import SharePointExporter
ALL_PLUGIN_EXPORTERS = [SharePointExporter()]

Test plan

  • Register an Azure AD app with Files.ReadWrite and Sites.ReadWrite.All delegated permissions
  • Set the three env vars and start Querybook
  • Run a query and export to a new workbook — verify file is created in OneDrive
  • Export to an existing workbook name — verify data is written (not creating duplicates)
  • Export with a SharePoint site URL — verify file is created in the team site
  • Export with folder_path set — verify file lands in the correct subfolder
  • Revoke the token and re-export — verify re-auth flow works cleanly
  • Confirm Google Sheets and other existing exporters are unaffected

🤖 Generated with Claude Code

Add SharePointExporter for exporting query results to an Excel workbook
on SharePoint or OneDrive using the Microsoft Graph API.

Features:
- OAuth2 Authorization Code flow via MSAL (token stored per user,
  auto-refreshed using the offline_access scope)
- Writes to the user's OneDrive by default; accepts an optional
  SharePoint site URL to target a team site document library
- Optional folder path within the drive
- Creates the workbook (.xlsx) if it doesn't exist, using openpyxl
  for the initial empty file upload
- Streams result rows in configurable batches (default 1,000 rows)
  to stay within Graph API request limits
- Returns the webUrl of the workbook for display in the UI

Configuration (environment variables set by the admin):
  SHAREPOINT_CLIENT_ID     — Azure AD app registration client ID
  SHAREPOINT_TENANT_ID     — Tenant ID, or "common" for multi-tenant
  SHAREPOINT_CLIENT_SECRET — Client secret

Adds requirements/exporter/sharepoint.txt with msal and openpyxl.
@singhankur
singhankur force-pushed the feat/sharepoint-exporter branch from a7d4cb1 to ff1f16b Compare July 29, 2026 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant