ピボットグリッド:アウトラインモード

アウトラインモードでは、PivotGridは行フィールドをアウトライン形式でレンダリングします。これはよりコンパクトで、画面に表示される余白の量を減らします。アウトラインモードは、多数の行フィールドを持つビューに推奨されます。

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; // import { PivotEngine, PivotPanel, PivotGrid } from '@grapecity/wijmo.olap'; import { CellRange } from '@grapecity/wijmo.grid'; import { toggleClass } from '@grapecity/wijmo'; import { getData } from './data'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { // create the olap components let theEngine = new PivotEngine({ autoGenerateFields: false, fields: [ { binding: 'country', header: '国' }, { binding: 'product', header: '商品' }, { binding: 'color', header: '色' }, { binding: 'active', header: '有効' }, { binding: 'due', header: '期限' }, { binding: 'sales', header: '売上' }, { binding: 'expenses', header: '費用' }, { binding: 'downloads', header: 'DL数' } ], itemsSource: getData(1000), showRowTotals: 'Subtotals', showColumnTotals: 'None', totalsBeforeData: true, rowFields: ['国', '商品', '色'], valueFields: ['売上', '費用', 'DL数'] }); // let thePanel = new PivotPanel('#thePanel', { engine: theEngine, }); // let theGrid = new PivotGrid('#theGrid', { itemsSource: theEngine, outlineMode: true, loadedRows: (s) => { let totalIndex = theEngine.totalsBeforeData ? 0 : s.rows.length - 1; s.rows[totalIndex].visible = false; } }); // // customize the olap components document.getElementById('outline').addEventListener('click', e => { theGrid.outlineMode = e.target.checked; if (theGrid.outlineMode) { let before = document.getElementById('before'); theEngine.totalsBeforeData = before.checked = true; } else { let before = document.getElementById('style'); before.checked = false; toggleClass(theGrid.hostElement, 'outline', false); } }); // document.getElementById('style').addEventListener('click', e => { let customStyle = e.target.checked; toggleClass(theGrid.hostElement, 'outline', customStyle); }); // document.getElementById('before').addEventListener('click', e => { theEngine.totalsBeforeData = e.target.checked; }); // document.getElementById('headers').addEventListener('click', e => { theGrid.showRowFieldHeaders = e.target.checked; }); // // export to CSV document.getElementById('csv').addEventListener('click', e => { let rng = new CellRange(0, 0, theGrid.rows.length - 1, theGrid.columns.length - 1), csv = theGrid.getClipString(rng, true, true, true); // exportFile(csv, 'FlexGrid.csv'); }); // function exportFile(csv, fileName) { let fileType = 'txt/csv;charset=utf-8'; // if (navigator.msSaveBlob) { // IE navigator.msSaveBlob(new Blob([csv], { type: fileType }), fileName); } else { let e = document.createElement('a'); e.setAttribute('href', 'data:' + fileType + ',' + encodeURIComponent(csv)); e.setAttribute('download', fileName); e.style.display = 'none'; document.body.appendChild(e); e.click(); document.body.removeChild(e); } } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Grapecity Wijmo OLAP Pivot Grid OutlineMode</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <label> アウトラインモード <input id="outline" type="checkbox" checked> </label><br/> <label> カスタムスタイル <input id="style" type="checkbox" checked> </label><br/> <label> 合計をデータの前に表示 <input id="before" type="checkbox" checked> </label><br/> <label> 行フィールドヘッダーを表示 <input id="headers" type="checkbox" checked> </label><br/> <div class="row"> <div class="col-xs-5"> <div id="thePanel"></div> </div> <div class="col-xs-7"> <div id="theGrid" class="outline"></div> <button id="csv" class="btn btn-primary">CSVの保存</button> </div> </div> </div> </body> </html> // // get the raw data export function getData(count) { let countries = ['ドイツ', 'イタリア', '日本', 'イギリス', 'アメリカ'], products = ['ウィジェット', 'ガジェット', 'ツール'], colors = ['赤', '緑', '青', '黄', '紫', '白', '黒', 'マゼンタ'], data = []; // for (let i = 0; i < count; i++) { let trend = (i % countries.length + 1) * (i % products.length + 1); data.push({ country: randomItem(countries), product: randomItem(products), color: randomItem(colors), active: i % 5 == 0, due: new Date(), sales: Math.random() * 10000 * trend, expenses: Math.random() * 5000 * trend, downloads: Math.random() * 100000 * trend }); } // return data; } // // get a random item from an array function randomItem(arr) { return arr[Math.floor(Math.random() * arr.length)]; } .wj-pivotgrid { max-height: 400px; box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); } .outline.wj-pivotgrid .wj-cell:not(.wj-state-selected) { border-right: none; border-bottom: none; background: #fff; color: #000; } body { margin-bottom: 24pt; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import { Component, Inject, enableProdMode, NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { WjOlapModule } from '@grapecity/wijmo.angular2.olap'; import { PivotEngine, PivotGrid } from '@grapecity/wijmo.olap'; import { CellRange } from '@grapecity/wijmo.grid'; import { DataService } from './app.data'; @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { ng: PivotEngine; outlineMode = true; customStyle = true; showRowFieldHeaders = true; constructor(@Inject(DataService) private dataService: DataService) { this.ng = new PivotEngine({ autoGenerateFields: false, fields: [ { binding: 'country', header: '国' }, { binding: 'product', header: '商品' }, { binding: 'color', header: '色' }, { binding: 'active', header: '有効' }, { binding: 'due', header: '期限' }, { binding: 'sales', header: '売上' }, { binding: 'expenses', header: '費用' }, { binding: 'downloads', header: 'DL数' } ], itemsSource: dataService.getData(1000), // raw data showRowTotals: 'Subtotals', showColumnTotals: 'None', totalsBeforeData: true, rowFields: ['国', '商品', '色'], valueFields: ['売上', '費用', 'DL数'] }); } outlineModeChanged() { if (this.outlineMode) { this.ng.totalsBeforeData = true; } else { this.customStyle = false; } } exportToCsv(grid: PivotGrid) { let rng = new CellRange(0, 0, grid.rows.length - 1, grid.columns.length - 1), csv = grid.getClipString(rng, true, true, true); this.exportFile(csv, 'FlexGrid.csv'); } exportFile(csv: string, fileName: string) { let fileType = 'txt/csv;charset=utf-8'; if (navigator.msSaveBlob) { // IE navigator.msSaveBlob(new Blob([csv], { type: fileType }), fileName); } else { let e = document.createElement('a'); e.setAttribute('href', 'data:' + fileType + ',' + encodeURIComponent(csv)); e.setAttribute('download', fileName); e.style.display = 'none'; document.body.appendChild(e); e.click(); document.body.removeChild(e); } } } @NgModule({ imports: [WjOlapModule, BrowserModule, FormsModule], declarations: [AppComponent], providers: [DataService], bootstrap: [AppComponent] }) export class AppModule { } // enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Grapecity Wijmo OLAP Pivot Grid OutlineMode</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <label> アウトラインモード <input id="outline" type="checkbox" [(ngModel)]="outlineMode" (change)="outlineModeChanged()" /> </label><br /> <label> カスタムスタイル <input id="style" type="checkbox" [(ngModel)]="customStyle" /> </label><br /> <label> 合計をデータの前に表示 <input id="before" type="checkbox" [(ngModel)]="ng.totalsBeforeData" /> </label><br /> <label> 行フィールドヘッダーを表示 <input id="headers" type="checkbox" [(ngModel)]="showRowFieldHeaders" /> </label><br /> <div class="row"> <div class="col-xs-5"> <wj-pivot-panel [itemsSource]="ng"> </wj-pivot-panel> </div> <div class="col-xs-7"> <wj-pivot-grid #grid [class.outline]="customStyle" [itemsSource]="ng" [outlineMode]="outlineMode" [showRowFieldHeaders]="showRowFieldHeaders"> </wj-pivot-grid> <button class="btn btn-primary" (click)="exportToCsv(grid)"> CSVの保存 </button> </div> </div> </div> import { Injectable } from '@angular/core'; @Injectable() export class DataService { getData(cnt: number): any[] { let countries = ['ドイツ', 'イタリア', '日本', 'イギリス', 'アメリカ'], products = ['ウィジェット', 'ガジェット', 'ツール'], colors = ['赤', '緑', '青', '黄', '紫', '白', '黒', 'マゼンタ'], data = []; for (let i = 0; i < cnt; i++) { let trend = (i % countries.length + 1) * (i % products.length + 1); data.push({ country: randomItem(countries), product: randomItem(products), color: randomItem(colors), active: i % 5 == 0, due: new Date(), sales: Math.random() * 10000 * trend, expenses: Math.random() * 5000 * trend, downloads: Math.random() * 100000 * trend }); } return data; } } function randomItem(arr: string[]): string { return arr[Math.floor(Math.random() * arr.length)]; } .wj-pivotgrid { max-height: 400px; box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); } .outline.wj-pivotgrid .wj-cell:not(.wj-state-selected) { border-right: none; border-bottom: none; background: #fff; color: #000; } body { margin-bottom: 24pt; } import './app.css'; import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; // import * as olap from '@grapecity/wijmo.olap'; import * as wjcOlap from '@grapecity/wijmo.react.olap'; import { CellRange } from '@grapecity/wijmo.grid'; import { getData } from './data'; // class App extends React.Component { // // initialize state constructor(props) { super(props); // this._ng = new olap.PivotEngine({ autoGenerateFields: false, fields: [ { binding: 'country', header: '国' }, { binding: 'product', header: '商品' }, { binding: 'color', header: '色' }, { binding: 'active', header: '有効' }, { binding: 'due', header: '期限' }, { binding: 'sales', header: '売上' }, { binding: 'expenses', header: '費用' }, { binding: 'downloads', header: 'DL数' } ], itemsSource: getData(1000), showRowTotals: 'Subtotals', showColumnTotals: 'None', totalsBeforeData: true, rowFields: ['国', '商品', '色'], valueFields: ['売上', '費用', 'DL数'] }); // this.state = { outlineMode: true, customStyle: true, totalsBeforeData: true, showRowFieldHeaders: true }; } // render() { return (<div className="container-fluid"> <label> アウトラインモード{' '} <input id="outlineMode" type="checkbox" checked={this.state.outlineMode} onChange={this._handleInputChange.bind(this)}/> </label><br /> <label> カスタムスタイル{' '} <input id="customStyle" type="checkbox" checked={this.state.customStyle} onChange={this._handleInputChange.bind(this)}/> </label><br /> <label> 合計をデータの前に表示{' '} <input id="totalsBeforeData" type="checkbox" checked={this.state.totalsBeforeData} onChange={this._handleInputChange.bind(this)}/> </label><br /> <label> 行フィールドヘッダーを表示{' '} <input id="showRowFieldHeaders" type="checkbox" checked={this.state.showRowFieldHeaders} onChange={this._handleInputChange.bind(this)}/> </label><br /> <div className="row"> <div className="col-xs-5"> <wjcOlap.PivotPanel itemsSource={this._ng}> </wjcOlap.PivotPanel> </div> <div className={'col-xs-7' + (this.state.customStyle ? ' outline' : '')}> <wjcOlap.PivotGrid initialized={sender => { this._grid = sender; }} // save reference to the grid itemsSource={this._ng} outlineMode={this.state.outlineMode} showRowFieldHeaders={this.state.showRowFieldHeaders}> </wjcOlap.PivotGrid> <button className="btn btn-primary" onClick={this._exportToCsv.bind(this)}> CSVの保存 </button> </div> </div> </div>); } // // handle checkboxes _handleInputChange(e) { const id = e.target.id; const checked = e.target.checked; // this.setState({ [id]: checked }); // switch (id) { case 'totalsBeforeData': // update engine from state this._ng.totalsBeforeData = checked; break; case 'outlineMode': // changing outlineMode resets subtotal position, style if (checked) { this._ng.totalsBeforeData = checked; this.setState({ totalsBeforeData: checked }); } else { this.setState({ customStyle: checked }); } break; } } // // export grid to CSV _exportToCsv() { let grid = this._grid, rng = new CellRange(0, 0, grid.rows.length - 1, grid.columns.length - 1), csv = grid.getClipString(rng, true, true, true); // this._exportFile(csv, 'FlexGrid.csv'); } // _exportFile(csv, fileName) { let fileType = 'txt/csv;charset=utf-8'; // if (navigator.msSaveBlob) { // IE navigator.msSaveBlob(new Blob([csv], { type: fileType }), fileName); } else { let e = document.createElement('a'); e.setAttribute('href', 'data:' + fileType + ',' + encodeURIComponent(csv)); e.setAttribute('download', fileName); e.style.display = 'none'; document.body.appendChild(e); e.click(); document.body.removeChild(e); } } } // ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Grapecity Wijmo OLAP Pivot Grid OutlineMode</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html> .wj-pivotgrid { max-height: 400px; box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); } .outline .wj-pivotgrid .wj-cell:not(.wj-state-selected) { border-right: none; border-bottom: none; background: #fff; color: #000; } body { margin-bottom: 24pt; } // get the raw data export function getData(count) { let countries = ['ドイツ', 'イタリア', '日本', 'イギリス', 'アメリカ'], products = ['ウィジェット', 'ガジェット', 'ツール'], colors = ['赤', '緑', '青', '黄', '紫', '白', '黒', 'マゼンタ'], data = []; // for (let i = 0; i < count; i++) { let trend = (i % countries.length + 1) * (i % products.length + 1); data.push({ country: randomItem(countries), product: randomItem(products), color: randomItem(colors), active: i % 5 == 0, due: new Date(), sales: Math.random() * 10000 * trend, expenses: Math.random() * 5000 * trend, downloads: Math.random() * 100000 * trend }); } // return data; } // // get a random item from an array function randomItem(arr) { return arr[Math.floor(Math.random() * arr.length)]; } <template> <div class="container-fluid"> <label> アウトラインモード <input id="outline" type="checkbox" v-model="outlineMode" v-on:change="outlineModeChanged"> </label><br/> <label> カスタムスタイル <input id="style" type="checkbox" v-model="customStyle"> </label><br/> <label> 合計をデータの前に表示 <input id="before" type="checkbox" v-model="ng.totalsBeforeData"> </label><br/> <label> 行フィールドヘッダーを表示 <input id="headers" type="checkbox" v-model="showRowFieldHeaders"> </label><br/> <div class="row"> <div class="col-xs-5"> <wj-pivot-panel :items-source="ng"></wj-pivot-panel> </div> <div class="col-xs-7" :class="customStyle ? 'outline' : ''"> <wj-pivot-grid control="grid" :items-source="ng" :outline-mode="outlineMode" :show-row-field-headers="showRowFieldHeaders"> </wj-pivot-grid> <button class="btn btn-primary" v-on:click="exportToCsv()"> CSVの保存 </button> </div> </div> </div> </template> <script> import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import Vue from 'vue'; import '@grapecity/wijmo.vue2.olap'; import { PivotEngine } from '@grapecity/wijmo.olap'; import { CellRange } from '@grapecity/wijmo.grid'; import { getData } from './data'; let App = Vue.extend({ name: "app", data: function () { return { ng: new PivotEngine({ autoGenerateFields: false, fields: [ { binding: 'country', header: '国' }, { binding: 'product', header: '商品' }, { binding: 'color', header: '色' }, { binding: 'active', header: '有効' }, { binding: 'due', header: '期限' }, { binding: 'sales', header: '売上' }, { binding: 'expenses', header: '費用' }, { binding: 'downloads', header: 'DL数' } ], itemsSource: getData(1000), showRowTotals: 'Subtotals', showColumnTotals: 'None', totalsBeforeData: true, rowFields: ['国', '商品', '色'], valueFields: ['売上', '費用', 'DL数'] }), outlineMode: true, customStyle: true, totalsBeforeData: true, showRowFieldHeaders: true }; }, methods: { outlineModeChanged() { if (this.outlineMode) { this.ng.totalsBeforeData = this.totalsBeforeData = true; } else { this.customStyle = false; } }, exportToCsv() { let grid = this.grid, // exposed with "control" attribute rng = new CellRange(0, 0, grid.rows.length - 1, grid.columns.length - 1), csv = grid.getClipString(rng, true, true, true); exportFile(csv, 'FlexGrid.csv'); } } }); new Vue({ render: h => h(App) }).$mount("#app"); function exportFile(csv, fileName) { let fileType = 'txt/csv;charset=utf-8'; if (navigator.msSaveBlob) { // IE navigator.msSaveBlob(new Blob([csv], { type: fileType }), fileName); } else { let e = document.createElement('a'); e.setAttribute('href', 'data:' + fileType + ',' + encodeURIComponent(csv)); e.setAttribute('download', fileName); e.style.display = 'none'; document.body.appendChild(e); e.click(); document.body.removeChild(e); } } </script> <style> .wj-pivotgrid { max-height: 400px; box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23); } .outline .wj-pivotgrid .wj-cell:not(.wj-state-selected) { border-right: none; border-bottom: none; background: #fff; color: #000; } body { margin-bottom: 24pt; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Grapecity Wijmo OLAP Pivot Grid OutlineMode</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"> </div> </body> </html> // get the raw data export function getData(count) { let countries = ['ドイツ', 'イタリア', '日本', 'イギリス', 'アメリカ'], products = ['ウィジェット', 'ガジェット', 'ツール'], colors = ['赤', '緑', '青', '黄', '紫', '白', '黒', 'マゼンタ'], data = []; for (let i = 0; i < count; i++) { let trend = (i % countries.length + 1) * (i % products.length + 1); data.push({ country: randomItem(countries), product: randomItem(products), color: randomItem(colors), active: i % 5 == 0, due: new Date(), sales: Math.random() * 10000 * trend, expenses: Math.random() * 5000 * trend, downloads: Math.random() * 100000 * trend }); } return data; } // get a random item from an array function randomItem(arr) { return arr[Math.floor(Math.random() * arr.length)]; }