---
title: "Write Row"
description: "Append one or many rows to a worksheet in a OneDrive-hosted Excel file."
icon: "table"
---

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
  [["Alice", "42"], ["Bob", "31"], ["Carol", "29"]]
  ```
- Anything else → parsed as **RFC 4180 CSV**:
  ```text
  Alice,42
  Bob,31
  Carol,29
  ```
  Wrap fields containing commas or newlines in double quotes; escape literal double quotes by doubling them:
  ```text
  "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
  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.
