> ## Documentation Index
> Fetch the complete documentation index at: https://agents.nanonets.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# OneDrive Excel Update

> Inserts or upserts rows in an `.xlsx` workbook stored in the connected user's OneDrive (or a SharePoint document library reachable from it).

Inserts or upserts rows in an `.xlsx` workbook stored in the connected user's OneDrive (or a SharePoint document library reachable from it). Display name **"OneDrive Excel Update"**.

For uploading or replacing whole files, see [`export_to_onedrive`](/docs/tools/export-to-onedrive); for reading files in, see [`import_from_onedrive`](/docs/tools/import-from-onedrive).

## Authentication and enablement

* **Connector**: OneDrive OAuth. The tool is only registered when OneDrive/SharePoint OAuth credentials are configured; `access_token` is injected from the workspace's OneDrive integration (`x-variable-service: onedrive`, `first_active`) and is never chosen by the model.
* **Default state**: **off**. Off by default — enable it in the agent's Tools panel.
* **Not supported by Microsoft**: workbooks on *consumer* OneDrive, and the legacy `.xls` format. Office Open XML (`.xlsx`) on a business tenant only.

## Inputs

| Field            | Required     | Notes                                                                                      |
| ---------------- | ------------ | ------------------------------------------------------------------------------------------ |
| `strategy`       | yes          | `insert` (append) or `upsert` (update on key match, else append).                          |
| `columns`        | yes          | Header names, column letters (`A`, `B`) or 1-based numbers. Fuzzy-matched against headers. |
| `rows`           | yes          | Array of rows; each row's length must equal `columns`.                                     |
| `item_id`        | one of these | Graph drive item ID — used directly when present.                                          |
| `file_url`       | one of these | OneDrive/SharePoint sharing URL, resolved to an item ID.                                   |
| `file_path`      | one of these | Path in the connected user's OneDrive, e.g. `Documents/Exports/140 Form.xlsx`.             |
| `worksheet_name` | no           | Defaults to the first worksheet. Fuzzy-matched against the workbook's sheet names.         |
| `key_column`     | upsert only  | Column to match on; must also appear in `columns`.                                         |

## Outputs

`rows_inserted` and `rows_updated` are **verified** counts — the number of rows confirmed present after the write, not the number requested. `warnings` carries non-fatal data problems (see duplicate keys below).

```json theme={null}
{
  "tool_name": "onedrive_excel_update_tool",
  "item_id": "017KADUB…",
  "worksheet_name": "DAS 140 FORM",
  "strategy": "insert",
  "rows_inserted": 1,
  "rows_updated": 0,
  "warnings": [],
  "completed_at": "2026-07-31T09:15:04Z"
}
```

## How rows are written (and why it matters)

Excel over Microsoft Graph has **no atomic append for a plain worksheet range**, no `If-Match`/ETag at the workbook object layer, and no idempotency key. Microsoft's [own guidance](https://learn.microsoft.com/en-us/graph/workbook-best-practice) is that concurrent writes to one workbook should not be attempted at all: *"for each workbook, only send the next request after receiving a successful response to the current request."*

The tool therefore:

1. **Serializes writes per (workbook, worksheet)** using a cross-process Postgres advisory lock. Two agents (or two steps of the same agent) writing the same worksheet queue rather than collide. A writer waits up to **60s**; past that the step fails with `another write to worksheet '…' is still in progress` and is safe to retry.
2. **Appends through an Excel table** (`POST /workbook/tables/{t}/rows/add` with `index: null`) so Graph — not this tool — picks the row. All rows go in one request.
3. **Creates a table on first use if the worksheet has none**, covering the worksheet's existing used range with `hasHeaders: true`. **This is a visible change to the customer's file**: the data region becomes an Excel Table. Filter buttons and banded rows are explicitly switched back off, but the table itself remains. If the worksheet already has **several** tables (e.g. an unrelated lookup range), the write targets the one whose header row carries the given `columns`; it refuses to guess when that is ambiguous and falls back to the range path.
4. **Verifies the write.** On an ambiguous failure (5xx or timeout, where the row may or may not have landed) the tool reads the table back and reconciles instead of re-sending, because a blind retry would duplicate the row.

### Fallback

Worksheets that cannot be represented as a table — merged cells, an unusable range, or a `columns` entry mapping beyond the table's last column — fall back to writing an absolute range (`PATCH /range(address='A41:R41')`). This path still computes the target row, so it is correct **only** because the lock is held. It is otherwise equivalent.

## Limits and side effects

* **Creates an Excel Table** in the target worksheet on first write (see above).
* `upsert` matching is case-insensitive and whitespace-trimmed on the key column.
* `upsert` replaces the whole matched row in one request, carrying over columns not named in `columns`.
* Row width on the table path must match the table exactly; wider writes take the fallback path.
* Throttling: Graph publishes only app-level Excel limits (5,000 req/10s per app, 1,500 per tenant) and treats per-workbook cost as resource-based. `429`/`Retry-After` is honoured with backoff.

## Expected errors

| Message                                                          | Cause and remedy                                                                                                                               |
| ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `the workbook is currently locked for editing by another client` | Someone has the file open in Excel, or a co-authoring session holds it (Graph `423`/`accessConflict`). Not retried by design — close the file. |
| `another write to worksheet '…' is still in progress after 1m0s` | Sustained contention on one worksheet. The step is retryable; consider batching rows into fewer calls.                                         |
| `failed to determine the next free row`                          | Fallback path could not read the used range. The tool refuses to guess rather than risk overwriting the header row.                            |
| `column '…' not found`                                           | `columns` entry matched no header, letter, or number.                                                                                          |
| `worksheet '…' is empty, cannot determine column positions`      | The target worksheet has no header row to map columns against.                                                                                 |
| `N rows already match key '…'; updated the first one` (warning)  | Pre-existing duplicate keys. The first match is updated and the write succeeds; clean up the duplicates in the workbook.                       |

## Audit

Outbound Microsoft Graph calls are audited (host only — paths and query strings are not logged).
