TableSheet can support the multiple Excel-like filters including Text, Number and Date conditions.
In order to improve the performance of opening filter dialogs when there is a large amount of data, TableSheet provides an option to create a specific field filter indexes cache.
For some cases, users may not need the checklist or some parts of the filter dialog, so TableSheet provides several options in columns to control the visibility of each part in the TableSheet filter dialog.
If the allowSort, allowFilterByValue and allowFilterByList are all false, the filter button in column header is invisible.
/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
<template>
<div class="sample-tutorial">
<gc-spread-sheets
class="sample-spreadsheets"
@workbookInitialized="init"
>
</gc-spread-sheets>
<div id="options-container" class="options-container">
<label for="dataRows">Row Count: </label>
<select id="dataRows" v-model="rowCount">
<option value="1000" selected="selected">1000</option>
<option value="3000">3000</option>
<option value="10000">10000</option>
<option value="30000">30000</option>
<option value="100000">100000</option>
<option value="300000">300000</option>
<option value="1000000">1000000</option>
</select>
<br>
<fieldset>
<legend>Create Filter Indexes</legend>
<input type="checkbox" id="createIdIndexes" v-model="createIDIndexes"/>
<label for="createIdIndexes">Create ID Indexes</label>
<br>
<input type="checkbox" id="createBirthIndexes" v-model="createBirthIndexes"/>
<label for="createBirthIndexes">Create Birthday Indexes</label>
<br>
</fieldset>
<fieldset>
<legend>ID Column Filter Dialog Options</legend>
<input type="checkbox" id="sortByValue_id" v-model="sortByValue_id"/>
<label for="sortByValue_id">Allow Sort</label>
<br>
<input type="checkbox" id="filterByValue_id" v-model="filterByValue_id"/>
<label for="filterByValue_id">Allow Filter By Value</label>
<br>
<input type="checkbox" id="listFilterArea_id" v-model="listFilterArea_id"/>
<label for="listFilterArea_id">Allow Filter By List</label>
<br>
</fieldset>
<fieldset>
<legend>Birthday Column Filter Dialog Options</legend>
<input type="checkbox" id="sortByValue_birthday" v-model="sortByValue_birthday"/>
<label for="sortByValue_birthday">Allow Sort</label>
<br>
<input type="checkbox" id="filterByValue_birthday" v-model="filterByValue_birthday"/>
<label for="filterByValue_birthday">Allow Filter By Value</label>
<br>
<input type="checkbox" id="listFilterArea_birthday" v-model="listFilterArea_birthday"/>
<label for="listFilterArea_birthday">Allow Filter By List</label>
<br>
</fieldset>
<input type="button" style="margin-left: 30px; margin-top: 10px;width:200px;" id="setDataSource" value="Set DataSource" @click="initSpread"/>
<fieldset style="heighy:155px;">
<legend>Performance</legend>
<textarea id="showEventArgs" style="width: 236px;height:135px;" cols="64" rows="15" v-model="showEventArgs"></textarea>
</fieldset>
</div>
</div>
</template>
<script>
import Vue from "vue";
import "@mescius/spread-sheets-vue";
import GC from "@mescius/spread-sheets";
import "@mescius/spread-sheets-tablesheet";
import "./styles.css";
let App = Vue.extend({
name: "app",
data: function() {
return {
spread: null,
tablesheet: null,
rowCount: 1000,
createIDIndexes: true,
createBirthIndexes: true,
sortByValue_id: true,
filterByValue_id: true,
listFilterArea_id: true,
sortByValue_birthday: true,
filterByValue_birthday: true,
listFilterArea_birthday: true,
showEventArgs: ""
}
},
methods: {
init: function(spread){
this.spread = spread;
this.initSpread();
},
initSpread: function () {
var _this = this;
var spread = _this.spread;
spread.suspendPaint();
//1. init a sheet
spread.clearSheets();
spread.clearSheetTabs();
var sheet = spread.addSheetTab(0, "TableSheet1", GC.Spread.Sheets.SheetType.tableSheet);
var data = generateData(+_this.rowCount);
var timeBeforeCreate = new Date();
var dataManager = spread.dataManager();
var employeeTable = dataManager.addTable("employeeTable", {
data: data.employees,
schema: {
columns: {
id: {
indexed: _this.createIDIndexes
},
birth: {
indexed: _this.createBirthIndexes
}
}
}
});
var departmentTable = dataManager.addTable("departmentTable", {
data: data.departments
});
dataManager.addRelationship(employeeTable, "dept", "department", departmentTable, "dept_no", "employees");
dataManager.addRelationship(departmentTable, "leader_id", "manager", employeeTable, "id", "a");
spread.resumePaint();
var numericStyle = new GC.Spread.Sheets.Style();
numericStyle.formatter = "$ #,##0.00";
var formatStringStyle = new GC.Spread.Sheets.Style();
formatStringStyle.formatter = 'yyyy-mm-dd';
var visibleInfo_id = {};
if (!_this.sortByValue_id) {
visibleInfo_id.sortByValue_id = false;
}
if (!_this.filterByValue_id) {
visibleInfo_id.filterByValue_id = false;
}
if (!_this.listFilterArea_id) {
visibleInfo_id.listFilterArea_id = false;
}
var visibleInfo_birthday = {};
if (!_this.sortByValue_birthday) {
visibleInfo_birthday.sortByValue_birthday = false;
}
if (!_this.filterByValue_birthday) {
visibleInfo_birthday.filterByValue_birthday = false;
}
if (!_this.listFilterArea_birthday) {
visibleInfo_birthday.listFilterArea_birthday = false;
}
var cols = [
{ value: 'id', caption: 'ID', allowSort: visibleInfo_id.sortByValue_id, allowFilterByValue: visibleInfo_id.filterByValue_id, allowFilterByList: visibleInfo_id.listFilterArea_id},
{ value: 'firstName', caption: 'First Name', width: 100},
{ value: 'lastName', caption: 'Last Name', width: 100},
{ value: 'birth', caption: 'Birthday', width: 100, style: formatStringStyle, allowSort: visibleInfo_birthday.sortByValue_birthday, allowFilterByValue: visibleInfo_birthday.filterByValue_birthday, allowFilterByList: visibleInfo_birthday.listFilterArea_birthday},
{ value: 'state', caption: 'State', width: 100},
{ value: 'dept', caption: 'Department No', width: 130},
{ value: 'title', caption: 'Title', width: 120},
{ value: 'salary', caption: 'Salary', style: numericStyle, width: 100},
];
var employeeView = employeeTable.addView("employeeView", cols, undefined);
employeeView.fetch().then(function (args) {
sheet.suspendPaint();
sheet.setDataView(employeeView);
sheet.resumePaint();
var timeGap = new Date() - timeBeforeCreate;
_this.showEventArgs = ("Fetch data and paint - " + (timeGap) + " ms");
});
initMultiFilterSample(spread);
},
}
});
function initMultiFilterSample (spread) {
spread.suspendPaint();
var dataManager = spread.dataManager();
var table = dataManager.addTable("CourseTable", {
data: [
{ Course: "Calculus", Term: 1, Credit: 5, Score: 80, Teacher: "Nancy Feehafer" },
{ Course: "P.E.", Term: 1, Credit: 3.5, Score: 85, Teacher: "Andrew Cencini" },
{ Course: "Political Economics", Term: 1, Credit: 3.5, Score: 95, Teacher: "Jan Kotas" },
{ Course: "Basic of Computer", Term: 1, Credit: 2, Score: 85, Teacher: "Steven Thorpe" },
{ Course: "Micro-Economics", Term: 1, Credit: 4, Score: 62, Teacher: "Jan Kotas" },
{ Course: "Linear Algebra", Term: 2, Credit: 5, Score: 73, Teacher: "Nancy Feehafer" },
{ Course: "Accounting", Term: 2, Credit: 3.5, Score: 86, Teacher: "Nancy Feehafer" },
{ Course: "Statistics", Term: 2, Credit: 5, Score: 85, Teacher: "Robert Zare" },
{ Course: "Marketing", Term: 2, Credit: 4, Score: 70, Teacher: "Laura Giussani" }
],
schema: {
type: 'json'
}
});
var sheet = spread.addSheetTab(1, "Course", GC.Spread.Sheets.SheetType.tableSheet);
table.fetch().then(function () {
var myView = table.addView("CourseTable", [
{ value: "Course", width: 130 },
{ value: "Term", width: 100 },
{ value: "Credit", width: 100 },
{ value: "Score", width: 100 },
{ value: "Teacher", width: 120 },
]);
spread.suspendPaint();
sheet.setDataView(myView);
spread.resumePaint();
});
initMultiFilterHierarchySample(spread, dataManager);
spread.resumePaint();
}
function initMultiFilterHierarchySample(spread, dataManager) {
var table = dataManager.addTable("Table", {
remote: {
read: {
url: getBaseApiUrl() + "/Hierarchy_Formula"
}
},
schema: {
hierarchy: {
type: 'Parent',
column: 'parent',
summaryFields: {
'budget':'=SUM(CHILDREN(1,"budget"))'
}
},
columns: {
id: {
isPrimaryKey: true,
},
},
}
});
var sheet = spread.addSheetTab(2, "Budget", GC.Spread.Sheets.SheetType.tableSheet);
sheet.options.allowAddNew = false;
table.fetch().then(function () {
var myView = table.addView("myView", [
{ value: '=CONCAT([@department]," (L",LEVEL(),"-",LEVELROWNUMBER(),")")', caption: 'Department', width: 265, outlineColumn: true },
{ value: "budget", width: 100, caption: 'Budget' },
{ value: '=IF(LEVEL()=0,"",[@budget]/PARENT(1,"budget"))', width: 120, caption: 'Percentage', style: { formatter: '0.00%' } },
{ value: "location", width: 100, caption: 'Location' },
{ value: "phone", width: 150, caption: 'Phone' },
{ value: "country", width: 100, caption: 'Country' },
]);
spread.suspendPaint();
sheet.setDataView(myView);
spread.resumePaint();
});
}
function getBaseApiUrl() {
return window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api';
}
function randomFromList(list) {
return list[~~(Math.random() * list.length)];
}
function generateData(itemCount) {
var data = {employees:[], departments: departments};
var states = ["Texas", "New York", "Florida", "Washington", "Ohio"];
var department_id = ["D001", "D002", "D003", "D004", "D005", "D006", "D007", "D008", "D009"];
var title = ["Senior Engineer", "Staff", "Engineer", "Senior Staff", "Assistant Engineer", "Technique Leader", "Manager"];
for (var i = 0; i < itemCount; i++) {
var date = new Date(parseInt(Math.random() * 12052666) * 24 * 3600); //The timestamp
date.setHours(0,0,0,0);
var item = {
id: i + 1,
firstName: randomFromList(firstNames),
lastName: randomFromList(lastNames),
birth: date,
state: randomFromList(states),
dept: i < 9 ? department_id[i] : randomFromList(department_id),
title: i < 9 ? "Manager" : randomFromList(title),
salary: 3000 + parseInt(Math.random() * 100) * 500,
};
data.employees.push(item);
}
return data;
}
new Vue({
render: (h) => h(App),
}).$mount("#app");
</script>
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/vue/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<!-- SystemJS -->
<script src="$DEMOROOT$/en/vue/node_modules/systemjs/dist/system.src.js"></script>
<script src="$DEMOROOT$/spread/source/data/departments.js" type="text/javascript"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('./src/app.vue');
System.import('$DEMOROOT$/en/lib/vue/license.js');
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
fieldset {
padding: 6px;
margin: 0;
margin-top: 10px;
}
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
.sample-spreadsheets {
width: calc(100% - 280px);
height: 100%;
overflow: hidden;
float: left;
}
.options-container {
float: right;
width: 280px;
padding: 12px;
height: 100%;
box-sizing: border-box;
background: #fbfbfb;
overflow: auto;
}
fieldset span,
fieldset input,
fieldset select {
display: inline-block;
text-align: left;
}
fieldset input[type=text] {
width: calc(100% - 58px);
}
fieldset input[type=button] {
width: 100%;
text-align: center;
}
fieldset select {
width: calc(100% - 50px);
}
.field-line {
margin-top: 4px;
}
.field-inline {
display: inline-block;
vertical-align: middle;
}
fieldset label.field-inline {
width: 100px;
}
fieldset input.field-inline {
width: calc(100% - 100px - 12px);
}
.required {
color: red;
font-weight: bold;
}
#fields {
display: none;
}
#fields.show {
display: block;
}
(function (global) {
System.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true
},
meta: {
'*.css': { loader: 'css' },
'*.vue': { loader: 'vue-loader' }
},
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
'@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js',
'@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js',
'@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js',
'@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js',
'jszip': 'npm:jszip/dist/jszip.js',
'css': 'npm:systemjs-plugin-css/css.js',
'vue': 'npm:vue/dist/vue.min.js',
'vue-loader': 'npm:systemjs-vue-browser/index.js',
'tiny-emitter': 'npm:tiny-emitter/index.js',
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
src: {
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
},
"node_modules": {
defaultExtension: 'js'
}
}
});
})(this);