Openclaw-master-skills microsoft-excel
git clone https://github.com/LeoYeAI/openclaw-master-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/LeoYeAI/openclaw-master-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/microsoft-excel" ~/.claude/skills/leoyeai-openclaw-master-skills-microsoft-excel && rm -rf "$T"
T=$(mktemp -d) && git clone --depth=1 https://github.com/LeoYeAI/openclaw-master-skills "$T" && mkdir -p ~/.openclaw/skills && cp -r "$T/skills/microsoft-excel" ~/.openclaw/skills/leoyeai-openclaw-master-skills-microsoft-excel && rm -rf "$T"
skills/microsoft-excel/SKILL.md- makes HTTP requests (curl)
- references .env files
Microsoft Excel
Access the Microsoft Excel API (via Microsoft Graph) with managed OAuth authentication. Read and write workbooks, worksheets, ranges, tables, and charts stored in OneDrive or SharePoint.
Quick Start
# List worksheets in a workbook python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Base URL
https://gateway.maton.ai/microsoft-excel/{native-api-path}
Replace
{native-api-path} with the actual Microsoft Graph API endpoint path. The gateway proxies requests to graph.microsoft.com and automatically injects your OAuth token.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as
MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Microsoft Excel OAuth connections at
https://ctrl.maton.ai.
List Connections
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=microsoft-excel&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Create Connection
python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'microsoft-excel'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Get Connection
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Response:
{ "connection": { "connection_id": "4751ac89-3970-47e1-872c-eacdf4291732", "status": "ACTIVE", "creation_time": "2026-02-07T00:43:18.565932Z", "last_updated_time": "2026-02-07T00:43:29.729782Z", "url": "https://connect.maton.ai/?session_token=...", "app": "microsoft-excel", "metadata": {} } }
Open the returned
url in a browser to complete OAuth authorization.
Delete Connection
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Specifying Connection
If you have multiple Microsoft Excel connections, specify which one to use with the
Maton-Connection header:
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/microsoft-excel/v1.0/me/drive') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '4751ac89-3970-47e1-872c-eacdf4291732') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
If omitted, the gateway uses the default (oldest) active connection.
Workbook Access Patterns
You can access workbooks using either ID-based or path-based patterns:
By File ID:
/microsoft-excel/v1.0/me/drive/items/{file-id}/workbook/...
By File Path:
/microsoft-excel/v1.0/me/drive/root:/{path-to-file}:/workbook/...
API Reference
Drive Operations
Get Drive Info
GET /microsoft-excel/v1.0/me/drive
List Root Files
GET /microsoft-excel/v1.0/me/drive/root/children
Search for Excel Files
GET /microsoft-excel/v1.0/me/drive/root/search(q='.xlsx')
Upload Excel File
PUT /microsoft-excel/v1.0/me/drive/root:/{filename}.xlsx:/content Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet {binary xlsx content}
Session Management
Sessions improve performance for multiple operations. Recommended for batch operations.
Create Session
POST /microsoft-excel/v1.0/me/drive/root:/{path}:/workbook/createSession Content-Type: application/json { "persistChanges": true }
Response:
{ "persistChanges": true, "id": "cluster=PUS7&session=..." }
Use the session ID in subsequent requests:
workbook-session-id: {session-id}
Close Session
POST /microsoft-excel/v1.0/me/drive/root:/{path}:/workbook/closeSession workbook-session-id: {session-id}
Worksheet Operations
List Worksheets
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets
Response:
{ "value": [ { "id": "{00000000-0001-0000-0000-000000000000}", "name": "Sheet1", "position": 0, "visibility": "Visible" } ] }
Get Worksheet
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')
Create Worksheet
POST /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets Content-Type: application/json { "name": "NewSheet" }
Update Worksheet
PATCH /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1') Content-Type: application/json { "name": "RenamedSheet", "position": 2 }
Delete Worksheet
DELETE /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('{worksheet-id}')
Returns 204 No Content on success.
Range Operations
Get Range
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/range(address='A1:B2')
Response:
{ "address": "Sheet1!A1:B2", "values": [ ["Hello", "World"], [1, 2] ], "formulas": [ ["Hello", "World"], [1, 2] ], "text": [ ["Hello", "World"], ["1", "2"] ], "numberFormat": [ ["General", "General"], ["General", "General"] ], "rowCount": 2, "columnCount": 2 }
Get Used Range
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/usedRange
Update Range
PATCH /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/range(address='A1:B2') Content-Type: application/json { "values": [ ["Updated", "Values"], [100, 200] ] }
Clear Range
POST /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/range(address='A1:B2')/clear Content-Type: application/json { "applyTo": "All" }
Options:
All, Formats, Contents
Table Operations
List Tables
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/tables
Create Table from Range
POST /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/tables/add Content-Type: application/json { "address": "A1:C4", "hasHeaders": true }
Response:
{ "id": "{6D182180-5F5F-448B-9E9C-377A5251CFC5}", "name": "Table1", "showHeaders": true, "showTotals": false, "style": "TableStyleMedium2" }
Get Table
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/tables('Table1')
Update Table
PATCH /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/tables('Table1') Content-Type: application/json { "name": "PeopleTable", "showTotals": true }
Get Table Rows
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/tables('Table1')/rows
Response:
{ "value": [ { "index": 0, "values": [["Alice", 30, "NYC"]] }, { "index": 1, "values": [["Bob", 25, "LA"]] } ] }
Add Table Row
POST /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/tables('Table1')/rows Content-Type: application/json { "values": [["Carol", 35, "Chicago"]] }
Delete Table Row
DELETE /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/tables('Table1')/rows/itemAt(index=0)
Returns 204 No Content on success.
Get Table Columns
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/tables('Table1')/columns
Add Table Column
POST /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/tables('Table1')/columns Content-Type: application/json { "values": [["Email"], ["alice@example.com"], ["bob@example.com"]] }
Named Items
List Named Items
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/names
Charts
List Charts
GET /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/charts
Add Chart
POST /microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets('Sheet1')/charts/add Content-Type: application/json { "type": "ColumnClustered", "sourceData": "A1:C4", "seriesBy": "Auto" }
Code Examples
JavaScript
// Get range values const response = await fetch( "https://gateway.maton.ai/microsoft-excel/v1.0/me/drive/root:/data.xlsx:/workbook/worksheets('Sheet1')/range(address='A1:B10')", { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json(); console.log(data.values);
Python
import os import requests # Update range values response = requests.patch( "https://gateway.maton.ai/microsoft-excel/v1.0/me/drive/root:/data.xlsx:/workbook/worksheets('Sheet1')/range(address='A1:B2')", headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, json={'values': [['Name', 'Age'], ['Alice', 30]]} ) print(response.json())
Notes
- Only
files are supported (not legacy.xlsx
).xls - Worksheet names with special characters need URL encoding
- Table and worksheet IDs containing
and{
must be URL-encoded (}
and%7B
)%7D - Sessions expire after ~5 minutes of inactivity (persistent) or ~7 minutes (non-persistent)
- Use
in value arrays to skip updating specific cellsnull - Blank cells should use
(empty string)"" - Range addresses use A1 notation (e.g.,
,A1:C10
)Sheet1!A1:B5 - IMPORTANT: When using curl commands, use
when URLs contain parentheses to disable glob parsingcurl -g - IMPORTANT: When piping curl output to
or other commands, environment variables likejq
may not expand correctly in some shell environments$MATON_API_KEY
Error Handling
| Status | Meaning |
|---|---|
| 400 | Missing Microsoft Excel connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 404 | Item not found or session expired |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Microsoft Graph API |
Common Error Codes
| Code | Description |
|---|---|
| File or resource doesn't exist |
| Worksheet or table with that name already exists |
| Invalid parameter or missing required field |
| Session expired or doesn't exist |
Troubleshooting: API Key Issues
- Check that the
environment variable is set:MATON_API_KEY
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
. For example:microsoft-excel
- Correct:
https://gateway.maton.ai/microsoft-excel/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets - Incorrect:
https://gateway.maton.ai/v1.0/me/drive/root:/workbook.xlsx:/workbook/worksheets