SheetLink Forms beta

Send form submissions to Excel Online automatically

Not a CSV export you run on Fridays. Rows appear in your Excel table as submissions happen.

Excel as a live destination, not an export format

"Export to Excel" usually means a button that produces a stale CSV. This is the other thing: SheetLink Forms writes each accepted submission directly into an Excel Online workbook through the Microsoft Graph API, as it arrives. The workbook in your Microsoft 365 account is the working system - open it and today's leads are already there, sitting in a table with your formulas, filters, and pivot tables downstream.

It is the same pipeline as the Google Sheets destination - same endpoint, same screening, same delivery log - with one structural difference that this guide centers on: Excel delivery writes into a table, and the table's columns define the row shape.

The table model: why a table and not "the sheet"

A Google Sheet is a loose grid; SheetLink can seed a header row on an empty sheet and append under it. Excel is different by design. Rows are written into an Excel table (the structured object you get from Insert -> Table), not into arbitrary cells - and the table's columns are the contract. Whatever columns the table has, in whatever order, is exactly the shape each delivered row takes. Fields are matched to those column headers; the table defines the shape, not the submission.

This is a feature, not a limitation. Because the table is the contract:

  1. Rows always land inside the table, so references like Table1[Email], filters, and PivotTables pick up new submissions automatically.
  2. Your columns cannot drift: a stray field in a submission cannot invent a column and shift your layout.
  3. Formulas in adjacent columns auto-fill down as the table grows, Excel's normal table behavior.

Setup, step by step

  1. Prepare the table. In Excel Online (Microsoft 365), put your column headers in a row - Name, Email, Message, plus any attribution columns like gclid or utm_campaign - select them, and choose Insert -> Table with "My table has headers" checked.
  2. Connect Microsoft 365 in the SheetLink dashboard and pick the workbook and the table you just created as the form's destination.
  3. Name your form fields to match the headers. Matching is case and punctuation insensitive - Email, email, and E-mail all land in an "Email" column - so most forms need no manual mapping. Explicit per-field mapping is there for the names that genuinely differ.
  4. Point your form at the endpoint and send a test submission.

The form itself is ordinary HTML:

<form action="https://sheetlinkforms.com/f/slf_yourtoken" method="POST">
  <input name="name" placeholder="Name" required>
  <input name="email" type="email" placeholder="Work email" required>
  <textarea name="message" placeholder="Message"></textarea>
  <input name="_slhp" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px">
  <button type="submit">Send</button>
</form>

The _slhp input is the spam honeypot; keep it in every form. JSON posts and the sl.js embed (AJAX submits, click-ID capture) work identically with an Excel destination - the destination is a per-form setting, invisible to the page.

How a submission becomes a table row

The path from POST to cell, as covered on how it works:

  1. The endpoint accepts the submission (urlencoded, JSON, or multipart - file parts are currently dropped; 256 KB body cap).
  2. Screening runs: honeypot, rate limits, origin rules, content heuristics. Suspicious items are quarantined for one-click review, never silently dropped.
  3. Fields are matched to the table's column headers; unmatched columns are simply left empty in that row.
  4. An asynchronous worker appends the row to the table via Microsoft Graph - direct, no Zapier, no middleman - retrying at 5 minutes, 30 minutes, and 2 hours if Graph is briefly unavailable.
  5. The attempt is recorded in the delivery log.

Cell values are also run through a formula-injection guard: leading =, +, -, and @ are escaped, so a hostile submission cannot plant an executable formula in your workbook.

Edge cases

  1. Adding a column later: add it to the table (not just a nearby cell), and matching fields start filling it from the next delivery. Existing rows keep their empty cell, as you would expect.
  2. Renaming a header: the contract follows the header. Rename Email to Work Email and the automatic match to a field named email breaks - fix the field name or add an explicit mapping.
  3. Data outside the table: notes or scratch formulas in cells beside the table are untouched; deliveries only ever append rows to the table object itself.
  4. Personal vs work accounts: the destination is Excel Online on Microsoft 365. Files must live where your connected account can reach them through Graph.
  5. Need Google Sheets instead (or both)? Each form picks its destination; the Sheets walkthrough is at HTML form to Google Sheets without a backend.

Troubleshooting

  1. Row missing: check the delivery log first - a pending retry looks like a missing row for a few minutes - then the quarantine queue.
  2. Values in the wrong column or missing: the field name does not match a table header. Remember matching is against the table's headers, insensitively; anything further apart than case and punctuation needs an explicit mapping.
  3. Rows appearing below the table instead of in it: the target was not actually an Excel table. Convert the range with Insert -> Table and re-pick it as the destination.
  4. A value shows a leading apostrophe or quote: that is the formula-injection guard escaping a value that began with =, +, -, or @ - working as intended.

See rows land live on the demo, then join the free beta via the waitlist - no per-submission fees, during beta or ever.

FAQ

Does this work with desktop Excel files on my computer?

The destination is Excel Online in Microsoft 365, reached through the Microsoft Graph API - the workbook needs to live in your Microsoft cloud storage. Once there, you can keep opening it in desktop Excel; rows delivered online sync down like any other edit.

What happens to submission fields that have no matching column?

The table's columns define the row shape, so a field with no matching header is not written and cannot create a column on its own. If you want it captured, add the column to the table or set an explicit mapping - deliveries from then on will fill it.

Can one form deliver to both Excel and Google Sheets?

The destination is chosen per form. To feed both a workbook and a sheet, run the flow into one destination as the system of record - the page-side integration (endpoint, embed, webhooks) is identical either way, so switching or splitting forms later is a dashboard change, not a code change.

Do formulas in my workbook survive incoming rows?

Yes. Deliveries append rows to the table object only; cells outside the table are never touched, and calculated columns inside the table auto-fill down for new rows, which is standard Excel table behavior. The formula-injection guard also prevents submitted values from executing as formulas.

Is Excel delivery slower than Google Sheets delivery?

Both destinations use the same asynchronous worker writing directly to the provider API - Microsoft Graph for Excel, the Sheets API for Google - with the same retry schedule (5 min / 30 min / 2 h) and the same delivery log. Rows typically land within moments of an accepted submission either way.

Related guides: Send an HTML form to Google Sheets without a backend ยท Forms to a spreadsheet without Zapier (and why you might want that)

Request an invite Developer docs