データ可視化アプリケーションにおいて、Excel ワークブック内のグラフや図形を独立した画像としてエクスポートすることは、データコンテンツのクロスプラットフォーム互換性を高めるための一般的な要件です。グラフや図形を PNG、JPG などの汎用フォーマットに変換することで、Web、モバイル、または非 Office 環境でも可視化コンテンツを正しく表示できるようになり、レポートやプレゼンテーションへの埋め込みも容易になります。
本記事では、Reactアプリケーションで Excel のグラフと図形を画像としてエクスポートするフロントエンド実装方法を紹介します。このソリューションは WebAssembly 技術に基づいており、バックエンドサービスを必要とせずにブラウザ上で直接 Excel ファイルを処理できます。
インストールと設定
まず、React プロジェクトに依存関係をインストールします:
npm i spire.office
インストール完了後、spire.xls.js と spire.xls.wasm ファイルをプロジェクトの public ディレクトリに配置する必要があります。これらのファイルは WebAssembly モジュールの中核コンポーネントであり、ブラウザ上での Excel ファイルの解析と処理を担当します。
React コンポーネントで動的インポートを使用して WebAssembly モジュールをロードします:
import React, { useState, useEffect } from 'react';
import JSZip from 'jszip';
function App() {
const [wasmModule, setWasmModule] = useState(null);
useEffect(() => {
(async () => {
try {
const publicUrl = process.env.PUBLIC_URL || '';
const spireModule = await import(/* webpackIgnore: true */ `${publicUrl}/spire.xls.js`);
const rawModule = spireModule.default || spireModule;
window.wasmModule = typeof rawModule === 'function'
? await rawModule({ locateFile: p => p.endsWith('.wasm') ? `${publicUrl}/${p}` : p })
: rawModule;
setWasmModule(window.wasmModule);
} catch (error) {
console.error('spire.xls.js WASMモジュールのロードに失敗しました:', error);
}
})();
}, []);
}
Excel のグラフを画像として保存
Workbook.SaveChartAsImage() メソッドを使用すると、ワークシート内の特定のグラフを画像ファイルとして保存できます。これらの画像は WebAssembly の仮想ファイルシステム(VFS)に保存され、後で ZIP にまとめてダウンロードすることができます。
主要な手順は以下の通りです:
-
FetchFileToVFS()を使用してフォントファイルと Excel ファイルを VFS にロード -
Workbookインスタンスを作成し、Excel ファイルをロード - ワークシートとグラフをループし、
SaveChartAsImage()で画像として保存 - VFS から画像ファイルを読み取り、ZIP にまとめてダウンロードをトリガー
const SaveExcelChartAsImage = async () => {
const wasmModule = window.wasmModule.spirexls;
if (wasmModule) {
// フォントを仮想ファイルシステム(VFS)にロード
await window.spire.FetchFileToVFS('Arial.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/static/font/`);
// Excel ファイルを仮想ファイルシステムにロード
const inputFileName = 'サンプル.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// VFS に画像フォルダを作成
const imageFolderName = `Images`;
window.dotnetRuntime.Module.FS.mkdirTree(imageFolderName);
// 新しいワークブックを作成
const workbook = new wasmModule.Workbook();
// 仮想ファイルシステムから Excel ファイルをロード
workbook.LoadFromFile(inputFileName);
// ワークブック内の各ワークシートをループ
for (let i = 0; i < workbook.Worksheets.Count; i++) {
const sheet = workbook.Worksheets.get(i);
for (let j = 0; j < sheet.Charts.Count; j++) {
let image = workbook.SaveChartAsImage({ worksheet: sheet, chartIndex: j });
let filePath = `${imageFolderName}/${sheet.Name}_Chart-${j}.png`;
image.Save(filePath);
}
}
// 画像フォルダを ZIP にまとめてダウンロード
// ...
}
};
Excel の図形を画像として保存
図形を処理するフローはグラフと似ていますが、Worksheet.PrstGeomShapes.get() を使用して図形オブジェクトを取得し、shape.SaveToImage() メソッドを呼び出す点が異なります。
const SaveExcelShapeAsImage = async () => {
const wasmModule = window.wasmModule.spirexls;
if (wasmModule) {
// フォントを仮想ファイルシステム(VFS)にロード
await window.spire.FetchFileToVFS('Arial.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/static/font/`);
// Excel ファイルを仮想ファイルシステムにロード
const inputFileName = 'Shape.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// VFS に画像フォルダを作成
const imageFolderName = `Images`;
window.dotnetRuntime.Module.FS.mkdirTree(imageFolderName);
// 新しいワークブックを作成
const workbook = new wasmModule.Workbook();
// 仮想ファイルシステムから Excel ファイルをロード
workbook.LoadFromFile(inputFileName);
// ワークブック内の各ワークシートをループ
for (let i = 0; i < workbook.Worksheets.Count; i++) {
const sheet = workbook.Worksheets.get(i);
for (let j = 0; j < sheet.PrstGeomShapes.Count; j++) {
const shape = sheet.PrstGeomShapes.get(j);
const image = shape.SaveToImage();
let filePath = `${imageFolderName}/${sheet.Name}_shape-${j}.png`;
image.Save(filePath);
}
}
// 画像フォルダを ZIP にまとめてダウンロード
// ...
}
};
ZIP にまとめてダウンロード
VFS からファイルを読み取り、ZIP にまとめてダウンロードする汎用ロジックは以下の通りです:
// ディレクトリとその内容を ZIP に追加する再帰関数
const addFilesToZip = (folderPath, zipFolder) => {
const items = window.dotnetRuntime.Module.FS.readdir(folderPath);
items.filter(item => item !== "." && item !== "..").forEach((item) => {
const itemPath = `${folderPath}/${item}`;
try {
const fileData = window.dotnetRuntime.Module.FS.readFile(itemPath);
zipFolder.file(item, fileData);
} catch (error) {
if (error.code === 'EISDIR') {
const zipSubFolder = zipFolder.folder(item);
addFilesToZip(itemPath, zipSubFolder);
} else {
console.error(`${itemPath} の処理中にエラーが発生しました:`, error);
}
}
});
};
// 画像フォルダを ZIP ファイルにまとめる
const zip = new JSZip();
addFilesToZip(imageFolderName, zip);
// ZIPファイルから Blob を生成し、ダウンロードをトリガー
zip.generateAsync({ type: "blob" })
.then(function(content) {
const link = document.createElement('a');
link.href = URL.createObjectURL(content);
link.download = 'images.zip';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
}).catch(function(err) {
console.error("ZIPファイルの生成中にエラーが発生しました:", err);
});
仮想ファイルシステムとリソース管理
仮想ファイルシステム(VFS) は、このソリューションの動作メカニズムにおける重要な要素です。Save() メソッドで生成されたファイルは、ユーザーの物理ディスクではなく、WebAssembly のメモリファイルシステムに保存されます。エクスポート時にはVFSからファイルデータを読み取り、ブラウザが認識可能な Blob オブジェクトに変換してからダウンロードをトリガーする必要があります。
FS.mkdirTree() メソッドはディレクトリを再帰的に作成するために使用され、FS.mkdir() と比較して、ネストされたパスを一度に作成できるため、複雑なパス構造を扱う際により便利です。
各 Workbook インスタンスは、操作完了後に Dispose() メソッドを明示的に呼び出してメモリリソースを解放することを推奨します。特に頻繁なエクスポートや大容量ファイルの処理シナリオでは、リソースを適時に解放することでブラウザのメモリ使用量の過剰な増加を防ぐことができます。
出力フォーマットの選択
このソリューションは、グラフや図形を PNG、JPG、BMP などの一般的な画像フォーマットで出力することをサポートしています。ベクターグラフィックスが必要な場合は、グラフやワークシートを SVG 形式に変換することも可能です。SVG 形式は Web 埋め込みシーンにおいて、任意の拡縮やテキスト選択が可能といった利点があり、PNG 形式は汎用互換性の面で優れています。開発者は実際のアプリケーションシーンに応じて適切な出力フォーマットを選択できます。
まとめ
React に WebAssembly ベースのExcel処理モジュールを統合することで、バックエンドサービスに依存せず、ブラウザ上で完全に Excel のグラフや図形を画像としてエクスポートすることが可能になります。このソリューションは仮想ファイルシステムを介して入出力ファイルを管理し、フロントエンドで直接 Excel の可視化コンテンツを処理する必要があるシーンに適しています。実際のプロジェクトでは、開発者は上記のサンプルコードをビジネス要件に合わせて適応・拡張することができます。