---
sidebar_position: 2
---

# Hyperlinks

<details>
  <summary><b>Format Support</b> (click to show)</summary>

**Cell Hyperlinks**: XLSX/M, XLSB, BIFF8 XLS, XLML, ODS, HTML

**Tooltips**: XLSX/M, XLSB, BIFF8 XLS, XLML

</details>

Hyperlinks are stored in the `l` key of cell objects.  The `Target` field of the
hyperlink object is the target of the link, including the URI fragment. Tooltips
are stored in the `Tooltip` field and are displayed when hovering over the text.

For example, the following snippet creates a link from cell `A3` to
<https://sheetjs.com> with the tip `"Find us @ SheetJS.com!"`:

```js
ws["A1"].l = { Target: "https://sheetjs.com", Tooltip: "Find us @ SheetJS.com!" };
```

:::note

Excel does not automatically style hyperlinks.  They will be displayed using
the default cell style. <a href="https://sheetjs.com/pro">SheetJS Pro Basic</a>
extends this export with support for hyperlink styling.

:::

<details open><summary><b>Live Example</b> (click to hide)</summary>

```jsx live
/* The live editor requires this function wrapper */
function ExportSimpleLink(props) { return ( <button onClick={() => {
  /* Create worksheet */
  var ws = XLSX.utils.aoa_to_sheet([ [ "Link", "No Link" ] ]);
  /* Add link */
  ws["A1"].l = {
    Target: "https://sheetjs.com",
    Tooltip: "Find us @ SheetJS.com!"
  };

  /* Export to file (start a download) */
  var wb = XLSX.utils.book_new();
  XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
  XLSX.writeFile(wb, "SheetJSSimpleLink.xlsx");
}}><b>Export XLSX!</b></button> ); }
```

</details>

## Remote Links

HTTP / HTTPS links can be used directly:

```js
ws["A2"].l = { Target: "https://docs.sheetjs.com/docs/csf/features/hyperlinks" };
ws["A3"].l = { Target: "http://localhost:7262/yes_localhost_works" };
```

Excel also supports `mailto` email links with subject line:

```js
ws["A4"].l = { Target: "mailto:ignored@dev.null" };
ws["A5"].l = { Target: "mailto:ignored@dev.null?subject=Test Subject" };
```

<details><summary><b>Live Example</b> (click to show)</summary>

**This demo creates a XLSX spreadsheet with a `mailto` email link. The email
address input in the form never leaves your machine.**

```jsx live
/* The live editor requires this function wrapper */
function ExportRemoteLink(props) {
  const [email, setEmail] = React.useState("ignored@dev.null");
  const set_email = React.useCallback((evt) => setEmail(evt.target.value));

  /* Callback invoked when the button is clicked */
  const xport = React.useCallback(() => {
    /* Create worksheet */
    var ws = XLSX.utils.aoa_to_sheet([ [ "HTTPS", "mailto" ] ]);
    /* Add links */
    ws["A1"].l = { Target: "https://sheetjs.com" };
    ws["B1"].l = { Target: `mailto:${email}` };

    /* Export to file (start a download) */
    var wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
    XLSX.writeFile(wb, "SheetJSRemoteLink.xlsx");
  });

  return (<>
    <b>Email: </b><input type="text" value={email} onChange={set_email} size="50"/>
    <br/><button onClick={xport}><b>Export XLSX!</b></button>
  </>);
}
```

</details>

## Local Links

Links to absolute paths should use the `file://` URI scheme:

```js
ws["B1"].l = { Target: "file:///SheetJS/t.xlsx" }; /* Link to /SheetJS/t.xlsx */
ws["B2"].l = { Target: "file:///c:/SheetJS.xlsx" }; /* Link to c:\SheetJS.xlsx */
```

Links to relative paths can be specified without a scheme:

```js
ws["B3"].l = { Target: "SheetJS.xlsb" }; /* Link to SheetJS.xlsb */
ws["B4"].l = { Target: "../SheetJS.xlsm" }; /* Link to ../SheetJS.xlsm */
```

:::caution

Relative Paths have undefined behavior in the SpreadsheetML 2003 format.  Excel
2019 will treat a `..\` parent mark as two levels up.

:::

## Internal Links

Links where the target is a cell or range or defined name in the same workbook
("Internal Links") are marked with a leading hash character:

```js
ws["C1"].l = { Target: "#E2" }; /* Link to cell E2 */
ws["C2"].l = { Target: "#Sheet2!E2" }; /* Link to cell E2 in sheet Sheet2 */
ws["C3"].l = { Target: "#SheetJSDName" }; /* Link to Defined Name */
```

<details><summary><b>Live Example</b> (click to show)</summary>

```jsx live
/* The live editor requires this function wrapper */
function ExportInternalLink(props) { return ( <button onClick={() => {
  /* Create empty workbook */
  var wb = XLSX.utils.book_new();

  /* Create worksheet */
  var ws = XLSX.utils.aoa_to_sheet([ [ "Same", "Cross", "Name" ] ]);
  XLSX.utils.book_append_sheet(wb, ws, "Sheet1");

  /* Create links */
  ws["A1"].l = { Target: "#B2:D4", Tooltip: "Same-Sheet" };
  ws["B1"].l = { Target: "#Sheet2!B2:D4", Tooltip: "Cross-Sheet" };
  ws["C1"].l = { Target: "#SheetJSDN", Tooltip: "Defined Name" };

  /* Create stub Sheet2 */
  var ws2 = XLSX.utils.aoa_to_sheet([["This is Sheet2"]]);
  XLSX.utils.book_append_sheet(wb, ws2, "Sheet2");

  /* Create defined name */
  wb.Workbook = {
    Names: [{Name: "SheetJSDN", Ref:"Sheet2!A1:B2"}]
  }

  /* Export to file (start a download) */
  XLSX.writeFile(wb, "SheetJSInternalLink.xlsx");
}}><b>Export XLSX!</b></button> ); }
```

</details>

:::caution

Some third-party tools like Google Sheets do not correctly parse hyperlinks in
XLSX documents.  A workaround was added in library version 0.18.12.

:::

## HTML

The HTML DOM parser will process `<a>` links in the table:

<details open><summary><b>Live Example</b> (click to hide)</summary>

```jsx live
/* The live editor requires this function wrapper */
function ExportHyperlink(props) {

  /* Callback invoked when the button is clicked */
  const xport = React.useCallback(() => {
    /* Create worksheet from HTML DOM TABLE */
    const table = document.getElementById("TableLink");
    const wb = XLSX.utils.table_to_book(table);

    /* Export to file (start a download) */
    XLSX.writeFile(wb, "SheetJSHTMLHyperlink.xlsx");
  });

  return (<>
    <button onClick={xport}><b>Export XLSX!</b></button>
    <table id="TableLink"><tbody><tr><td>
      Do not click here, for it is link-less.
    </td></tr><tr><td>
      <a href="https://sheetjs.com">Click here for more info</a>
    </td></tr></tbody></table>
  </>);
}
```

</details>