ReactアプリでのExcel連携 — SheetJSでインポート／エクスポートを簡単実装

Web アプリが扱うデータ量は年々増え続けています。その中でも Excel ファイル は昔から変わらず「データ受け渡しの共通フォーマット」として親しまれています。本記事では、React で SheetJS (xlsx) を使い、Excel の インポート／エクスポート 機能を実装する方法をまとめました。

## 1. Excel 連携が求められるシーン

- データ移行：異なるシステム間でデータを簡単に受け渡し
- チームコラボレーション：Excel で一括編集 → アプリへ取り込み
- データ分析：“慣れた Excel” で集計し、結果を再アップロード

Excel を介することで、非エンジニア も参加しやすいワークフローを構築できます。

## 2. SheetJS とは？

- ブラウザ／Node.js 対応 のスプレッドシート操作ライブラリ
- xlsx, csv, ods など複数フォーマットをサポート
- 依存関係が少なく軽量

### インストール
```
npm install xlsx
```

```
import * as XLSX from 'xlsx';
```

これだけで、Excel ファイルの読み書きが可能になります。

## 3. 基本 API 一覧

### 3.1 `XLSX.read()` — 読み込み

```
const workbook = XLSX.read(fileBinary, { type: 'binary' });
```

- **fileBinary**: `FileReader` などで取得したバイナリ文字列
- **workbook**: シート情報をまとめたオブジェクト

### 3.2 `XLSX.utils.sheet_to_json()` — シート ⇒ JSON

```
const ws = workbook.Sheets['Sheet1'];
const data = XLSX.utils.sheet_to_json(ws, { header: 1 });
```

- { header: 1 } で 1 行目をヘッダーとして扱う
- 配列 or オブジェクト 形式で取得できる

### 3.3 `XLSX.utils.aoa_to_sheet()` — 配列 ⇒ シート

```
const aoa = [
  ['Name', 'Age', 'Country'],
  ['John Doe', 25, 'Indonesia'],
];
const ws = XLSX.utils.aoa_to_sheet(aoa);
```

- AoA（Array of Arrays）をワークシート形式に変換

### 3.4 `XLSX.write()` — 書き込み

```
const buffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
const blob = new Blob([buffer], {
  type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8',
});
FileSaver.saveAs(blob, 'sample.xlsx');
```

- FileSaver でダウンロードリンクを生成・保存
- bookType を変更すれば csv などにも対応

## 4. 実践：カスタムフック useXLSX

以下のフックは、配列形式（AoA） または JSON 形式 のデータを簡単にエクスポート／インポートできます。

```
// useXLSX.ts
import * as XLSX from 'xlsx';
import * as FileSaver from 'file-saver';

type DataKind = 'array' | 'object';

function useXLSX() {
  /** Excel へ書き出し */
  const exportAoAXLSX = (
    data: any,
    kind: DataKind,
    fileName = 'export',
    sheetName = 'Sheet1',
    wscols?: XLSX.ColInfo[],
  ) => {
    const ws =
      kind === 'array'
        ? XLSX.utils.aoa_to_sheet(data)
        : XLSX.utils.json_to_sheet(data);

    if (wscols) {
      ws['!cols'] = wscols;
      ws['!cols'][0] = { hidden: true }; // 1 列目を非表示にする例
    }

    const wb = { Sheets: { [sheetName]: ws }, SheetNames: [sheetName] };
    const buffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
    const blob = new Blob([buffer], {
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8',
    });
    FileSaver.saveAs(blob, `${fileName}.xlsx`);
  };

  /** Excel から読み込み */
  const importXLSX = (file: File, callback?: (data: any[]) => void) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const wb = XLSX.read(e.target?.result, { type: 'binary' });
      const ws = wb.Sheets[wb.SheetNames[0]];
      const rows = XLSX.utils.sheet_to_json(ws, { header: 1 });
      callback?.(rows);
    };
    reader.readAsBinaryString(file);
  };

  return { exportAoAXLSX, importXLSX };
}

export default useXLSX;
```

## 5. コンポーネント側での利用例

```
import useXLSX from './useXLSX';

function App() {
  const { importXLSX } = useXLSX();

  const handleUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    importXLSX(file, (rows) => {
      console.log('読み込んだデータ', rows);
    });
  };

  return (
    <div>
      <input type="file" accept=".xlsx" onChange={handleUpload} />
    </div>
  );
}
```

1. ファイル選択 → `importXLSX` が実行
2. 解析済みデータ (rows) を `console.log` で確認
3. 必要に応じて state 更新 や API 送信 へ応用可能

エクスポートは `exportAoAXLSX(data, 'array')` を呼ぶだけで OK です。

## 6. まとめ

- SheetJS はブラウザだけで Excel 読み書きが可能
- 基本 API（read, sheet_to_json, aoa_to_sheet, write）を押さえれば十分実用的
- カスタムフック化すると 再利用性 が高まり、コンポーネントがスッキリ
- データ移行・チーム連携・高度な分析など、Excel 連携はビジネス現場で大きな価値を持つ

React × SheetJS で、エンドユーザーにも開発者にも優しいデータ操作機能を実装してみてください！

## 参考リンク
[SheetJS (xlsx) GitHub](https://github.com/SheetJS/sheetjs)
[FileSaver.js](https://github.com/eligrey/FileSaver.js)