スプレッドシート:ソート

FlexSheetは、任意の列でソートできます。SortManagerを使用すると、FlexSheetでソート処理を管理できます。次の例では、SortManagerを使用して、ソート順の指定、ソート列の追加や削除、ソート列の順序の変更を行います。

import 'bootstrap.css'; import '@mescius/wijmo.styles/wijmo.css'; import './styles.css'; import * as wjCore from '@mescius/wijmo'; import * as wjGrid from '@mescius/wijmo.grid'; import * as wjFlexSheet from '@mescius/wijmo.grid.sheet'; import { getData, getCountries, getProducts } from './data'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { let sortSheet = new wjFlexSheet.FlexSheet('#sortSheet'); sortSheet.addBoundSheet('国', getData(50)); sortSheet.deferUpdate(() => { let column = sortSheet.columns.getColumn('countryId'); if (column && !column.dataMap) { column.dataMap = buildDataMap(getCountries()); } column = sortSheet.columns.getColumn('productId'); if (column && !column.dataMap) { column.dataMap = buildDataMap(getProducts()); } column = sortSheet.columns.getColumn('amount'); if (column) { column.format = 'c2'; } }); let sortManager = sortSheet.sortManager; updateSortTable(); onClick('addLevel', addSortLevel); onClick('delLevel', deleteSortLevel); onClick('copyLevel', copySortLevel); onClick('moveup', () => { moveSortLevel(-1); }); onClick('movedown', () => { moveSortLevel(1); }); onClick('commitSort', commitSort); onClick('cancelSort', cancelSort); sortSheet.selectedSheetChanged.addHandler(() => { updateSortTable(); }); sortManager.sortDescriptions.collectionChanged.addHandler(() => { updateSortTable(); }); sortManager.sortDescriptions.currentChanged.addHandler(() => { updateSortTable(); }); function updateSortTable() { let sortTableBody = document.querySelector('#sortTable tbody'), tRows = '', columns = getColumns(), sortItem; for (let index = 0; index < sortManager.sortDescriptions.itemCount; index++) { sortItem = sortManager.sortDescriptions.items[index]; tRows += '<tr class="' + (sortManager.sortDescriptions.currentPosition === index ? 'success"' : '"') + '><td>' + updateColumnSelect(columns, sortItem) + '</td>'; tRows += '<td><select class="form-control" onchange=""><option value="0"' + ((!sortItem || sortItem.ascending) ? ' selected="selected">' : '>') + '昇順</option>' + '<option value="1"' + ((sortItem && !sortItem.ascending) ? ' selected="selected">' : '>') + '降順</option></select></td></tr>'; } sortTableBody.innerHTML = tRows; let sortRows = sortTableBody.querySelectorAll('tr'); for (let rowIndex = 0; rowIndex < sortRows.length; rowIndex++) { sortRows[rowIndex].addEventListener('click', () => { sortManager.sortDescriptions.moveCurrentToPosition(rowIndex); updateActiveRow(); }); } let columnSelects = sortTableBody.querySelectorAll('tr td:first-child select'), ascendingSelects = sortTableBody.querySelectorAll('tr td:last-child select'); for (let sortIndex = 0; sortIndex < columnSelects.length; sortIndex++) { let sortItem = sortManager.sortDescriptions.items[sortIndex]; columnSelects[sortIndex].addEventListener('change', e => { sortItem.columnIndex = e.target.selectedIndex - 1; }); ascendingSelects[sortIndex].addEventListener('change', e => { sortItem.ascending = e.target.selectedIndex === 0; }); } updateMoveButtonState(); } function updateActiveRow() { let sortTableBody = document.querySelector('#sortTable tbody'), sortRows = sortTableBody.querySelectorAll('tr'); removeSuccessClass(sortRows); wjCore.addClass(sortRows[sortManager.sortDescriptions.currentPosition], 'success'); } function removeSuccessClass(sortRows) { for (let rowIndex = 0; rowIndex < sortRows.length; rowIndex++) { wjCore.removeClass(sortRows[rowIndex], 'success'); } } function updateColumnSelect(columns, sortItem) { let colSelect = '<select class="form-control"><option value=-1></option>'; for (let index = 0; index < columns.length; index++) { colSelect += '<option ' + ((sortItem && sortItem.columnIndex === index) ? 'selected="selected" ' : '') + ' value="' + index + '">' + columns[index] + '</option>'; } colSelect += '</select>'; return colSelect; } function updateMoveButtonState() { let moveupBtn = document.querySelector('#moveup'), movedownBtn = document.querySelector('#movedown'); if (sortManager.sortDescriptions.currentPosition === 0) { moveupBtn.setAttribute('disabled', 'true'); } else { moveupBtn.removeAttribute('disabled'); } if (sortManager.sortDescriptions.currentPosition === sortManager.sortDescriptions.itemCount - 1) { movedownBtn.setAttribute('disabled', 'true'); } else { movedownBtn.removeAttribute('disabled'); } } // get the columns with the column header text for the column selection for sort setting. function getColumns() { var columns = [], i = 0; if (sortSheet) { for (; i < sortSheet.columns.length; i++) { columns.push('列 ' + wjFlexSheet.FlexSheet.convertNumberToAlpha(i)); } } return columns; } // commit the sorts function commitSort() { sortManager.commitSort(); } // cancel the sorts function cancelSort() { sortManager.cancelSort(); updateActiveRow(); } // add new sort level function addSortLevel() { sortManager.addSortLevel(); updateActiveRow(); } // delete current sort level function deleteSortLevel() { sortManager.deleteSortLevel(); updateActiveRow(); } // copy a new sort level by current sort level setting. function copySortLevel() { sortManager.copySortLevel(); updateActiveRow(); } // move the sort level function moveSortLevel(offset) { sortManager.moveSortLevel(offset); updateActiveRow(); } // build a data map from a string array using the indices as keys function buildDataMap(items) { let map = []; for (let i = 0; i < items.length; i++) { map.push({ key: i, value: items[i] }); } return new wjGrid.DataMap(map, 'key', 'value'); } ; function onClick(id, fn) { document.querySelector('#' + id).addEventListener('click', fn); } }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>MESCIUS Wijmo FlexSheet Sorting</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.21.5/system.src.js" integrity="sha512-skZbMyvYdNoZfLmiGn5ii6KmklM82rYX2uWctBhzaXPxJgiv4XBwJnFGr5k8s+6tE1pcR1nuTKghozJHyzMcoA==" crossorigin="anonymous"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <div id="sortSheet"></div> <table id="sortTable" class="table table-bordered"> <thead> <tr> <th class="text-center">列</th> <th class="text-center">順序</th> </tr> </thead> <tbody> </tbody> </table> <div class="btn-group"> <button id="addLevel" type="button" class="btn btn-default"> レベルの追加 </button> <button id="delLevel" type="button" class="btn btn-default"> レベルの削除 </button> <button id="copyLevel" type="button" class="btn btn-default"> レベルのコピー </button> </div> <div class="btn-group"> <button id="moveup" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-arrow-up"></span> </button> <button id="movedown" type="button" class="btn btn-default"> <span class="glyphicon glyphicon-arrow-down"></span> </button> </div> <div class="btn-group"> <button id="commitSort" type="button" class="btn btn-default">OK</button> <button id="cancelSort" type="button" class="btn btn-default">キャンセル</button> </div> </div> </body> </html>
let countries = ['アメリカ', 'ドイツ', 'イギリス', '日本', 'イタリア', 'ギリシャ'], products = ['ウィジェット', 'ガジェット', 'ツール']; export function getData(count) { let data = [], i = 0, countryId, productId; for (; i < count; i++) { countryId = Math.floor(Math.random() * countries.length); productId = Math.floor(Math.random() * products.length); data.push({ id: i, countryId: countryId, productId: productId, date: new Date(2014, i % 12, i % 28), amount: Math.random() * 10000, active: i % 4 === 0 }); } return data; } export function getCountries() { return countries; } export function getProducts() { return products; }
.wj-flexsheet { height: 400px; margin: 6px 0; }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { 'jszip': 'npm:jszip/dist/jszip.js', '@mescius/wijmo': 'npm:@mescius/wijmo/index.js', '@mescius/wijmo.input': 'npm:@mescius/wijmo.input/index.js', '@mescius/wijmo.styles': 'npm:@mescius/wijmo.styles', '@mescius/wijmo.cultures': 'npm:@mescius/wijmo.cultures', '@mescius/wijmo.chart': 'npm:@mescius/wijmo.chart/index.js', '@mescius/wijmo.chart.analytics': 'npm:@mescius/wijmo.chart.analytics/index.js', '@mescius/wijmo.chart.animation': 'npm:@mescius/wijmo.chart.animation/index.js', '@mescius/wijmo.chart.annotation': 'npm:@mescius/wijmo.chart.annotation/index.js', '@mescius/wijmo.chart.finance': 'npm:@mescius/wijmo.chart.finance/index.js', '@mescius/wijmo.chart.finance.analytics': 'npm:@mescius/wijmo.chart.finance.analytics/index.js', '@mescius/wijmo.chart.hierarchical': 'npm:@mescius/wijmo.chart.hierarchical/index.js', '@mescius/wijmo.chart.interaction': 'npm:@mescius/wijmo.chart.interaction/index.js', '@mescius/wijmo.chart.radar': 'npm:@mescius/wijmo.chart.radar/index.js', '@mescius/wijmo.chart.render': 'npm:@mescius/wijmo.chart.render/index.js', '@mescius/wijmo.chart.webgl': 'npm:@mescius/wijmo.chart.webgl/index.js', '@mescius/wijmo.chart.map': 'npm:@mescius/wijmo.chart.map/index.js', '@mescius/wijmo.gauge': 'npm:@mescius/wijmo.gauge/index.js', '@mescius/wijmo.grid': 'npm:@mescius/wijmo.grid/index.js', '@mescius/wijmo.grid.detail': 'npm:@mescius/wijmo.grid.detail/index.js', '@mescius/wijmo.grid.filter': 'npm:@mescius/wijmo.grid.filter/index.js', '@mescius/wijmo.grid.search': 'npm:@mescius/wijmo.grid.search/index.js', '@mescius/wijmo.grid.grouppanel': 'npm:@mescius/wijmo.grid.grouppanel/index.js', '@mescius/wijmo.grid.multirow': 'npm:@mescius/wijmo.grid.multirow/index.js', '@mescius/wijmo.grid.transposed': 'npm:@mescius/wijmo.grid.transposed/index.js', '@mescius/wijmo.grid.transposedmultirow': 'npm:@mescius/wijmo.grid.transposedmultirow/index.js', '@mescius/wijmo.grid.pdf': 'npm:@mescius/wijmo.grid.pdf/index.js', '@mescius/wijmo.grid.sheet': 'npm:@mescius/wijmo.grid.sheet/index.js', '@mescius/wijmo.grid.xlsx': 'npm:@mescius/wijmo.grid.xlsx/index.js', '@mescius/wijmo.grid.selector': 'npm:@mescius/wijmo.grid.selector/index.js', '@mescius/wijmo.grid.cellmaker': 'npm:@mescius/wijmo.grid.cellmaker/index.js', '@mescius/wijmo.nav': 'npm:@mescius/wijmo.nav/index.js', '@mescius/wijmo.odata': 'npm:@mescius/wijmo.odata/index.js', '@mescius/wijmo.olap': 'npm:@mescius/wijmo.olap/index.js', '@mescius/wijmo.rest': 'npm:@mescius/wijmo.rest/index.js', '@mescius/wijmo.pdf': 'npm:@mescius/wijmo.pdf/index.js', '@mescius/wijmo.pdf.security': 'npm:@mescius/wijmo.pdf.security/index.js', '@mescius/wijmo.viewer': 'npm:@mescius/wijmo.viewer/index.js', '@mescius/wijmo.xlsx': 'npm:@mescius/wijmo.xlsx/index.js', '@mescius/wijmo.undo': 'npm:@mescius/wijmo.undo/index.js', '@mescius/wijmo.interop.grid': 'npm:@mescius/wijmo.interop.grid/index.js', '@mescius/wijmo.touch': 'npm:@mescius/wijmo.touch/index.js', '@mescius/wijmo.cloud': 'npm:@mescius/wijmo.cloud/index.js', '@mescius/wijmo.barcode': 'npm:@mescius/wijmo.barcode/index.js', '@mescius/wijmo.barcode.common': 'npm:@mescius/wijmo.barcode.common/index.js', '@mescius/wijmo.barcode.composite': 'npm:@mescius/wijmo.barcode.composite/index.js', '@mescius/wijmo.barcode.specialized': 'npm:@mescius/wijmo.barcode.specialized/index.js', 'jszip': 'npm:jszip/dist/jszip.js', 'bootstrap.css': 'npm:bootstrap/dist/css/bootstrap.min.css', 'css': 'npm:systemjs-plugin-css/css.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' }, "node_modules": { defaultExtension: 'js' }, } }); })(this);