Add Hyperlinks to Pictures in Excel with JavaScript in React

A picture in Excel is more than decoration. Put a logo or a product shot on a worksheet and give it a hyperlink, and the file stops being a plain description and becomes something a reader can click through. A picture is not a cell, though, and its hyperlink lives on the picture object, so both setting and reading one go through the worksheet's picture collection rather than its cell hyperlink collection. Spire.XLS for JavaScript does this in the browser on WebAssembly, handling input and output files through a virtual file system (VFS) with no backend service.

This article covers two core feature points:

For installation and project setup, see Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module has been initialised.


Set a hyperlink on a picture

Setting a hyperlink on a picture is what turns it into a clickable entry point: a reader who clicks the picture on the worksheet opens the address it points at. The link belongs to the picture itself rather than to a cell, so the picture object has to be taken from the worksheet's picture collection first, and the address handed to that object. The steps are:

  1. Load the font, the picture and the test data file into the VFS.
  2. Load the workbook with workbook.LoadFromFile.
  3. Insert the picture into the space left for it with sheet.Pictures.Add.
  4. Set the hyperlink on the picture with picture.SetHyperLink, passing true as the second argument.
  5. Save the workbook with workbook.SaveToFile.
  6. Dispose of the workbook with workbook.Dispose to free resources.

The complete code example below shows how to set a hyperlink on a picture in Excel in React:

function App() {
  const pictureHyperlink = async () => {
    // get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // check that the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // load the font, the picture and the test data file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    await window.spire.FetchFileToVFS('logo.png', '', `${process.env.PUBLIC_URL}data/`);
    const inputFileName = 'PictureLink.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // load the workbook
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });

    // take the first worksheet and drop the picture into the space left for it
    const sheet = workbook.Worksheets.get(0);
    const picture = sheet.Pictures.Add({ topRow: 10, leftColumn: 1, fileName: 'logo.png' });

    // set the hyperlink on the picture; the second argument being true means it points outside the workbook
    picture.SetHyperLink('https://www.e-iceblue.com/Misc/about-us.html', true);

    // save the workbook
    const outputFileName = 'PictureHyperlink.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, fileFormat: xlsModule.FileFormat.Version2010 });

    // dispose of the workbook to free resources
    workbook.Dispose();

    // read the result file from the VFS and start the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Add Hyperlinks to Pictures in Excel</h1>
      <button id="picture-hyperlink" onClick={pictureHyperlink}>Set a hyperlink on the picture</button>
    </div>
  );
}

export default App;

After running, the effect of setting a hyperlink on a picture:

Set a hyperlink on a picture in Excel


Read the hyperlink from a picture

Reading the hyperlink off a picture is how a finished workbook is checked over: whether the links are all there, and whether they point at the right addresses. The addresses that come back are written out as a text file, which makes them easy to line up against a list of links. Picture hyperlinks are not kept in the cell hyperlink collection, so the pictures have to be taken from the worksheet one by one, and each one asked for its own link object. The steps are:

  1. Load the font and the test data file into the VFS.
  2. Load the workbook with workbook.LoadFromFile.
  3. Take the picture count from sheet.Pictures.Count and walk every picture on the worksheet with it.
  4. Take this picture's hyperlink object with picture.GetHyperLink.
  5. Read the target address from the link object's Address, collecting the addresses as you go.
  6. Write the collected addresses into a text file with FS.writeFile, one address per line.
  7. Dispose of the workbook with workbook.Dispose to free resources.

The complete code example below shows how to read the hyperlink from a picture in Excel in React:

function App() {
  const readPictureHyperlink = async () => {
    // get the Spire.XLS WASM module
    const xlsModule = window.wasmModule?.spirexls;

    // check that the module is ready
    if (!xlsModule) {
      alert('Spire.Xls is not ready yet');
      return;
    }

    // load the font and the test data file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'PictureHyperlinks.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // load the workbook
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });

    // walk the pictures of the worksheet and read the hyperlink off each one
    const sheet = workbook.Worksheets.get(0);
    const pictures = sheet.Pictures;
    const addresses = [];
    for (let i = 0; i < pictures.Count; i++) {
      const link = pictures.get(i).GetHyperLink();
      addresses.push(link.Address);
    }

    // write the addresses that were read into a text file
    const outputFileName = 'ReadPictureHyperlink.txt';
    window.dotnetRuntime.Module.FS.writeFile(outputFileName, addresses.join('\n'));

    // dispose of the workbook to free resources
    workbook.Dispose();

    // read the result file from the VFS and start the download
    const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
    const blob = new Blob([fileArray], { type: 'text/plain' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = outputFileName;
    a.click();
    URL.revokeObjectURL(url);
  };

  return (
    <div style={{ textAlign: 'center', height: '300px' }}>
      <h1>Add Hyperlinks to Pictures in Excel</h1>
      <button id="read-picture-hyperlink" onClick={readPictureHyperlink}>Read the hyperlink from the picture</button>
    </div>
  );
}

export default App;

After running, the effect of reading the hyperlink from a picture:

Read the hyperlink from a picture in Excel


FAQ

Why does a picture's hyperlink not show up in sheet.HyperLinks?

Cause: sheet.HyperLinks collects cell hyperlinks only. A picture is not a cell; it belongs to the worksheet's picture collection, and the link hangs on the picture object itself.

Solution: Go through the picture collection. In this example, after a hyperlink was set on the picture, sheet.HyperLinks.Count was still 0, and it was still 0 after the file was saved and opened again. Read a picture's link with sheet.Pictures.get(i).GetHyperLink(), then read the Address off the link object.

When should the second argument of SetHyperLink be false?

Cause: The second argument of picture.SetHyperLink(address, isExternal) says whether the target lies outside the workbook.

Solution: Pass true for a web page or an external file, and the link type comes out as HyperLinkType.Url; pass false for a position inside the same workbook, write the address as a cell reference such as Sheet1!A1, and the type comes out as HyperLinkType.Workbook. In this example both forms were saved, and after the file was opened again the Address and Type read back matched what had been set.

Get a Free License

Spire.XLS for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.