Skip to main content

超链接和工具提示

File Format Support (click to show)

Traditional spreadsheet software, including Excel, support "Cell Links". The entire cell text is clickable.

Modern spreadsheet software, including Numbers, support "Span Links". Links are applied to text fragments within the cell content. This mirrors HTML semantics.

FormatsLinkTooltipLink Type
XLSX / XLSMCell Link
XLSBCell Link
XLS (BIFF8)Cell Link
XLMLCell Link
ODS / FODS / UOSSpan Link
HTMLSpan Link
NUMBERSSpan Link

X (✕) marks features that are not supported by the file formats. For example, the NUMBERS file format does not support custom tooltips.

For "Span Link" formats, parsers apply the first hyperlink to the entire cell and writers apply the hyperlink to the entire cell text.

电子表格超链接是对其他位置的可点击引用。它们的作用与 HTML <a> 标记相同。

¥Spreadsheet hyperlinks are clickable references to other locations. They serve the same role as the HTML <a> tag.

电子表格应用可以处理 "internal"(单元格、范围和定义的名称)和 "external"(网站、电子邮件地址和本地文件)引用。

¥Spreadsheet applications can process "internal" (cells, ranges, and defined names) and "external" (websites, email addresses, and local files) references.

SheetJS 超链接对象存储在单元格对象的 l 键中。超链接对象包括以下字段:

¥SheetJS hyperlink objects are stored in the l key of cell objects. Hyperlink objects include the following fields:

  • Target(必填)描述参考。

    ¥Target (required) describes the reference.

  • Tooltip 是工具提示文本。将鼠标悬停在文本上时会显示工具提示。

    ¥Tooltip is the tooltip text. Tooltips are shown when hovering over the text.

例如,以下代码片段创建从单元格 A1https://sheetjs.com 的链接,并带有提示 "Find us @ SheetJS.com!"

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

/* create worksheet with cell A1 = "https://sheetjs.com" */
var ws = XLSX.utils.aoa_to_sheet([["https://sheetjs.com"]]);

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

Cell A1 is a hyperlink with a custom tooltip

按照传统软件,超链接应用于整个单元对象。某些格式(包括 HTML)将链接附加到文本范围。解析器将第一个链接应用于整个单元格。作者将链接应用于整个单元格文本。

¥Following traditional software, hyperlinks are applied to entire cell objects. Some formats (including HTML) attach links to text spans. The parsers apply the first link to the entire cell. Writers apply links to the entire cell text.

Excel 不会自动设置超链接的样式。它们将使用默认的单元格样式显示。

¥Excel does not automatically style hyperlinks. They will be displayed using the default cell style.

SheetJS Pro 基础版 包括对一般超链接样式的支持。

¥SheetJS Pro Basic includes support for general hyperlink styling.

¥External Hyperlinks

电子表格软件通常会启动其他程序来处理外部超链接。例如,单击 "网站链接" 将打开一个新的浏览器窗口。

¥Spreadsheet software will typically launch other programs to handle external hyperlinks. For example, clicking a "Web Link" will open a new browser window.

¥Web Links

可以直接使用 HTTP 和 HTTPS 链接:

¥HTTP and HTTPS links can be used directly:

ws["A2"].l = { Target: "https://xlsx.nodejs.cn/docs/csf/features/hyperlinks#web-links" };
ws["A3"].l = { Target: "http://localhost:7262/yes_localhost_works" };
Live Example (click to hide)
Result
Loading...
Live Editor
/* The live editor requires this function wrapper */
function ExportSimpleLink() { 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> ); }

¥Mail Links

Excel 还支持带有主题行的 mailto 电子邮件链接:

¥Excel also supports mailto email links with subject line:

ws["A4"].l = { Target: "mailto:ignored@dev.null" };
ws["A5"].l = { Target: "mailto:ignored@dev.null?subject=Test Subject" };
Live Example (click to show)

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

Result
Loading...
Live Editor
/* The live editor requires this function wrapper */
function ExportRemoteLink() {
  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>
  </> );
}

¥Local Links

绝对路径的链接应使用 file:// URI 方案:

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

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:

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

相对路径在 SpreadsheetML 2003 格式中具有未定义的行为。Excel 2019 会将 ..\ 父标记视为上两级。

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

¥Internal Hyperlinks

目标是同一工作簿 ("内部链接") 中的单元格或范围或定义名称的链接标有前导哈希字符:

¥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:

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 */
Live Example (click to show)

This demo creates a workbook with two worksheets. In the first worksheet:

  • Cell A1 ("Same") will link to the range B2:D4 in the first sheet
  • Cell B1 ("Cross") will link to the range B2:D4 in the second sheet
  • Cell C1 ("Name") will link to the range in the defined name SheetJSDN

The defined name SheetJSDN points to the range A1:B2 in the second sheet.

Result
Loading...
Live Editor
/* The live editor requires this function wrapper */
function ExportInternalLink() { 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> ); }

某些第三方工具(例如 Google Sheets)无法正确解析 XLSX 文档中的超链接。库版本 0.18.12 中添加了解决方法。

¥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.

工具提示

¥Tooltips

工具提示附加到超链接信息。如果不分配单元格链接,则无法指定工具提示。

¥Tooltips are attached to hyperlink information. There is no way to specify a tooltip without assigning a cell link.

Excel 的未记录工具提示长度限制为 255 个字符。

¥Excel has an undocumented tooltip length limit of 255 characters.

该库当前允许编写更长的工具提示,但生成的文件将无法在 Excel 中打开。

¥Writing longer tooltips is currently permitted by the library but the generated files will not open in Excel.

HTML

HTML DOM 解析器 [^1] 将处理表中的 <a> 链接。

¥The HTML DOM parser[^1] will process <a> links in the table.

Live Example (click to hide)

此示例使用 table_to_book 从 HTML 表生成 SheetJS 工作簿对象。第二行中的超链接将被解析为单元格级链接。

¥This example uses table_to_book to generate a SheetJS workbook object from a HTML table. The hyperlink in the second row will be parsed as a cell-level link.

Result
Loading...
Live Editor
/* The live editor requires this function wrapper */
function ExportHyperlink() {

  /* 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>
  </> );
}

HTML writer[^2] 将生成 <a> 链接。

¥The HTML writer[^2] will generate <a> links.

Live Example (click to hide)

此示例创建一个工作表,其中 A1 有链接,而 B1 没有。sheet_to_html 函数生成一个 HTML 表格,其中左上角的表格单元格具有标准 HTML 链接。

¥This example creates a worksheet where A1 has a link and B1 does not. The sheet_to_html function generates an HTML table where the topleft table cell has a standard HTML link.

Result
Loading...
Live Editor
/* The live editor requires this function wrapper */
function ExportALinks() {
  const [ __html, setHTML ] = React.useState("");
  React.useEffect(() => {
    /* 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!"
    };

    /* Generate HTML */
    setHTML(XLSX.utils.sheet_to_html(ws));
  }, []);

  return ( <div dangerouslySetInnerHTML={{__html}}/> );
}

杂项

¥Miscellany

Extract all links from a file (click to show)

The following example iterates through each worksheet and each cell to find all links. The table shows sheet name, cell address, and target for each link.

Result
Loading...
Live Editor
function SheetJSParseLinks() {
  const [rows, setRows] = React.useState([]);

  return ( <>
    <input type="file" onChange={async(e) => {
      let rows = [];
      /* parse workbook */
      const file = e.target.files[0];
      const data = await file.arrayBuffer();
      const wb = XLSX.read(data);

      const html = [];
      wb.SheetNames.forEach(n => {
        var ws = wb.Sheets[n]; if(!ws) return;
        var ref = XLSX.utils.decode_range(ws["!ref"]);
        for(var R = 0; R <= ref.e.r; ++R) for(var C = 0; C <= ref.e.c; ++C) {
          var addr = XLSX.utils.encode_cell({r:R,c:C});
          if(!ws[addr] || !ws[addr].l) continue;
          var link = ws[addr].l;
          rows.push({ws:n, addr, Target: link.Target});
        }
      });
      setRows(rows);
    }}/>
    <table><tr><th>Sheet</th><th>Address</th><th>Link Target</th></tr>
    {rows.map(r => (<tr><td>{r.ws}</td><td>{r.addr}</td><td>{r.Target}</td></tr>))}
    </table>
  </> );
}

[^1]: 主要的 SheetJS DOM 解析方法是 table_to_booktable_to_sheetsheet_add_dom

¥The primary SheetJS DOM parsing methods are table_to_book, table_to_sheet, and sheet_add_dom

[^2]: HTML 字符串可以使用 writewriteFile 方法中的 bookType: "html" 或使用 专用 sheet_to_html 实用功能 编写

¥HTML strings can be written using bookType: "html" in the write or writeFile methods or by using the dedicated sheet_to_html utility function