1. はじめに
プロジェクトを進める中で、ユーザーが画面上で確認したデータをExcelとしてダウンロードする機能を開発することになりました。単にデータを書き出すのではなく、ユーザーが画面上で見ている形式とできるだけ同じ結果をExcelでも提供することこれが要件でした。
たとえば、ステータス値に応じて文字色が変わったり、特定の行が強調表示されたり、ヘッダーに個別の背景色が適用されたりする場合など、ブラウザ上の視覚的な要素もExcelで維持する必要がありました。
最初は、ag-Gridが提供するexportDataAsExcel()メソッドを呼び出すだけで、画面と同じ結果が生成されると思っていました。しかし実際には、ブラウザのレンダリング方式とExcel Exportの動作方式が異なるため、スタイルが維持されませんでした。この問題を解決するために経験した試行錯誤と解決プロセスを共有したいと思います。本記事はag-Grid v28.0.2環境を基準に作成しており、バージョンによって一部の動作やサポート機能が異なる場合があります。
2. 画面とExcelのデータが異なっていた理由:`valueFormatter`が適用されない
【問題の状況】
一部のカラムでは、DBから取得した元の値ではなく、ユーザーの可読性を高めるために`valueFormatter`を使用して変換したテキストを画面に表示していました。
この状態でExcel出力を実行すると、画面では「承認」と表示されているデータが、Excelファイル内では元のデータである「Y」として出力される現象が発生しました。
【解決方法】
ag-GridのExcel Exportオプションの一つである`processCellCallback`を利用し、Excelファイルにセルの値を書き込む前に、valueFormatterが適用された最終的なテキストを返すよう値を加工するコールバックロジックを追加しました。
この処理により、内部データのキー値ではなく、ユーザーが画面上で見る直感的なテキストのままExcelに保存できました。
3. CSSがExcelにそのまま適用されない理由
【問題の状況】
ブラウザ上で特定の条件を満たした際にセルの文字色を赤に変更するため、以下のように`cellClass`設定を使用しました。
画面ではCSSスクリプト(`.text-red { color: red; }`)によって正常に動作しましたが、ダウンロードしたExcelファイルではスタイルがまったく適用されませんでした。
【原因分析】
ag-GridのExcel Exportエンジンは、ブラウザでレンダリングされたCSSのホスト環境を読み取ることができません。その代わりに、Excel固有のXMLスタイル形式に変換する内部オブジェクトである`excelStyles`配列を参照してスタイルを構築する仕組みになっていました。
つまり、画面で使用しているCSSだけではExcelのスタイルは自動的に反映されませんでした。この問題を解決するため、excelStylesとセルクラスのマッピング方式を適用しました。その過程については次のセクションで説明します。
4. excelStylesとcellClass、cellClassRulesの連携構造
【解決方法】
問題を解決するため、Grid内で共通して使用する`excelStyles`設定を宣言しました。重要なのは、CSSクラス名と`excelStyles`のidを1:1でマッピングすることです。
【分かったこと】
バージョン28.0.2では、`cellClass`関数によって返されたクラス名であっても、`cellClassRules`によって条件を満たして有効化されたクラス名であっても、最終的にセルに付与されたクラス文字列がexcelStylesのidと一致すれば、Excelエンジンがこれを自動的に認識します。そのおかげで、フォントの色や太さなどの属性が正常にエンコードされ、画面のCSS構造とExcelのスタイル構造を一貫性を保って組み合わせることができました。
5. Headerスタイルの適用過程と特別な固有ID(header)
【問題の状況】
ヘッダー(Header)領域のスタイリングでも、予想していなかった問題に直面しました。最初は、先ほど成功した一般的なCell方式と同じように、カスタムスタイルIDを定義してマッピングすればよいと考えていました。
画面のCSSは正常に動作しましたが、Excelをダウンロードしてみると、ヘッダーにはスタイルがまったく適用されていませんでした。最初は単純なタイプミスや設定ミスだと思い、何度もコードを確認してテストを繰り返しましたが、結果は同じでした。
【原因分析と解決】
公式ドキュメントで、ag-GridのExcel Exportエンジンではヘッダー領域が非常に特殊な方法で処理されることを知りました。ヘッダーは開発者が任意に指定したカスタムID(`blue-header`)を認識せず、ag-Gridが内部的に予約している固有IDである`header`という名称を強制的に構造化して使用していました。
そのため、excelStyles設定を任意のIDではなく、公式仕様に合わせて以下のように修正しました。
【分かったこと】
修正後、ヘッダーのスタイルがExcelファイルに正常に反映されることを確認できました。この過程を通じて、一般的なCell領域とHeader領域では、内部のパースエンジン自体がまったく異なるメカニズムで動作することを理解しました。ヘッダースタイルを制御する際は、任意のクラスバインディングよりも、フレームワークが指定する組み込みルール(`id: "header"`)に従うことが重要でした。
ただし、上記の内容はag-Grid v28.0.2を基準としており、v29以降ではExcel Exportの内部エンジン構造が一部変更されている可能性があるため、公式ドキュメントも併せて確認することをおすすめします。
6. まとめ
今回の経験を通じて、単に機能を実装するだけでなく、ライブラリの動作方式を理解し、プロジェクトの状況に合った解決策を選択するプロセスの重要性を改めて実感しました。
出典および参考資料
* ag-Grid公式ドキュメント – Excel Export:https://www.ag-grid.com/react-data-grid/excel-export/
* ag-Grid公式ドキュメント – Excel Export Styles:https://www.ag-grid.com/react-data-grid/excel-export-styles/
* ag-Grid公式ドキュメント – Cell Styles(`cellClass`、`cellClassRules`):https://www.ag-grid.com/react-data-grid/cell-styles/
JJ