66
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AG-gridを使用してウェブでExcelを使おう!

Last updated at Posted at 2025-12-19

初めに

このポストを見ている皆さんは、AG-gridのことをお分かりですか?
ウェブで高性能のデータテーブルが使用可能ンオープンソースライブラリーです。

React,Angular,Vue,Javascriptなどいろんなフレームワークと交換できており、
無料バージョンとエンタープライズバージョンがあります。

今日はこのAG-gridをウェブ上でExcelライクに使用できる機能を使ってみようと思います。
*今回のポストでは無料バージョンを基準にご紹介します。

まずは設置から

AG-grid公式サイト

メニューのDocs->QuickStartに入ります。
https://ag-grid.com/react-data-grid/getting-started/

npm install ag-grid-react

これでAG-gridのパッケージを設置します。

import { AgGridReact } from 'ag-grid-react'; // Reactコンポーネント
import { ModuleRegistry, AllCommunityModule, themeQuartz } from 'ag-grid-community'; // themeQuartz 추가
import { useState } from 'react'; 

ModuleRegistry.registerModules([ AllCommunityModule ]);

function App() {
  // カラム定義(ヘッダー設定)
  const [colDefs] = useState([
    { field: "No", width: 80 , headerName: "順番"},
    { field: "Product", headerName: "種類" , editable:true},
    { field: "price", headerName: "値段", editable:true },
  ]);

  // データ
  const [rowData] = useState([
    { No : 1, Product: "グミ", price: 600 },
    { No : 2, Product: "チョコ", price: 600 },
    { No : 3, Product: "プリン", price: 600 },
    { No : 4, Product: "ケーキ", price: 600 },
    { No : 5, Product: "アイス", price: 600 },
  ]);

  return (
    <div style={{ padding: '30px' }}>
      <h1>スイーツメニュー</h1>  
      <div style={{ height: 260, width: 490 }}>
        <AgGridReact
          rowData={rowData}
          columnDefs={colDefs}
          theme={themeQuartz} 
        />
      </div>
    </div>
  );
}

export default App;

設置する前にDemoから使用感を確認、
ThemeBuilderからはいろんなオプションを設定できます。
API文書も要チェック!

AG-gridダウンロードしました

image.png

選択したテーマやオプションによって見た目は変わりませんが、
このようなテーブルを見れます。

モダンなスタイルでフィルター、ソートなどを使える便利なテーブルですが、
まだExcelライクというには足りないですね。

どの機能が使えるの?

じゃあ、いろんなオプションを入れてカスタムしてみましょう!

といったところですが、
実は基本機能だけでも結構EXCELと似てるものがあります。

列の固定

固定したいカラムのcolDefsに、pinned: 'left'または'right'を利用してEXCELみたいに列を左または右に固定できます。

 const [colDefs] = useState([
    { field: "No", width: 80 , headerName: "順番"},
    { field: "Product", headerName: "種類" ,pinned:'left'},
    { field: "price", headerName: "値段"},
  ]);

image.png

### セルの編集
編集したいカラムのcolDefsに、editable: trueを追加して、編集可能なセルに設定できます。

const [colDefs] = useState([
    { field: "No", width: 80 , headerName: "順番"},
    { field: "Product", headerName: "種類" , editable:true,pinned:'left'},
    { field: "price", headerName: "値段", editable:true },
  ]);

image.png
*編集する際には該当セルをダブルクリック!

方向キーでセルの移動,エンターキーで入力セル選択

照会状態でキーボードで上下左右のセルを移動、
エンターキーでそのセルを編集できます。

列幅調整(リサイズ)

列の境界にカーソルを置くと、
その列の幅をリサイズできるようになります。

行高さ自動調整

wrapText={true}
autoHeight={true}

上記のオプションを組み合わせると、長いテキストがある際にEXCELの「折り返して全体を表示する」のように行の高さが児童に伸びます。

整列

ヘッダークリックで複数県の整列(Shift + クリック)が可能です。

フィルター

テキスト・数字・日にち専用フィルターでEXCELのフィルタリング機能を実装できます。

コピー

単一セルの選択状態でCtrl + Cを利用して、その値をクリップボードにコピーされEXCELなどにペーストできます。

値のパーシングとフォーマッティング

valueParserを使用して、入力された文字列を数字に変更したり、
valueFormatterに数字に、を追加するのができます。

 { field: "price", headerName: "値段", editable:true,
        valueFormatter: (params) => {
          if (params.value == null) return "";
          return Math.floor(params.value).toLocaleString();
        },
       },

image.png

エンタープライズ版で使える機能

エンターで行移動

enterNavigatesVertically:true
enterNavigatesVerticallyAfterEdit:true

gridOptionsにこの設定を追加したらEXCELみたいにエンターキーで編集終了と一緒にセルの移動ができます

コンテキストメニュー

右クリックで様々な操作ができるコンテキストメニューを呼び出せます。
こちらの表示項目もAG-grid設定で編集できます。

マルチセレクト

enableRangeSelection:true

このオプションを設定するとドラッグで複数のセルを選択できます。
この状態でコピー&ペーストも可能なので、複数個の内容を移すのに便利です。

EXCELファイルダウンロード

image.png

AG-gridのエンタープライズ版では、右クリックを使用して、
現在のテーブルをEXCELファイルにEXPORTできます!

追加のカスタム

公式のオプションから離れたものもいろいろカスタムできます!

方向キーでセル間を移動

ここからは公式オプションではなく、
scriptを使ってカスタムしてみましょう。

    import { AgGridReact } from 'ag-grid-react';
import { ModuleRegistry, AllCommunityModule, themeQuartz } from 'ag-grid-community';
import { useState, useCallback, useRef } from 'react';

ModuleRegistry.registerModules([AllCommunityModule]);

// 1.カスタムコンポーネント定義
const ArrowKeyNavigationEditor = (params) => {
  const [value, setValue] = useState(params.value);
  const inputRef = useRef(null);

  // キーダウンイベント処理
  const onKeyDown = (event) => {
    const key = event.key;
    const isArrowKey = ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(key);

    if (!isArrowKey) return;

    // 1. 基本動作中止
    event.preventDefault();

    // 2. 値保存、編集中止
    params.stopEditing();

    // 3. フォーカス移動
    setTimeout(() => {
      const api = params.api;
      const currentRowIndex = params.node.rowIndex;
      const currentColumn = params.column;

      let nextRowIndex = currentRowIndex;
      let nextColumn = currentColumn;

      if (key === 'ArrowUp' || key === 'ArrowDown') {
        nextRowIndex = key === 'ArrowUp' ? currentRowIndex - 1 : currentRowIndex + 1;
        if (nextRowIndex < 0 || nextRowIndex >= api.getDisplayedRowCount()) return;
      } else {
        const allColumns = api.getAllDisplayedColumns();
        const currentColIndex = allColumns.indexOf(currentColumn);
        const nextColIndex = key === 'ArrowLeft' ? currentColIndex - 1 : currentColIndex + 1;
        if (nextColIndex < 0 || nextColIndex >= allColumns.length) return;
        nextColumn = allColumns[nextColIndex];
      }

      // 4.次のセルにフォーカス移動
      api.setFocusedCell(nextRowIndex, nextColumn);
      api.startEditingCell({ rowIndex: nextRowIndex, colKey: nextColumn.getId() });
    }, 0);
  };

  return (
    <input
      ref={inputRef}
      className="ag-input-field-input ag-text-field-input"
      style={{ width: '100%', height: '100%', border: 'none' }}
      value={value}
      onChange={(e) => setValue(e.target.value)}
      onKeyDown={onKeyDown}
      autoFocus
    />
  );
};

function App() {
  const [colDefs] = useState([
    { field: "No", width: 80 },
    { 
      field: "Product", 
      flex: 1, 
      editable: true,
      cellEditor: ArrowKeyNavigationEditor // カスタム適用
    },
    { 
      field: "price", 
      editable: true,
      cellEditor: ArrowKeyNavigationEditor // カスタム適用
    },
  ]);

  const [rowData] = useState([
    { No: 1, Product: "グミ", price: 600 },
    { No: 2, Product: "チョコ", price: 600 },
    { No: 3, Product: "プリン", price: 600 },
    { No: 4, Product: "ケーキ", price: 800 },
  ]);

  return (
    <div style={{ padding: '30px' }}>
      <h1>スイーツメニュー</h1>
      <div className="ag-theme-quartz" style={{ height: 300, width: 500 }}>
        <AgGridReact
          rowData={rowData}
          columnDefs={colDefs}
          theme={themeQuartz}
          singleClickEdit={true}
          stopEditingWhenCellsLoseFocus={true}
        />
      </div>
    </div>
  );
}

export default App;

これ以外にもscriptでいろんなカスタムが可能です。
もちろんgridOptionなど、基本オプションも澤山なのでまずはそこで探してみるのもお勧めです!

Localeの設定で日本語で使おう!

AG-gridを日本語で使ってみましょう。
基本英語だったメニューなどが日本語に出るのでとても便利です。

使える言語の種類はここ
https://www.ag-grid.com/javascript-data-grid/localisation/#reference-localisation-getLocaleText

npm install @ag-grid-community/locale

まずはAG-gridコミュニティーのロケールを設置します。
いろんな言語をサポートしています。

import { AG_GRID_LOCALE_JP } from '@ag-grid-community/locale';

設置が終わったら、文書のヘッダーにロケールをimportします。

<AgGridReact
          rowData={rowData}
          columnDefs={colDefs}
          theme={themeQuartz}
          //ここにロケールデータを設定
          localeText={AG_GRID_LOCALE_JP}
        />

そのあと、自分のAG-gridのオプションに設定したら完了です。

ここに紹介した内容以外にも、エンタープライズ版の使用やscriptのカスタムの使用で使えるオプションはいくらでもあります。

自分が一番使いやすい方向で、またはプロジェクトで必要な機能にカスタムしてみましょう!

66
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
66
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?