Introducing wijmo.olap
The wijmo.olap module contains controls that allow you to add Excel-like pivot table and pivot chart features to your applications. To use it, follow these steps:
- Add references to the wijmo and wijmo.olap modules to the page.
- Add a PivotPanel control to the page.
- Add one or more PivotGrid and PivotChart controls to the page, and connect them to the PivotPanel by setting their itemsSource property to the PivotPanel control.
- Set the PivotPanel's itemsSource property to an array containing the raw data you want to analyze.
- Optionally add code to print, export, save and load views and view definitions.
That's all. The PivotPanel will show a list of the fields available, and users will be able to drag fields between summary areas to generate data summaries (AKA "views"). Users may also configure the fields by setting their headers, summary functions, filters, and formats.
Users may analyze the data and print the results, export the results to XLSX or PDF, and save view definitions that can be re-used later.
Here is a simple example:
Add a PivotPanel and a PivotGrid to the page
The PivotPanel control is similar to Excel's "field list" window that is associated with pivot tables and charts.
- Add fields to the view by dragging or using the checkboxes.
- Remove fields from the view by dragging them back to the top area or by using their context menu.
- Configure fields using their context menu. You may modify their header, summary function, and format. Note that the format is used when grouping the data, so you can group data by day, month, quarter or year by changing the format of the date fields for example.
The PivotGrid control extends the FlexGrid to support pivoting features including custom cell merging, hierarchical row and column groups, and a custom context menu that allows users to configure the pivot fields and to drill-down into the data items that were used in the computation of specific summary cells.
<div class="mdl-grid" id="theView">
<div class="mdl-cell mdl-cell--4-col">
<wj-pivot-panel
control="thePanel"
items-source="rawData"
initialized="initPanel(s,e)">
</wj-pivot-panel>
</div>
<div class="mdl-cell mdl-cell--8-col">
<wj-pivot-grid
control="pivotGrid"
items-source="thePanel">
</wj-pivot-grid>
</div>
</div>
// initialize the view definition
$scope.initPanel = function (sender, e) {
var ng = sender.engine;
ng.rowFields.push('Product', 'Country');
ng.valueFields.push('Sales', 'Downloads');
ng.showRowTotals = wijmo.olap.ShowTotals.Subtotals;
ng.showColTotals = wijmo.olap.ShowTotals.Subtotals;
}
Use the viewDefinition property to save and restore view definitions. For example:
Or build a list of pre-defined views for the user to pick from. For example:
<button
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect"
ng-click="saveView()">
Save View
</button>
<button
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect"
ng-click="loadView()">
Load View
</button>
<ul>
<li ng-repeat="view in viewDefs">
<a href="#theView" index="$index" ng-click="loadView(view.def)">
{{ view.name }}
</a>
</li>
</ul>
// save/restore view definitions
$scope.saveView = function () {
if ($scope.thePanel.isViewDefined) {
localStorage.viewDefinition = $scope.thePanel.viewDefinition;
}
}
$scope.loadView = function (def) {
if (def) {
// load pre-defined view (against specific dataset)
$scope.rawData = $scope.dataSets[3].value;
$scope.thePanel.viewDefinition = def;
} else {
// load view from localStorage (whatever the user saved)
$scope.thePanel.viewDefinition = localStorage.viewDefinition;
}
}
Configure the PivotPanel properties
The PivotPanel control has properties that allow you to customize the view. Use the controls below to modify the value of some properties and see their effect:
- Dataset
-
- Row totals
-
- Column totals
-
- Show Zeros
- Totals Before Data
<dl class="dl-horizontal">
<dt>Dataset</dt>
<dd>
<wj-combo-box
items-source="dataSets"
display-member-path="name"
selected-value-path="value"
selected-value="rawData">
</wj-combo-box>
</dd>
<dt>Row totals</dt>
<dd>
<wj-combo-box
items-source="showTotals"
display-member-path="name"
selected-value-path="value"
selected-value="thePanel.engine.showRowTotals">
</wj-combo-box>
</dd>
<dt>Column totals</dt>
<dd>
<wj-combo-box
items-source="showTotals"
display-member-path="name"
selected-value-path="value"
selected-value="thePanel.engine.showColumnTotals">
</wj-combo-box>
</dd>
<dt>Show Zeros</dt>
<dd>
<input ng-model="thePanel.engine.showZeros" type="checkbox" />
</dd>
</dl>
// no code required!
Show the results in a PivotChart
The PivotChart control provides a graphical visualization of the results. It is similar to Excel's pivot charts, including support for multiple chart types and hierarchical axes.
To use the PivotChart control, connect it to a PivotPanel using the itemsSource property:
Please create a view in order to see the chart.
- Chart Type
-
- Show Legend
-
- Show Title
<div ng-show="thePanel.isViewDefined">
<dl class="dl-horizontal">
<dt>Chart Type</dt>
<dd>
<wj-combo-box
items-source="chartTypes"
display-member-path="name"
selected-value-path="value"
selected-value="theChart.chartType">
</wj-combo-box>
</dd>
<dt>Show Legend</dt>
<dd>
<wj-combo-box
items-source="legendVisibility"
display-member-path="name"
selected-value-path="value"
selected-value="theChart.showLegend">
</wj-combo-box>
</dd>
<dt>Show Title</dt>
<dd>
<input type="checkbox" checked="checked" ng-model="theChart.showTitle">
</dd>
</dl>
<wj-pivot-chart
control="theChart"
show-legend="Auto"
items-source="thePanel">
</wj-pivot-chart>
</div>
<div ng-hide="thePanel.isViewDefined">
<p>
Please create a view in order to see the chart.</p>
</div>
// no code required!
View and edit the source data
The pivot view is live. If you edit any of the {{ rawData.items.length | number }} items, the pivot view will be updated automatically. (This grid is read-only because it is bound to a read-only data source, but you can still apply filters to the raw data.)
<wj-flex-grid
style="border:none"
control="rawGrid"
items-source="rawData"
is-read-only="{{ rawData.tableName != null }}"
show-selected-headers="All">
<wj-flex-grid-filter></wj-flex-grid-filter>
</wj-flex-grid>
// no code required!
Export the results to Excel
The PivotGrid control extends the FlexGrid, so you can export it to any of the formats supported by the extension modules provided with the FlexGrid. The list of supported formats includes XLSX, CSV, and PDF.
For example, the button below creates an Excel file with two sheets: the current view and the raw data (if the data has 10,000 items or less):
<button
class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect"
ng-click="export()">
Export to XLSX
</button>
$scope.export = function () {
var ng = $scope.thePanel.engine;
// create book with current view
var book = wijmo.grid.xlsx.FlexGridXlsxConverter.save($scope.pivotGrid, {
includeColumnHeaders: true,
includeRowHeaders: true
});
book.sheets[0].name = 'Main View';
addTitleCell(book.sheets[0], getViewTitle(ng));
// add sheet with raw data
if ($scope.rawGrid.rows.length <= 10000) {
var raw = wijmo.grid.xlsx.FlexGridXlsxConverter.save($scope.rawGrid, {
includeColumnHeaders: true,
includeRowHeaders: false
});
raw.sheets[0].name = 'Raw Data';
book.sheets.push(raw.sheets[0]);
}
// save the book
book.save('wijmo.olap.xlsx');
}
Customize the PivotGrid cells
The PivotGrid control extends the FlexGrid, so you can customize the display of the grid cells using the formatItem event and modifying the content of each cell with complete flexibility.
For example, the PivotGrid below uses colors and icons similar to the ones in Excel's icon sets to show how sales changed from quarter to quarter:
<wj-pivot-grid
items-source="ngFmt"
format-item="formatItem(s,e)"
style="border:none">
</wj-pivot-grid>
$scope.ngFmt = new wijmo.olap.PivotEngine({
autoGenerateFields: false,
itemsSource: getSimpleDataSet(10000),
showColumnTotals: wijmo.olap.ShowTotals.GrandTotals,
showRowTotals: wijmo.olap.ShowTotals.None,
fields: [
{ binding: 'product', header: 'Product' },
{ binding: 'date', header: 'Date', format: 'yyyy \"Q\"q' },
{ binding: 'sales', header: 'Sales', format: 'n0' },
{ binding: 'sales', header: 'Diff', format: 'p0', showAs: wijmo.olap.ShowAs.DiffRowPct }
]
});
$scope.ngFmt.rowFields.push('Date');
$scope.ngFmt.columnFields.push('Product');
$scope.ngFmt.valueFields.push('Sales', 'Diff');
$scope.formatItem = function (s, e) {
if (e.panel == s.cells && e.col % 2 == 1) {
var value = s.getCellData(e.row, e.col),
color = '#d8b400',
glyph = 'circle';
if (value != null) {
if (value < 0) { // negative variation
color = '#9f0000';
glyph = 'down';
} else if (value > 0.05) { // positive variation
color = '#4c8f00';
glyph = 'down';
}
e.cell.style.color = color;
e.cell.innerHTML += ' <span style="font-size:120%" class="wj-glyph-' + glyph + '"></span>';
}
}
}
Notice that in this example we only have one pre-defined view, and don't need a PivotPanel at all. Instead, the code creates a PivotEngine directly and uses that as the grid's itemsSource.