ブラウザ上でピボットテーブルが作れるJavaScriptライブラリ「orb」を紹介します

めちゃいい感じのライブラリっぽいんですが如何せんドキュメントがない？？見つけられない？？のでデモを弄ってなんとなく理解した仕様をまとめます。えらい！

## リンク
https://github.com/nnajm/orb

# 何ができるライブラリ？
![demo](https://camo.githubusercontent.com/71ae3a3c9c2d0113b78d131fc4274ac72b5fe90e/687474703a2f2f692e696d6775722e636f6d2f785777366e34742e676966)

* D&Dによる項目の移動
* ソート
* フィルタ
* ドリルダウン
* 行/列それぞれに複数の項目をセット
* 合計/小計行および列を自動挿入
* エクセル出力

など、欲しい機能は大体揃ってます(エクセル出力はなぜかxls形式ですが…)
あとデザインがBootstrapベースで地味に嬉しい。

# 使い方
まずは基本的な使い方から。
コードの中で解説を入れていきます。

```:フォルダ構成
root/
  ├ demo.html
  ├ demo.js
  ├ demo_data.js
  ├ orb/
  │  ├ orb.css
  │  ├ orb.js
  │  └ deps/
  │     ├ JSXTransformer-0.12.2.js
  │     ├ less.js
  │     └ react-0.12.2.js
  └ custom_orb.css
```

```html:demo.html
<!DOCTYPE html>
<html lang="ja">

  <head>
    <meta charset="UTF-8">
    <title>orb demo</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css" integrity="sha384-PmY9l28YgO4JwMKbTvgaS7XNZJ30MK9FAZjjzXtlqyZCqBY6X6bXIkM++IkyinN+" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="./orb/orb.css">
    <link rel="stylesheet" type="text/css" href="./custom_orb.css">
    <script src="./orb/deps/react-0.12.2.js"></script>
    <script src="./orb/orb.js"></script>
    <script src="./demo_data.js"></script>
    <script src="./demo.js"></script>
  </head>

  <body>
    <div id="orb" style="padding: 7px"></div>
    <!-- IDは好きに決めてください。後で使います。 -->
  </body>

</html>
```

```javascript:demo_data.js
const demo_data = [
  ["ポークカレー","お肉","チキンにこみカレー",875,22.7,28.3,126.7,4],
  ["ポークカレー","揚げ物","フライドチキンカレー",1051,26.8,40.6,136.5,3.9],
  ["ポークカレー","揚げ物","ロースカツカレー",1153,27.6,45.1,148.6,4],
  ["ポークカレー","揚げ物","チキンカツカレー",1200,30.3,50.2,148.3,4.3],
  ["ポークカレー","揚げ物","パリパリチキンカレー",1036,27.9,37.8,138.1,4.1],
  ["ポークカレー","揚げ物","メンチカツカレー",1097,21.1,41.8,151.7,4.3],
  ["ポークカレー","お肉","ハンバーグカレー",939,26.1,29.5,136.3,4.4],
  ["ポークカレー","お肉","豚しゃぶカレー",1059,22.5,46.6,128.3,3.3],
  ["ポークカレー","お肉","ソーセージカレー",1035,21.6,43.2,131.5,4.4],
  ["ポークカレー","お肉","チーズインハンバーグカレー",1078,25.8,43,138.7,5],
  ["ポークカレー","揚げ物","ビーフカツカレー",1267,27.2,58.2,152.2,4.7],
  ["ポークカレー","揚げ物","手仕込とんかつカレー",1347,34.6,65.1,146.1,3.8],
  ["ポークカレー","揚げ物","チキン三昧カレー",1615,56.8,79.1,158.5,5.7],
  ["ポークカレー","揚げ物","フィッシュフライカレー",980,22,32.8,142.2,4.2],
  ["ポークカレー","海の幸","たっぷりあさりカレー",823,23.7,21.3,127.6,3.8],
  ["ポークカレー","海の幸","エビあさりカレー",829,26.6,20.9,127.2,3.9],
  ["ポークカレー","海の幸","イカカレー",888,24.2,26.2,132.3,3.7],
  ["ポークカレー","海の幸","エビにこみカレー",834,29.5,20.4,126.7,4],
  ["ポークカレー","海の幸","海の幸カレー",895,33,24,130.1,4.2],
  ["ポークカレー","揚げ物","エビカツカレー",1040,26,36.3,145.3,4.7],
  ["ポークカレー","野菜","なすカレー",921,12.4,36.5,131.2,3.3],
  ["ポークカレー","野菜","やさいカレー",845,13.2,22.1,142.2,3.3],
  ["ポークカレー","野菜","ほうれん草カレー",766,13.2,20.1,128.1,3.4],
  ["ポークカレー","野菜","トマトアスパラカレー",773,12.8,20,130.4,3.2],
  ["ポークカレー","野菜","野菜三昧カレー",1021,15.7,38.7,148.5,3.5],
  ["ポークカレー","その他","納豆カレー",841,18.5,24.1,131.9,3.3],
  ["ポークカレー","その他","スクランブルエッグカレー",900,15.9,31.9,131.6,3.8],
  ["ポークカレー","その他","チーズカレー",935,23.4,34.9,127.9,4.2],
  ["ポークカレー","揚げ物","クリームコロッケカレー",1142,17.1,47.2,155.7,4.6],
  ["ポークカレー","その他","きのこカレー",765,13,20.1,129.4,3.7],
  ["ポークカレー","その他","ネバネバ三昧カレー",859,19.3,24.1,135.6,3.9],
  ["甘口ポークカレー","お肉","チキンにこみカレー",840,22,25.7,125.1,3.3],
  ["甘口ポークカレー","揚げ物","フライドチキンカレー",1016,26.1,38,134.9,3.2],
  ["甘口ポークカレー","揚げ物","ロースカツカレー",1118,26.9,42.5,147,3.3],
  ["甘口ポークカレー","揚げ物","チキンカツカレー",1165,29.6,47.6,146.7,3.6],
  ["甘口ポークカレー","揚げ物","パリパリチキンカレー",1001,27.2,35.2,136.5,3.4],
  ["甘口ポークカレー","揚げ物","メンチカツカレー",1062,20.4,39.2,150.1,3.6],
  ["甘口ポークカレー","お肉","ハンバーグカレー",904,25.4,26.9,134.7,3.7],
  ["甘口ポークカレー","お肉","豚しゃぶカレー",1024,21.8,44,126.7,2.6],
  ["甘口ポークカレー","お肉","ソーセージカレー",1000,20.9,40.6,129.9,3.7],
  ["甘口ポークカレー","お肉","チーズインハンバーグカレー",1043,25.1,40.4,137.1,4.3],
  ["甘口ポークカレー","揚げ物","ビーフカツカレー",1232,26.5,55.6,150.6,4],
  ["甘口ポークカレー","揚げ物","手仕込とんかつカレー",1312,33.9,62.5,144.5,3.1],
  ["甘口ポークカレー","揚げ物","チキン三昧カレー",1580,56.1,76.5,156.9,5],
  ["甘口ポークカレー","揚げ物","フィッシュフライカレー",945,21.3,30.2,140.6,3.5],
  ["甘口ポークカレー","海の幸","たっぷりあさりカレー",788,23,18.7,126,3.1],
  ["甘口ポークカレー","海の幸","エビあさりカレー",794,25.9,18.3,125.6,3.2],
  ["甘口ポークカレー","海の幸","イカカレー",853,23.5,23.6,130.7,3],
  ["甘口ポークカレー","海の幸","エビにこみカレー",799,28.8,17.8,125.1,3.3],
  ["甘口ポークカレー","海の幸","海の幸カレー",860,32.3,21.4,128.5,3.5],
  ["甘口ポークカレー","揚げ物","エビカツカレー",1005,25.3,33.7,143.7,4],
  ["甘口ポークカレー","野菜","なすカレー",886,11.7,33.9,129.6,2.6],
  ["甘口ポークカレー","野菜","やさいカレー",810,12.5,19.5,140.6,2.6],
  ["甘口ポークカレー","野菜","ほうれん草カレー",731,12.5,17.5,126.5,2.7],
  ["甘口ポークカレー","野菜","トマトアスパラカレー",738,12.1,17.4,128.8,2.5],
  ["甘口ポークカレー","野菜","野菜三昧カレー",986,15,36.1,146.9,2.8],
  ["甘口ポークカレー","その他","納豆カレー",806,17.8,21.5,130.3,2.6],
  ["甘口ポークカレー","その他","スクランブルエッグカレー",865,15.2,29.3,130,3.1],
  ["甘口ポークカレー","その他","チーズカレー",900,22.7,32.3,126.3,3.5],
  ["甘口ポークカレー","揚げ物","クリームコロッケカレー",1107,16.4,44.6,154.1,3.9],
  ["甘口ポークカレー","その他","きのこカレー",730,12.3,17.5,127.8,3],
  ["甘口ポークカレー","その他","ネバネバ三昧カレー",824,18.6,21.5,134,3.2],
  ["ビーフカレー","お肉","チキンにこみカレー",947,26.6,35.4,124.8,3.3],
  ["ビーフカレー","揚げ物","フライドチキンカレー",1123,30.7,47.7,134.6,3.2],
  ["ビーフカレー","揚げ物","ロースカツカレー",1225,31.5,52.2,146.7,3.3],
  ["ビーフカレー","揚げ物","チキンカツカレー",1272,34.2,57.3,146.4,3.6],
  ["ビーフカレー","揚げ物","パリパリチキンカレー",1108,31.8,44.9,136.2,3.4],
  ["ビーフカレー","揚げ物","メンチカツカレー",1169,25,48.9,149.8,3.6],
  ["ビーフカレー","お肉","ハンバーグカレー",1011,30,36.6,134.4,3.7],
  ["ビーフカレー","お肉","豚しゃぶカレー",1131,26.4,53.7,126.4,2.6],
  ["ビーフカレー","お肉","ソーセージカレー",1107,25.5,50.3,129.6,3.7],
  ["ビーフカレー","お肉","チーズインハンバーグカレー",1150,29.7,50.1,136.8,4.3],
  ["ビーフカレー","揚げ物","ビーフカツカレー",1339,31.1,65.3,150.3,4],
  ["ビーフカレー","揚げ物","手仕込とんかつカレー",1419,38.5,72.2,144.2,3.1],
  ["ビーフカレー","揚げ物","チキン三昧カレー",1687,60.7,86.2,156.6,5],
  ["ビーフカレー","揚げ物","フィッシュフライカレー",1052,25.9,39.9,140.3,3.5],
  ["ビーフカレー","海の幸","たっぷりあさりカレー",895,27.6,28.4,125.7,3.1],
  ["ビーフカレー","海の幸","エビあさりカレー",901,30.5,28,125.3,3.2],
  ["ビーフカレー","海の幸","イカカレー",960,28.1,33.3,130.4,3],
  ["ビーフカレー","海の幸","エビにこみカレー",906,33.4,27.5,124.8,3.3],
  ["ビーフカレー","海の幸","海の幸カレー",967,36.9,31.1,128.2,3.5],
  ["ビーフカレー","揚げ物","エビカツカレー",1112,29.9,43.4,143.4,4],
  ["ビーフカレー","野菜","なすカレー",993,16.3,43.6,129.3,2.6],
  ["ビーフカレー","野菜","やさいカレー",917,17.1,29.2,140.3,2.6],
  ["ビーフカレー","野菜","ほうれん草カレー",838,17.1,27.2,126.2,2.7],
  ["ビーフカレー","野菜","トマトアスパラカレー",845,16.7,27.1,128.5,2.5],
  ["ビーフカレー","野菜","野菜三昧カレー",1093,19.6,45.8,146.6,2.8],
  ["ビーフカレー","その他","納豆カレー",913,22.4,31.2,130,2.6],
  ["ビーフカレー","その他","スクランブルエッグカレー",972,19.8,39,129.7,3.1],
  ["ビーフカレー","その他","チーズカレー",1007,27.3,42,126,3.5],
  ["ビーフカレー","揚げ物","クリームコロッケカレー",1214,21,54.3,153.8,3.9],
  ["ビーフカレー","その他","きのこカレー",837,16.9,27.2,127.5,3],
  ["ビーフカレー","その他","ネバネバ三昧カレー",931,23.2,31.2,133.7,3.2],
  ["ハッシュドビーフ","お肉","チキンにこみカレー",1060,31.7,41.5,132.8,3],
  ["ハッシュドビーフ","揚げ物","フライドチキンカレー",1236,35.8,53.8,142.6,2.9],
  ["ハッシュドビーフ","揚げ物","ロースカツカレー",1338,36.6,58.3,154.7,3],
  ["ハッシュドビーフ","揚げ物","チキンカツカレー",1385,39.3,63.4,154.4,3.3],
  ["ハッシュドビーフ","揚げ物","パリパリチキンカレー",1221,36.9,51,144.2,3.1],
  ["ハッシュドビーフ","揚げ物","メンチカツカレー",1282,30.1,55,157.8,3.3],
  ["ハッシュドビーフ","お肉","ハンバーグカレー",1124,35.1,42.7,142.4,3.4],
  ["ハッシュドビーフ","お肉","豚しゃぶカレー",1244,31.5,59.8,134.4,2.3],
  ["ハッシュドビーフ","お肉","ソーセージカレー",1220,30.6,56.4,137.6,3.4],
  ["ハッシュドビーフ","お肉","チーズインハンバーグカレー",1263,34.8,56.2,144.8,4],
  ["ハッシュドビーフ","揚げ物","ビーフカツカレー",1452,36.2,71.4,158.3,3.7],
  ["ハッシュドビーフ","揚げ物","手仕込とんかつカレー",1532,43.6,78.3,152.2,2.8],
  ["ハッシュドビーフ","揚げ物","チキン三昧カレー",1800,65.8,92.3,164.6,4.7],
  ["ハッシュドビーフ","揚げ物","フィッシュフライカレー",1165,31,46,148.3,3.2],
  ["ハッシュドビーフ","海の幸","たっぷりあさりカレー",1008,32.7,34.5,133.7,2.8],
  ["ハッシュドビーフ","海の幸","エビあさりカレー",1014,35.6,34.1,133.3,2.9],
  ["ハッシュドビーフ","海の幸","イカカレー",1073,33.2,39.4,138.4,2.7],
  ["ハッシュドビーフ","海の幸","エビにこみカレー",1019,38.5,33.6,132.8,3],
  ["ハッシュドビーフ","海の幸","海の幸カレー",1080,42,37.2,136.2,3.2],
  ["ハッシュドビーフ","揚げ物","エビカツカレー",1225,35,49.5,151.4,3.7],
  ["ハッシュドビーフ","野菜","なすカレー",1106,21.4,49.7,137.3,2.3],
  ["ハッシュドビーフ","野菜","やさいカレー",1030,22.2,35.3,148.3,2.3],
  ["ハッシュドビーフ","野菜","ほうれん草カレー",951,22.2,33.3,134.2,2.4],
  ["ハッシュドビーフ","野菜","トマトアスパラカレー",958,21.8,33.2,136.5,2.2],
  ["ハッシュドビーフ","野菜","野菜三昧カレー",1206,24.7,51.9,154.6,2.5],
  ["ハッシュドビーフ","その他","納豆カレー",1026,27.5,37.3,138,2.3],
  ["ハッシュドビーフ","その他","スクランブルエッグカレー",1085,24.9,45.1,137.7,2.8],
  ["ハッシュドビーフ","その他","チーズカレー",1120,32.4,48.1,134,3.2],
  ["ハッシュドビーフ","揚げ物","クリームコロッケカレー",1327,26.1,60.4,161.8,3.6],
  ["ハッシュドビーフ","その他","きのこカレー",950,22,33.3,135.5,2.7],
  ["ハッシュドビーフ","その他","ネバネバ三昧カレー",1044,28.3,37.3,141.7,2.9]
]
```
※ <a>https://www.ichibanya.co.jp/menu/pdf/nutrition.pdf</a>のデータを拡張

```javascript:demo.js
window.onload = () => CreatePivotTable(demo_data)

const CreatePivotTable = (data) => {
  const config = {
    dataSource: data,
    canMoveFields: true, 
    dataHeadersLocation: 'columns',
    width: 1906,
    height: 900,
    theme: 'green', /*テーマカラーを指定できます。用意されてるテーマは
    bootstrap、red、blue、green、orange、flower、gray、black、whiteの9色*/
    toolbar: {
      visible: true
    },
    grandTotal: { //このあたりは全て初期値の設定です。ツールバーのvisibleをtrueにしていれば後から変更できます。
      rowsvisible: true,
      columnsvisible: false
    },
    subTotal: {
      visible: true,
      collapsed: true,
      collapsible: true
    },
    rowSettings: {
      subTotal: {
        visible: true,
        collapsed: true,
        collapsible: true
      }
    },
    columnSettings: {
      subTotal: {
        visible: true,
        collapsed: true,
        collapsible: true
      }
    },
    fields: [ //テーブルで扱う項目を作成します。
      {
        name: 0, /*このデータに該当するdataSourceの列番号を指定します。
        プロパティ名おかしいんですが多分{"ベースソース":ポークカレー}みたいなJSONをデータソースにすると
        ここが"ベースソース"になるんじゃないかなあと予想してます。未検証*/
        caption: 'ベースソース'
      },
      {
        name: 1,
        caption: 'ジャンル'
      },
      {
        name: 2,
        caption: 'カレーメニュー'
      },
      {
        name: 3,
        caption: 'エネルギー(kcal)',
        dataSettings: {
          aggregateFunc: 'avg',
          /*この項目を集計対象にした際に使用する関数です。
          count、sum、min、max、avg、prod、stdev、stdevp、var、varpの10種類から選びます。
        　デフォルト値はsum*/
          formatFunc: val => val ? String(parseInt(val)).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : 0
          //format関数みたいなやつです。この例では数値を切り捨ててカンマ区切りを入れています。
        }
      },
      {
        name: 4,
        caption: 'タンパク質(g)',
        dataSettings: {
          aggregateFunc: 'avg',
          formatFunc: val => val ? String(parseInt(val)).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : 0
        }
      },
      {
        name: 5,
        caption: '脂質(g)',
        dataSettings: {
          aggregateFunc: 'avg',
          formatFunc: val => val ? String(parseInt(val)).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : 0
        }
      },
      {
        name: 6,
        caption: '炭水化物(g)',
        dataSettings: {
          aggregateFunc: 'avg',
          formatFunc: val => val ? String(parseInt(val)).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : 0
        }
      },
      {
        name: 7,
        caption: '塩分(g)',
        dataSettings: {
          aggregateFunc: 'avg',
          formatFunc: val => val ? String(parseInt(val)).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : 0
        }
      }
    ],
    //初期配置
    rows: ['ベースソース', 'カレーメニュー'],
    columns: ['ジャンル'],
    data: ['エネルギー(kcal)', 'タンパク質(g)'],
  }
  const pgridwidget = new orb.pgridwidget(config)
  pgridwidget.render(document.getElementById('orb'))
  //demo.htmlでdiv要素に指定したID
}
```
これでdemo.htmlを開くとこんな見た目になります。
![01](https://qiita-image-store.s3.amazonaws.com/0/245527/2290a1cc-c7a7-cd52-3a36-20d9ae2c41f2.png)
ボタンで開閉します。
![02](https://qiita-image-store.s3.amazonaws.com/0/245527/9044e444-e77f-6859-9e21-e89f4ffde4d3.gif)
いい感じです。

## 応用編
上記のサンプルでもまあ使えるは使えるのですが、fields等の作り方が若干イケてないので書き換えます。

```javascript:demo_data.js
const demo_data = {
  columns: [
    {name: 'ベースソース', func: '', init: 'rows'},
    {name: 'ジャンル', func: '', init: 'columns'},
    {name: 'カレーメニュー', func: 'avg', init: ''},
    {name: 'エネルギー(kcal)', func: 'avg', init: 'data'},
    {name: 'タンパク質(g)', func: 'avg', init: 'data'},
    {name: '脂質(g)', func: 'avg', init: ''},
    {name: '炭水化物(g)', func: 'avg', init: ''},
    {name: '塩分(g)', func: 'avg', init: ''}
  ],
  data: [
    ["ポークカレー","お肉","チキンにこみカレー",875,22.7,28.3,126.7,4],
    ["ポークカレー","揚げ物","フライドチキンカレー",1051,26.8,40.6,136.5,3.9],
    ["ポークカレー","揚げ物","ロースカツカレー",1153,27.6,45.1,148.6,4],
    ["ポークカレー","揚げ物","チキンカツカレー",1200,30.3,50.2,148.3,4.3],
    ["ポークカレー","揚げ物","パリパリチキンカレー",1036,27.9,37.8,138.1,4.1],
    ["ポークカレー","揚げ物","メンチカツカレー",1097,21.1,41.8,151.7,4.3],
    ["ポークカレー","お肉","ハンバーグカレー",939,26.1,29.5,136.3,4.4],
    ["ポークカレー","お肉","豚しゃぶカレー",1059,22.5,46.6,128.3,3.3],
    ["ポークカレー","お肉","ソーセージカレー",1035,21.6,43.2,131.5,4.4],
    ["ポークカレー","お肉","チーズインハンバーグカレー",1078,25.8,43,138.7,5],
    ["ポークカレー","揚げ物","ビーフカツカレー",1267,27.2,58.2,152.2,4.7],
    ["ポークカレー","揚げ物","手仕込とんかつカレー",1347,34.6,65.1,146.1,3.8],
    ["ポークカレー","揚げ物","チキン三昧カレー",1615,56.8,79.1,158.5,5.7],
    ["ポークカレー","揚げ物","フィッシュフライカレー",980,22,32.8,142.2,4.2],
    ["ポークカレー","海の幸","たっぷりあさりカレー",823,23.7,21.3,127.6,3.8],
    ["ポークカレー","海の幸","エビあさりカレー",829,26.6,20.9,127.2,3.9],
    ["ポークカレー","海の幸","イカカレー",888,24.2,26.2,132.3,3.7],
    ["ポークカレー","海の幸","エビにこみカレー",834,29.5,20.4,126.7,4],
    ["ポークカレー","海の幸","海の幸カレー",895,33,24,130.1,4.2],
    ["ポークカレー","揚げ物","エビカツカレー",1040,26,36.3,145.3,4.7],
    ["ポークカレー","野菜","なすカレー",921,12.4,36.5,131.2,3.3],
    ["ポークカレー","野菜","やさいカレー",845,13.2,22.1,142.2,3.3],
    ["ポークカレー","野菜","ほうれん草カレー",766,13.2,20.1,128.1,3.4],
    ["ポークカレー","野菜","トマトアスパラカレー",773,12.8,20,130.4,3.2],
    ["ポークカレー","野菜","野菜三昧カレー",1021,15.7,38.7,148.5,3.5],
    ["ポークカレー","その他","納豆カレー",841,18.5,24.1,131.9,3.3],
    ["ポークカレー","その他","スクランブルエッグカレー",900,15.9,31.9,131.6,3.8],
    ["ポークカレー","その他","チーズカレー",935,23.4,34.9,127.9,4.2],
    ["ポークカレー","揚げ物","クリームコロッケカレー",1142,17.1,47.2,155.7,4.6],
    ["ポークカレー","その他","きのこカレー",765,13,20.1,129.4,3.7],
    ["ポークカレー","その他","ネバネバ三昧カレー",859,19.3,24.1,135.6,3.9],
    ["甘口ポークカレー","お肉","チキンにこみカレー",840,22,25.7,125.1,3.3],
    ["甘口ポークカレー","揚げ物","フライドチキンカレー",1016,26.1,38,134.9,3.2],
    ["甘口ポークカレー","揚げ物","ロースカツカレー",1118,26.9,42.5,147,3.3],
    ["甘口ポークカレー","揚げ物","チキンカツカレー",1165,29.6,47.6,146.7,3.6],
    ["甘口ポークカレー","揚げ物","パリパリチキンカレー",1001,27.2,35.2,136.5,3.4],
    ["甘口ポークカレー","揚げ物","メンチカツカレー",1062,20.4,39.2,150.1,3.6],
    ["甘口ポークカレー","お肉","ハンバーグカレー",904,25.4,26.9,134.7,3.7],
    ["甘口ポークカレー","お肉","豚しゃぶカレー",1024,21.8,44,126.7,2.6],
    ["甘口ポークカレー","お肉","ソーセージカレー",1000,20.9,40.6,129.9,3.7],
    ["甘口ポークカレー","お肉","チーズインハンバーグカレー",1043,25.1,40.4,137.1,4.3],
    ["甘口ポークカレー","揚げ物","ビーフカツカレー",1232,26.5,55.6,150.6,4],
    ["甘口ポークカレー","揚げ物","手仕込とんかつカレー",1312,33.9,62.5,144.5,3.1],
    ["甘口ポークカレー","揚げ物","チキン三昧カレー",1580,56.1,76.5,156.9,5],
    ["甘口ポークカレー","揚げ物","フィッシュフライカレー",945,21.3,30.2,140.6,3.5],
    ["甘口ポークカレー","海の幸","たっぷりあさりカレー",788,23,18.7,126,3.1],
    ["甘口ポークカレー","海の幸","エビあさりカレー",794,25.9,18.3,125.6,3.2],
    ["甘口ポークカレー","海の幸","イカカレー",853,23.5,23.6,130.7,3],
    ["甘口ポークカレー","海の幸","エビにこみカレー",799,28.8,17.8,125.1,3.3],
    ["甘口ポークカレー","海の幸","海の幸カレー",860,32.3,21.4,128.5,3.5],
    ["甘口ポークカレー","揚げ物","エビカツカレー",1005,25.3,33.7,143.7,4],
    ["甘口ポークカレー","野菜","なすカレー",886,11.7,33.9,129.6,2.6],
    ["甘口ポークカレー","野菜","やさいカレー",810,12.5,19.5,140.6,2.6],
    ["甘口ポークカレー","野菜","ほうれん草カレー",731,12.5,17.5,126.5,2.7],
    ["甘口ポークカレー","野菜","トマトアスパラカレー",738,12.1,17.4,128.8,2.5],
    ["甘口ポークカレー","野菜","野菜三昧カレー",986,15,36.1,146.9,2.8],
    ["甘口ポークカレー","その他","納豆カレー",806,17.8,21.5,130.3,2.6],
    ["甘口ポークカレー","その他","スクランブルエッグカレー",865,15.2,29.3,130,3.1],
    ["甘口ポークカレー","その他","チーズカレー",900,22.7,32.3,126.3,3.5],
    ["甘口ポークカレー","揚げ物","クリームコロッケカレー",1107,16.4,44.6,154.1,3.9],
    ["甘口ポークカレー","その他","きのこカレー",730,12.3,17.5,127.8,3],
    ["甘口ポークカレー","その他","ネバネバ三昧カレー",824,18.6,21.5,134,3.2],
    ["ビーフカレー","お肉","チキンにこみカレー",947,26.6,35.4,124.8,3.3],
    ["ビーフカレー","揚げ物","フライドチキンカレー",1123,30.7,47.7,134.6,3.2],
    ["ビーフカレー","揚げ物","ロースカツカレー",1225,31.5,52.2,146.7,3.3],
    ["ビーフカレー","揚げ物","チキンカツカレー",1272,34.2,57.3,146.4,3.6],
    ["ビーフカレー","揚げ物","パリパリチキンカレー",1108,31.8,44.9,136.2,3.4],
    ["ビーフカレー","揚げ物","メンチカツカレー",1169,25,48.9,149.8,3.6],
    ["ビーフカレー","お肉","ハンバーグカレー",1011,30,36.6,134.4,3.7],
    ["ビーフカレー","お肉","豚しゃぶカレー",1131,26.4,53.7,126.4,2.6],
    ["ビーフカレー","お肉","ソーセージカレー",1107,25.5,50.3,129.6,3.7],
    ["ビーフカレー","お肉","チーズインハンバーグカレー",1150,29.7,50.1,136.8,4.3],
    ["ビーフカレー","揚げ物","ビーフカツカレー",1339,31.1,65.3,150.3,4],
    ["ビーフカレー","揚げ物","手仕込とんかつカレー",1419,38.5,72.2,144.2,3.1],
    ["ビーフカレー","揚げ物","チキン三昧カレー",1687,60.7,86.2,156.6,5],
    ["ビーフカレー","揚げ物","フィッシュフライカレー",1052,25.9,39.9,140.3,3.5],
    ["ビーフカレー","海の幸","たっぷりあさりカレー",895,27.6,28.4,125.7,3.1],
    ["ビーフカレー","海の幸","エビあさりカレー",901,30.5,28,125.3,3.2],
    ["ビーフカレー","海の幸","イカカレー",960,28.1,33.3,130.4,3],
    ["ビーフカレー","海の幸","エビにこみカレー",906,33.4,27.5,124.8,3.3],
    ["ビーフカレー","海の幸","海の幸カレー",967,36.9,31.1,128.2,3.5],
    ["ビーフカレー","揚げ物","エビカツカレー",1112,29.9,43.4,143.4,4],
    ["ビーフカレー","野菜","なすカレー",993,16.3,43.6,129.3,2.6],
    ["ビーフカレー","野菜","やさいカレー",917,17.1,29.2,140.3,2.6],
    ["ビーフカレー","野菜","ほうれん草カレー",838,17.1,27.2,126.2,2.7],
    ["ビーフカレー","野菜","トマトアスパラカレー",845,16.7,27.1,128.5,2.5],
    ["ビーフカレー","野菜","野菜三昧カレー",1093,19.6,45.8,146.6,2.8],
    ["ビーフカレー","その他","納豆カレー",913,22.4,31.2,130,2.6],
    ["ビーフカレー","その他","スクランブルエッグカレー",972,19.8,39,129.7,3.1],
    ["ビーフカレー","その他","チーズカレー",1007,27.3,42,126,3.5],
    ["ビーフカレー","揚げ物","クリームコロッケカレー",1214,21,54.3,153.8,3.9],
    ["ビーフカレー","その他","きのこカレー",837,16.9,27.2,127.5,3],
    ["ビーフカレー","その他","ネバネバ三昧カレー",931,23.2,31.2,133.7,3.2],
    ["ハッシュドビーフ","お肉","チキンにこみカレー",1060,31.7,41.5,132.8,3],
    ["ハッシュドビーフ","揚げ物","フライドチキンカレー",1236,35.8,53.8,142.6,2.9],
    ["ハッシュドビーフ","揚げ物","ロースカツカレー",1338,36.6,58.3,154.7,3],
    ["ハッシュドビーフ","揚げ物","チキンカツカレー",1385,39.3,63.4,154.4,3.3],
    ["ハッシュドビーフ","揚げ物","パリパリチキンカレー",1221,36.9,51,144.2,3.1],
    ["ハッシュドビーフ","揚げ物","メンチカツカレー",1282,30.1,55,157.8,3.3],
    ["ハッシュドビーフ","お肉","ハンバーグカレー",1124,35.1,42.7,142.4,3.4],
    ["ハッシュドビーフ","お肉","豚しゃぶカレー",1244,31.5,59.8,134.4,2.3],
    ["ハッシュドビーフ","お肉","ソーセージカレー",1220,30.6,56.4,137.6,3.4],
    ["ハッシュドビーフ","お肉","チーズインハンバーグカレー",1263,34.8,56.2,144.8,4],
    ["ハッシュドビーフ","揚げ物","ビーフカツカレー",1452,36.2,71.4,158.3,3.7],
    ["ハッシュドビーフ","揚げ物","手仕込とんかつカレー",1532,43.6,78.3,152.2,2.8],
    ["ハッシュドビーフ","揚げ物","チキン三昧カレー",1800,65.8,92.3,164.6,4.7],
    ["ハッシュドビーフ","揚げ物","フィッシュフライカレー",1165,31,46,148.3,3.2],
    ["ハッシュドビーフ","海の幸","たっぷりあさりカレー",1008,32.7,34.5,133.7,2.8],
    ["ハッシュドビーフ","海の幸","エビあさりカレー",1014,35.6,34.1,133.3,2.9],
    ["ハッシュドビーフ","海の幸","イカカレー",1073,33.2,39.4,138.4,2.7],
    ["ハッシュドビーフ","海の幸","エビにこみカレー",1019,38.5,33.6,132.8,3],
    ["ハッシュドビーフ","海の幸","海の幸カレー",1080,42,37.2,136.2,3.2],
    ["ハッシュドビーフ","揚げ物","エビカツカレー",1225,35,49.5,151.4,3.7],
    ["ハッシュドビーフ","野菜","なすカレー",1106,21.4,49.7,137.3,2.3],
    ["ハッシュドビーフ","野菜","やさいカレー",1030,22.2,35.3,148.3,2.3],
    ["ハッシュドビーフ","野菜","ほうれん草カレー",951,22.2,33.3,134.2,2.4],
    ["ハッシュドビーフ","野菜","トマトアスパラカレー",958,21.8,33.2,136.5,2.2],
    ["ハッシュドビーフ","野菜","野菜三昧カレー",1206,24.7,51.9,154.6,2.5],
    ["ハッシュドビーフ","その他","納豆カレー",1026,27.5,37.3,138,2.3],
    ["ハッシュドビーフ","その他","スクランブルエッグカレー",1085,24.9,45.1,137.7,2.8],
    ["ハッシュドビーフ","その他","チーズカレー",1120,32.4,48.1,134,3.2],
    ["ハッシュドビーフ","揚げ物","クリームコロッケカレー",1327,26.1,60.4,161.8,3.6],
    ["ハッシュドビーフ","その他","きのこカレー",950,22,33.3,135.5,2.7],
    ["ハッシュドビーフ","その他","ネバネバ三昧カレー",1044,28.3,37.3,141.7,2.9]
  ]
}
```

```javascript:demo.js
window.onload = () => CreatePivotTable(demo_data)

const CreatePivotTable = (data) => {
  const config = {
    dataSource: data.data,
    canMoveFields: true, 
    dataHeadersLocation: 'columns',
    width: 1906,
    height: 900,
    theme: 'green',
    toolbar: {
      visible: true
    },
    grandTotal: {
      rowsvisible: true,
      columnsvisible: false
    },
    subTotal: {
      visible: true,
      collapsed: true,
      collapsible: true
    },
    rowSettings: {
      subTotal: {
        visible: true,
        collapsed: true,
        collapsible: true
      }
    },
    columnSettings: {
      subTotal: {
        visible: true,
        collapsed: true,
        collapsible: true
      }
    },
    fields: [
    ],
    rows: [],
    columns: [],
    data: [],
  }
  //data.columnsを走査してfields及び初期配置を指定
  for (let i=0, l=data.columns.length; i<l; i++) {
    const col = data.columns[i]
    const fieldConfig = {
      name: i,
      caption: col.name
    }
    if (col.func) {
      fieldConfig.dataSettings = {
        aggregateFunc: col.func,
        formatFunc: val => val ? String(parseInt(val)).replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,') : 0
      }
    }
    config.fields.push(fieldConfig)
    if (col.init) {
      config[col.init].push(col.name)
    }
  }
  const pgridwidget = new orb.pgridwidget(config)
  pgridwidget.render(document.getElementById('orb'))
}
```
こっちの方が綺麗なはず。

# 問題点
ボタンがBootstrapのものなので場合によって潰れます。
![03](https://qiita-image-store.s3.amazonaws.com/0/245527/97124b7b-7714-fa8e-c3b4-7c0cdb8b7187.png)
![04](https://qiita-image-store.s3.amazonaws.com/0/245527/12aef0e1-480b-cef5-7b54-37276610048b.png)
またボタンが多すぎると画面からはみ出して使用不可能になります。
ので、これを解消するためのcssを書きましょう。

```css:custom_orb.css
.fld-btn {
  white-space: nowrap;
}

.orb .inner-table.upper-buttons{
  table-layout: fixed;
}

.orb .av-flds{
  overflow-x: auto;
}

::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}

/* orb.cssから好きな色を持ってきてください */
::-webkit-scrollbar-thumb {
  border-radius: 3px;
  background:#ebf7e7;
  border:1px solid #9fda8b;
}

::-webkit-scrollbar-thumb:active {
  border-radius: 3px;
  background:#9fda8b;
}
```
スクロールバーのくだりはwebkit系ブラウザのみ対応ですが、これで
![5](https://qiita-image-store.s3.amazonaws.com/0/245527/830ab8cd-9e42-dfe5-315a-096ac3c6c54f.gif)
OKです。

# 終わりに
少なくとも日本語の解説記事はこれが初だと思います。
そもそもブラウザでピボットテーブルが作りたい！という状況自体稀だとは思いますが、
フィルタに正規表現が使えたり本当に高機能なので是非使ってみて下さい🍛