ReoGrid ReoGrid Web

ブラウザでXLSXをJSONに変換 — サーバー不要・アップロード不要

· unvell team
ブラウザでXLSXをJSONに変換 — サーバー不要・アップロード不要

「XLSXをJSONに変換」というと、たいていファイルをバックエンドに送り、ライブラリで解析し、データを返してもらう、という流れになります。この往復は遅く、機密のスプレッドシートを他人のサーバーに置くことになります。

もっと良い方法があります。ブラウザの中で変換するのです。ReoGrid は .xlsx をクライアントで読み込むので、バイト列はユーザーの端末から出ません。しかも編集可能なグリッドに描画もするので、スプレッドシートを見せつつ、同じコンポーネントから JSON を返せます。

この記事では、実際に欲しくなる2種類の「JSON」と、それぞれの使い分けを扱います。


2種類のJSON

コードを書く前に、ユースケースにとって「JSON」が何を意味するかを決めましょう。

ReoGrid JSON(ロスレス)データ行(素)
{ format, version, workbook, styles, … }[{ Product: 'Widget', Price: '9.99' }, …]
保持スタイル・数式・結合・セルタイプ値のみ
用途保存/復元・バージョン管理・再描画API・DB・AI・分析

あとでファイルをそのまま開き直したいなら ReoGrid JSON。データを別の何かに渡したいならデータ行。両方やってみます。


準備

xlsx の読み込みは無料の Lite でも Pro でも可能ですが、Lite は 100 行 × 26 列を超えるファイルを切り詰めます。実務ファイルの変換には Pro を使ってください。

import { createReogrid } from '@reogrid/pro';

const grid = createReogrid('#grid', { licenseKey: 'YOUR-LICENSE-KEY' });
<input type="file" accept=".xlsx" id="file" />
<div id="grid" style="width: 100%; height: 420px;"></div>

種類1 — ロスレスな ReoGrid JSON

ファイルを読み込み、toJson() を呼ぶだけ。これが変換のすべてです。

const input = document.querySelector<HTMLInputElement>('#file')!;

input.addEventListener('change', async (e) => {
  const file = (e.target as HTMLInputElement).files?.[0];
  if (!file) return;

  await grid.loadFromFile(file);   // .xlsx を解析・描画
  const doc = grid.toJson();       // ワークブック全体 → ReoGrid JSON

  console.log(JSON.stringify(doc, null, 2));
});

grid.toJson()全シートとアクティブシート番号をシリアライズします。結果は ReoGrid JSON ドキュメント — ロスレスなので、xlsx が往復できるものに加えて ReoGrid 固有機能(カスタムセルタイプ、全条件付き書式ルール)も往復します。grid.loadJson(doc) でいつでも復元できます。

ワークブック全体ではなくアクティブシートだけを変換するには:

import { stringifyReoGridJson } from '@reogrid/pro';

await grid.loadFromFile(file);
const json = stringifyReoGridJson(grid.worksheet, { pretty: true });

結果をダウンロード

function downloadJson(doc: unknown, filename: string) {
  const blob = new Blob([JSON.stringify(doc, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = Object.assign(document.createElement('a'), { href: url, download: filename });
  a.click();
  URL.revokeObjectURL(url);
}

await grid.loadFromFile(file);
downloadJson(grid.toJson(), file.name.replace(/\.xlsx$/i, '.json'));

種類2 — 素のデータ行

ほとんどのアプリ連携では、スタイルや数式ソースは要らず、がヘッダー行をキーにしたオブジェクトの配列で欲しいはずです。読み込み後にグリッドから読み取ります。

import type { ReogridInstance } from '@reogrid/pro';

function sheetToRows(grid: ReogridInstance): Record<string, string>[] {
  const ws = grid.worksheet;

  // スパースなセルスナップショットから使用範囲を求める。
  const snapshot = ws.getExportSnapshot();
  let lastRow = 0, lastCol = 0;
  for (const cell of snapshot.cells) {
    lastRow = Math.max(lastRow, cell.row);
    lastCol = Math.max(lastCol, cell.column);
  }

  // ヘッダー行 → キー。getDisplayText は*描画後*の値を返す。
  const headers: string[] = [];
  for (let c = 0; c <= lastCol; c++) {
    headers[c] = (ws.getDisplayText(0, c) || `col${c}`).trim();
  }

  // データ行 → オブジェクト。
  const rows: Record<string, string>[] = [];
  for (let r = 1; r <= lastRow; r++) {
    const row: Record<string, string> = {};
    for (let c = 0; c <= lastCol; c++) row[headers[c]] = ws.getDisplayText(r, c) ?? '';
    rows.push(row);
  }
  return rows;
}
await grid.loadFromFile(file);
const rows = sheetToRows(grid);
// [{ Product: 'Widget', Price: '9.99', Qty: '40' }, …]

肝は getDisplayTextcell.value ではなく)です。getDisplayText は数式が評価され数値書式が適用された描画後の値("$9.99", "1,200")を返します。cell.value は生の入力 — 数式セルではソース文字列("=B2*1.1")であり、計算結果ではありません。


なぜクライアント側が勝つのか

  • プライバシー。 ファイルはブラウザの File API で読まれ、キャンバス上で解析されます。アップロードはなし — 財務・人事・その他機密のスプレッドシートにも安全です(これはまさに無料オンライン XLSX ビューアの仕組みです)。
  • バックエンド不要。 アップロード用エンドポイントも、解析サービスも、一時ファイルの後始末も不要。静的ホスティングで十分。
  • 即時かつ可視。 変換しながらスプレッドシートが描画されるので、ユーザーは正しいファイルを選んだか確認できます。

次に進むなら

ReoGrid Web を試してみる

React/Vue 向けの Canvas ベース Excel 互換スプレッドシートコンポーネント。 Lite は無料 — npm install 一発で始められます。

関連記事

ニュースレター

開発の最新情報をお届けします

新しいリリース・機能追加・お知らせをいち早く受け取るには、
メーリングリストにご登録ください。