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

# Write Row

> Append one or many rows to a worksheet in a OneDrive-hosted Excel file.

The **Excel — Write Row** step appends data to a worksheet in an Excel file stored in OneDrive or SharePoint. It can append a single row or a batch of rows in a single, atomic Graph API call.

Use it whenever an agent needs to record output to a spreadsheet — logging analysis results, building a tracker, exporting structured data, or fanning workflow outputs into a shared sheet.

***

## How it works

The step calls the Microsoft Graph API on your behalf using a Microsoft OAuth credential. It picks the most reliable write path automatically:

* If the target worksheet contains exactly **one Excel Table**, the step uses Graph's `tables/rows/add` endpoint. The Table itself decides the row indexes server-side. This applies to **both** single-row writes and **Row Values Batch** writes — each call is a single atomic Graph request, and concurrent agents writing to the same Table will not overwrite each other. No locking or coordination on the platform side is needed.
* If the worksheet has **no Excel Table** (or more than one), the step computes the next available row, takes an in-execution lock, and writes via a range `PATCH`. Concurrent appends from the same agent execution are serialized; concurrent appends from different executions on the same sheet rely on the next-available-row computation and may collide under concurrent executions.

<Tip>
  For the most predictable cross-agent behavior — especially when multiple agents or multiple executions may write to the same sheet at once — format the destination region as an Excel Table (`Insert → Table` in Excel). Both single-row and multi-row writes then go through the atomic Table append path.
</Tip>

***

## Prerequisites

* The **OneDrive Excel** steps must be enabled on your workspace (feature flag: `step-sdk-onedrive-excel`).
* A **Microsoft OAuth credential** that has access to the target file (delegated or end-user auth — see [Microsoft Authentication](/integrations/Tools/Microsoft%20Authentication)).
* The Excel file already exists at the configured **Path**. The step does not create the file.
* The target **Worksheet Name** exists. Use the [Add Worksheet](/building-and-deploying-agents/agent-basics/onedrive-excel-add-worksheet) step first if you need to create it.

***

## Inputs

| Parameter            | Required    | Description                                                                                                                                                                   |
| -------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Credential**       | Yes         | The Microsoft OAuth credential used to access the file.                                                                                                                       |
| **Path**             | Yes         | The file path in OneDrive, for example `/Documents/MySpreadsheet.xlsx`.                                                                                                       |
| **Worksheet Name**   | Yes         | The worksheet to write to.                                                                                                                                                    |
| **Row Values**       | Conditional | Comma-separated values for a single row, for example `Alice,42,active`. Required unless **Row Values Batch** is provided.                                                     |
| **Row Values Batch** | Conditional | A batch of rows to append in one operation. CSV (`a,b\nc,d`) or JSON 2D (`[["a","b"],["c","d"]]`); format is auto-detected. Takes precedence over **Row Values**.             |
| **Range Address**    | No          | A cell or range to write to, for example `A5:C5`, `C10`, or `C10:E14`. If empty, the step appends to the next available row. See [Range Address rules](#range-address-rules). |

<Info>
  All text inputs accept `{{variable}}` expressions so you can wire in values from earlier steps.
</Info>

### Row Values Batch — input formats

The batch input is auto-detected by the first non-whitespace character:

* Starts with `[` → parsed as **JSON 2D array**:
  ```json theme={null}
  [["Alice", "42"], ["Bob", "31"], ["Carol", "29"]]
  ```
* Anything else → parsed as **RFC 4180 CSV**:
  ```text theme={null}
  Alice,42
  Bob,31
  Carol,29
  ```
  Wrap fields containing commas or newlines in double quotes; escape literal double quotes by doubling them:
  ```text theme={null}
  "Hello, world",42
  "She said ""hi""",7
  ```

All rows must have the **same number of columns**. The step rejects jagged input with a clear error.

### Range Address rules

| Sheet has an Excel Table? | Range Address provided?     | Behavior                                                                                                                       |
| ------------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Yes                       | —                           | **Ignored.** Graph's `tables/rows/add` always appends to the Table; a warning is logged.                                       |
| No                        | empty                       | Appends starting at column `A` on the next available row.                                                                      |
| No                        | single cell (e.g. `C10`)    | Uses the cell as the **start cell**. The column span of the data determines the end column.                                    |
| No                        | full range (e.g. `C10:D12`) | The range must match the data shape exactly (same row count and column count). The step rejects mismatches with a clear error. |

Sheet-qualified addresses (`Sheet1!A1`) and absolute markers (`$A$1`) are accepted and normalized.

***

## Outputs

| Variable        | Type          | Description                                                                                                                                                                       |
| --------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RowIndex`      | `int \| null` | The 1-based worksheet row of the first row written. `null` when the write went through the Excel Table append path (Graph returns only a table-relative index for that endpoint). |
| `StartRowIndex` | `int \| null` | Same value and semantics as `RowIndex`; provided for clarity when working with batches.                                                                                           |
| `RowsWritten`   | `int`         | The number of rows written. `1` for single-row writes; the batch size for multi-row writes. Always populated.                                                                     |

Reference these in downstream steps with the standard syntax, for example `{{Steps.Write_Row.RowsWritten}}`.

<Note>
  If you need the absolute row number after writing into a Table, follow up with a [Read File](/building-and-deploying-agents/agent-basics/onedrive-excel-read-file) step or a Graph call to look up the most recent rows. The Table path intentionally trades that lookup for cross-agent ordering safety.
</Note>

***

## Examples

### 1) Append a single row

Log an enrichment result to a tracker.

* **Path:** `/Reports/Enrichment Tracker.xlsx`
* **Worksheet Name:** `Runs`
* **Row Values:** `{{Steps.Lookup.CompanyName}},{{Steps.Lookup.Industry}},{{Steps.Lookup.Confidence}}`

### 2) Append a batch from JSON

A prior step has produced an array of records and a small formatter converted it to a 2D array.

* **Path:** `/Reports/Daily Export.xlsx`
* **Worksheet Name:** `Today`
* **Row Values Batch:** `{{Steps.Format.RowsAsJson2D}}`

For 50 records this is a single Graph call instead of 50 — significantly less API quota usage and an atomic write on Table sheets.

### 3) Append a batch from CSV starting at a specific column

The first two columns of the sheet hold static IDs maintained by another team. You only want to write into columns C–E.

* **Path:** `/Reports/Shared Tracker.xlsx`
* **Worksheet Name:** `Q2`
* **Range Address:** `C10` (single cell — used as the start)
* **Row Values Batch:**
  ```text theme={null}
  Alice,42,active
  Bob,31,active
  Carol,29,pending
  ```

The step writes to `C10:E12` because the data is 3 rows × 3 columns.

### 4) Append a batch into a precise range

Same scenario as above, but the range is fully specified for clarity.

* **Range Address:** `C10:E12`
* **Row Values Batch:** same 3×3 CSV

If the batch shape doesn't match (e.g. 4 rows or 2 columns), the step fails fast with a shape-mismatch error.

***

## Notes and limitations

* **Single file per invocation.** Use a Loop step over a list of paths if you need to write to multiple files.
* **Path resolution caches per execution.** The first write looks up the file ID; subsequent writes from the same execution reuse the cached ID.
* **Table detection caches per execution.** The list of Tables on the worksheet is fetched once per execution per `path|worksheet` pair.
* **Graph soft request limits.** Very large batches can be rejected by Graph (it has a per-request body cap). If you need to write tens of thousands of rows, chunk the input upstream and call the step multiple times.
* **No file creation.** The step does not create missing files or worksheets. Pair with [Add Worksheet](/building-and-deploying-agents/agent-basics/onedrive-excel-add-worksheet) if needed.
* **No typed cell values.** Cell values are written as strings; Graph coerces them to numbers/dates where the format allows. Pre-format the destination cells if you need a specific cell type.

***

## Troubleshooting

### "Either RowValues or RowValuesBatch must be provided"

Provide one of the two. Leaving both empty is invalid.

### "Row N has X columns; expected Y"

Your batch input is jagged. Make sure every row has the same column count. Empty trailing fields in CSV still count as a column — `a,b,` is three columns.

### "Range A1:C3 does not match batch shape (rows × cols)"

The full range you provided doesn't match the data. Either remove the end cell to let the step infer it, or fix the range/data so they agree.

### Authentication error / 401 / 403

* Confirm the selected credential is still valid (re-authenticate if expired).
* Confirm the credential's user has at least edit access to the file.
* For end-user auth, verify the running user has connected their Microsoft account in **User Settings**.

### My rows landed in the wrong order across agents

Format the destination range as an Excel Table. The step then uses Graph's atomic `tables/rows/add`, which assigns row indexes server-side and avoids collisions.
