EatSheet.xlsx
npm
A1
=PREVIEW(file, in="react")

Preview an XLSX file in React

To preview an XLSX file in React, open it with EatSheet in an effect and put the returned HTML in a scrolling element. Parsing runs in a Web Worker, so the page keeps responding, and only the rows in view are rendered.

1. Install it

npm install eatsheet

2. Add the component

import { useEffect, useRef, useState } from 'react';
import { openWorkbook } from 'eatsheet/worker';
import 'eatsheet/eatsheet.css';

export function ExcelPreview({ file }) {
  const box = useRef(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    const element = box.current;
    let book, gone = false, frame = 0;
    setError(null);

    const draw = async () => {
      const { html } = await book.render(0, { offset: element.scrollTop });
      if (!gone) element.innerHTML = html; // EatSheet escapes cell content
    };
    const onScroll = () => {
      cancelAnimationFrame(frame);
      frame = requestAnimationFrame(() => draw().catch(setError));
    };

    openWorkbook(file).then(opened => {
      if (gone) return opened.close();
      book = opened;
      element.addEventListener('scroll', onScroll);
      return draw();
    }).catch(failure => { if (!gone) setError(failure); });

    return () => {
      gone = true;
      cancelAnimationFrame(frame);
      element.removeEventListener('scroll', onScroll);
      book?.close();
    };
  }, [file]);

  return (
    <>
      {error && <p role="alert">Couldn't open this file: {error.code ?? error.message}</p>}
      <div ref={box} tabIndex={0} hidden={!!error} style={{ height: 480, overflow: 'auto' }} />
    </>
  );
}

3. Use it with a file input

function App() {
  const [file, setFile] = useState(null);
  return (
    <>
      <input type="file" accept=".xlsx,.csv,.tsv" onChange={e => setFile(e.target.files[0])} />
      {file && <ExcelPreview file={file} />}
    </>
  );
}

Good to know

Other sources. file can also be a URL, Blob, Response or ArrayBuffer. A URL on another host must allow CORS.
Other sheets. Use book.sheets to build tabs, and pass the index to book.render().
Clean up. The effect closes the workbook when the file changes or the component unmounts, which ends its worker.