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

# Integrate Unsiloed with Microsoft Excel

> Build an Excel task-pane add-in, verify your Unsiloed API key, and write the connection result into a worksheet.

An Excel task-pane add-in connects a workbook to the Unsiloed API. Its JavaScript
makes API requests, and Office.js reads and writes worksheet cells.

In this guide, we'll build a local add-in that checks your Unsiloed API key and
writes the organization name into a new worksheet. This gives us a working
connection to extend with document-processing workflows.

> [!NOTE]
>
> Looking to extract data **from** an `.xls` or `.xlsx` workbook instead? You
> don't need an add-in. Upload the workbook to
> [`POST /parse/excel`](https://www.unsiloed.ai/docs/api-reference/parser/parse-excel), then poll
> `GET /parse/{job_id}` until the job succeeds. Each table segment includes
> `cell_references` that trace it back to its sheet and cell range. The
> [Excel parsing guide](https://www.unsiloed.ai/docs/document-processing/parsing/excel.md) has upload examples
> and configuration options.

## How Unsiloed Works with Excel

The connection follows this path:

`Excel → Task-Pane Add-in → Local Server → Unsiloed API → Add-in → Excel`

The add-in is a web page loaded beside the workbook. An XML manifest tells Excel
where to load it and requests workbook access. We'll use Vite to serve the page
with a trusted local HTTPS certificate. Vite also forwards the connection check
to Unsiloed, because the usage endpoint blocks direct browser requests from
localhost.

## Requirements for the Excel Integration

Before you start, gather:

* Node.js 22.12 or higher
* A Microsoft account that can upload custom add-ins in [Excel for the web](https://excel.cloud.microsoft)
* An Unsiloed API key from the [Unsiloed dashboard](https://app.unsiloed.ai)

The steps below use Chrome on macOS and Excel for the web. No Microsoft Office
desktop installation is needed.

## Create the Local Add-in

We'll create three files: the server configuration, the task-pane page, and the
manifest. Open Terminal and run:

```bash theme={null}
mkdir unsiloed-excel-connection
cd unsiloed-excel-connection
npm init -y
npm install --save-dev vite office-addin-dev-certs
```

Create `vite.config.mjs` in that directory:

```javascript vite.config.mjs theme={null}
import { defineConfig } from "vite";
import devCerts from "office-addin-dev-certs";

export default defineConfig(async ({ command }) => {
  if (command !== "serve") return {};

  return {
    server: {
      host: "localhost",
      port: 3000,
      strictPort: true,
      https: await devCerts.getHttpsServerOptions(),
      proxy: {
        "/unsiloed-usage": {
          target: "https://platformbackend.unsiloed.ai",
          changeOrigin: true,
          rewrite: () => "/api/v1/org/get_usage",
        },
      },
    },
  };
});
```

The [Vite proxy](https://vite.dev/config/server-options#server-proxy) forwards the
request and its `api-key` header to the read-only
[organization usage endpoint](https://www.unsiloed.ai/docs/api-reference/organization/usage.md). The key isn't
stored in this configuration. Document-processing workflows use the separate API
at `prod.visionapi.unsiloed.ai`, which the cookbook calls directly from the task
pane.

The `strictPort` setting makes Vite stop with an error if port 3000 is busy,
instead of moving to a port the manifest doesn't point to.

## Add the Connection Check

Create `index.html` beside the configuration file:

```html index.html theme={null}
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Unsiloed Connection</title>
  <script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
</head>
<body>
  <h1>Connect to Unsiloed</h1>
  <form id="form">
    <label for="api-key">Unsiloed API key</label>
    <input id="api-key" type="password" autocomplete="off" required />
    <button id="check" type="submit" disabled>Check connection</button>
  </form>
  <p id="status" role="status">Open this page as an Excel add-in.</p>

  <script type="module">
    const form = document.querySelector("#form");
    const keyInput = document.querySelector("#api-key");
    const button = document.querySelector("#check");
    const status = document.querySelector("#status");

    Office.onReady((info) => {
      if (info.host === Office.HostType.Excel) {
        button.disabled = false;
        status.textContent = "Enter your API key to check the connection.";
      }
    });

    form.addEventListener("submit", async (event) => {
      event.preventDefault();
      button.disabled = true;
      status.textContent = "Checking connection…";

      try {
        const response = await fetch("/unsiloed-usage", {
          headers: { "api-key": keyInput.value.trim() },
          signal: AbortSignal.timeout(15000),
        });
        if (!response.ok) {
          const hint = response.status === 401 ? " Check your API key." : "";
          throw new Error(`Connection failed (HTTP ${response.status}).${hint}`);
        }
        const usage = await response.json();
        if (typeof usage.org_name !== "string") {
          throw new Error("Unsiloed returned no organization name.");
        }
        const name = /^[=+\-@]/.test(usage.org_name)
          ? "'" + usage.org_name
          : usage.org_name;

        await Excel.run(async (context) => {
          const sheet = context.workbook.worksheets.add();
          const range = sheet.getRange("A1:B1");
          sheet.getRange("B1").numberFormat = [["@"]];
          range.values = [["Unsiloed organization", name]];
          range.format.autofitColumns();
          sheet.activate();
          await context.sync();
        });
        status.textContent = `Connected to ${usage.org_name}. Added a worksheet.`;
      } catch (error) {
        status.textContent = error.name === "TimeoutError"
          ? "Unsiloed didn't respond within 15 seconds. Try again."
          : error.message;
      } finally {
        button.disabled = false;
      }
    });
  </script>
</body>
</html>
```

The button becomes available once Office.js connects to Excel. After the API
check succeeds, `Excel.run` queues a worksheet write and `context.sync()` applies
it. Adding a sheet leaves existing worksheets untouched. B1 uses Excel's text
format, and names beginning with a formula-like prefix also receive a leading
apostrophe to prevent Excel from interpreting them as formulas.

## Register the Add-in with Excel

Create `manifest.xml` in the same directory:

```xml manifest.xml theme={null}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:type="TaskPaneApp">
  <Id>4e796815-b704-4a27-87a0-8358602112e7</Id>
  <Version>1.0.0.0</Version>
  <ProviderName>Unsiloed AI</ProviderName>
  <DefaultLocale>en-US</DefaultLocale>
  <DisplayName DefaultValue="Unsiloed Connection" />
  <Description DefaultValue="Check the Unsiloed connection from Excel." />
  <IconUrl DefaultValue="https://www.unsiloed.ai/docs/logo/dark.png" />
  <SupportUrl DefaultValue="https://www.unsiloed.ai/docs" />
  <Hosts>
    <Host Name="Workbook" />
  </Hosts>
  <DefaultSettings>
    <SourceLocation DefaultValue="https://localhost:3000/index.html" />
  </DefaultSettings>
  <Permissions>ReadWriteDocument</Permissions>
</OfficeApp>
```

The manifest points to the local page and requests permission to create and write
worksheets. It contains no API credentials.

## Run and Verify the Connection

From `unsiloed-excel-connection`, run:

```bash theme={null}
npx vite
```

The certificate helper may ask for your macOS password to trust the localhost
certificate. Keep Terminal open, then visit:

```text theme={null}
https://localhost:3000/index.html
```

Confirm that the page opens without a certificate warning. Its message asks you
to open it as an Excel add-in because it isn't connected to a workbook yet.

**1. Open the Add-ins menu**

Open a blank workbook in Excel for the web. On the **Home** tab, click
the **Add-ins** button (1), a grid icon near the right of the ribbon.

![Excel for the web with a red numbered callout around the Add-ins button on the Home ribbon](https://mintcdn.com/unsiloed/FXw-Mm6LLqFCgEI3/images/excel/01-open-addins-clean.jpg?fit=max\&auto=format\&n=FXw-Mm6LLqFCgEI3\&q=85\&s=7a1b03ccf6b94a576794c75ba153e5d8)

In the panel that opens, click **More Add-ins** (2).

![The Excel Add-ins panel with a red numbered callout around More Add-ins](https://mintcdn.com/unsiloed/FXw-Mm6LLqFCgEI3/images/excel/02-more-addins-clean.jpg?fit=max\&auto=format\&n=FXw-Mm6LLqFCgEI3\&q=85\&s=cf1d117b61356cf2dfee8647f8159d77)

Some accounts show **More Settings** instead of **More Add-ins**, and the
next dialog shows **Upload My Add-in** directly. See the
[Microsoft sideloading guide](https://learn.microsoft.com/en-us/office/dev/add-ins/testing/sideload-office-add-ins-for-testing)
if the menu differs. If custom uploads are disabled, ask your administrator
or use a personal Microsoft account.

**2. Upload the manifest**

Open **Manage My Add-ins** and choose **Upload My Add-in** (3).
The banner shown below refers to add-ins installed by an administrator;
use the upload option for this local project.

![The Office Add-ins dialog with Manage My Add-ins expanded and a red numbered callout around Upload My Add-in](https://mintcdn.com/unsiloed/FXw-Mm6LLqFCgEI3/images/excel/03-upload-my-addin-clean.jpg?fit=max\&auto=format\&n=FXw-Mm6LLqFCgEI3\&q=85\&s=06c6ad666524e187f85dffa902e39c64)

Click **Browse** (4), select `unsiloed-excel-connection/manifest.xml`, and
click **Upload** (5).

![The Upload Add-in dialog with red numbered callouts around Browse and Upload](https://mintcdn.com/unsiloed/FXw-Mm6LLqFCgEI3/images/excel/04-choose-and-upload-manifest-clean.jpg?fit=max\&auto=format\&n=FXw-Mm6LLqFCgEI3\&q=85\&s=e88340dbe83be9fb6920bd670604226d)

**3. Check the connection**

The **Unsiloed Connection** pane should open beside the workbook. If Chrome
asks for local network access, click **Allow** so Excel can load localhost.
Enter your API key and click **Check connection**.

A new worksheet should show **Unsiloed organization** in A1 and your
organization name in B1. The task pane should also confirm the connection.
Each successful check creates a new sheet.

To reopen the pane later, choose **Home → Add-ins** and select **Unsiloed
Connection**. Excel for the web keeps uploaded manifests in browser storage, so
upload it again after clearing browser data or switching browsers.

If Excel can't load the pane, confirm that Vite is still running and that the
localhost page opens without a certificate warning. If you blocked Chrome's
local network access prompt, set **Local network access** to **Allow** in the
site settings for `excel.cloud.microsoft`, then reload the workbook.

If the task pane shows HTTP 401, re-enter your API key. For other HTTP errors,
check the Vite output in Terminal and try again. The key stays in the page's
memory and isn't saved to the workbook or browser storage.

## Add a Document-Processing Workflow

The connection is now ready for task-specific code. Use `/parse` to read a PDF or
image's existing tables, or `/v2/extract` to return fields defined by a JSON Schema.
These workflows submit a job and poll for its result before writing cells.

> [card] [Extract a Table from a Document](https://www.unsiloed.ai/docs/cookbooks/spreadsheets/excel-extract-table.md)
>
> Build a task pane that uploads a document, polls the parse job, and writes the first table to a worksheet.

> [card] [Extract Typed Fields](https://www.unsiloed.ai/docs/document-processing/extraction/extraction.md)
>
> Return a predictable set of fields for fixed spreadsheet columns.

For a distributed add-in, host the page and API proxy on HTTPS and update the
manifest URL. Vite's proxy runs only during development. Use per-user
authentication or a backend that keeps shared credentials out of browser code.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.