Sort in EJ2 TypeScript Spreadsheet control

4 Jul 202419 minutes to read

Sorting helps arranging the data to a specific order in a selected range of cells. You can use the allowSorting property to enable or disable sorting functionality.

  • The default value for allowSorting property is true.

By default, the sort module is injected internally into Spreadsheet to perform sorting.

Sort by cell value

In the active Spreadsheet, select a range of cells to sort by cell value. The range sort can be done by any of the following ways:

  • Select the sort item in the Ribbon toolbar and choose the ascending or descending item.
  • Right-click the sheet, select the sort item in the context menu and choose the ascending/descending item.

  • Use the sort() method programmatically.

The cell values can be sorted in the following orders:

  • Ascending
  • Descending
  • Ascending is the default order for sorting.

The sort() method with empty arguments will sort the selected range by active cell’s column as sort column in ascending order.

  • The beforeSort event will be triggered before sorting the specified range.
  • The sortComplete event will be triggered after the sort action is completed successfully.

The following code example shows Sort functionality in the Spreadsheet control.

import { Spreadsheet } from '@syncfusion/ej2-spreadsheet';
import { defaultData } from './datasource.ts';

let spreadsheet: Spreadsheet = new Spreadsheet({
    sheets: [{ ranges: [{ dataSource: defaultData }] }],
    allowSorting: true,
    beforeSort: function (args) {
        //code here to handle sorting arguments.
    },
    sortComplete: function (args) {
        spreadsheet.selectRange(args.range);
        // code here.
    },
    dataBound: function () {
        if (spreadsheet.activeSheetIndex === 0) {
            spreadsheet.sort({ containsHeader: true }, 'A1:H11');
        }
    }
});

//Render the initialized Spreadsheet
spreadsheet.appendTo('#spreadsheet');
<!DOCTYPE html>
<html lang="en">

<head>
        <title>EJ2 SpreadSheet</title>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="description" content="Typescript UI Controls" />
        <meta name="author" content="Syncfusion" />
        <link rel="shortcut icon" href="resources/favicon.ico" />
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-base/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-inputs/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-buttons/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-lists/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-navigations/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-popups/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-grids/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-spreadsheet/styles/material.css" rel="stylesheet" />
        <link href="styles.css" rel="stylesheet" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/shim.min.js"></script>
        <script src="system.config.js"></script>
        <script src="es5-datasource.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
       <!--Element which is going to render-->
       <div id='loader'>Loading....</div>
       <div id='container'>
       <div id="spreadsheet"></div>
       </div>
</body>

</html>

Data contains header

You can specify whether the selected range of cells contains header. To specify, you need to set the containsHeader property to true and pass it as sortOption arguments of the sort() method.

  • If the containsHeader property is not set and active cell column’s first cell value type is differed from the second cell value type, the first row data in the range are marked as column headers.

You can also enable or disable this property using beforeSort event arguments,

let spreadsheet: Spreadsheet = new Spreadsheet({

    beforeSort: function (args) {
        args.sortOptions.containsHeader = true;
    }

});

In the custom sort dialog, the Data contains header checkbox is checked on load. Thus, the default value for containsHeader is true in custom sort dialog.

Case sensitive sort

The default sort functionality of Spreadsheet is a case insensitive sorting. When you want to perform sorting with case sensitive, you need to set the caseSensitive property to true and pass it as sortOption arguments of the sort() method.

Case sensitive sorting is applicable only for cells with alphabets. In ascending order sorting with case sensitive enabled, the cells with lower case text will be placed above the cells with upper case text.

  • The default value for the caseSensitive property is false.

You can also enable or disable this property using beforeSort event arguments,

let spreadsheet: Spreadsheet = new Spreadsheet({

    beforeSort: function (args) {
        args.sortOptions.caseSensitive = true;
    }

});

In the custom sort dialog, the Case sensitive checkbox is unchecked on load as the default value is false.

Sort multiple columns

When you want to perform sorting on multiple columns, it can be done by any of the following ways:

  • Select the Custom sort… menu item from the Ribbon toolbar item or context menu item.
  • Use the sort() method programmatically by providing sort criteria.
  • The current sorting functionality supports sorting based on cell values only.

Custom sort dialog

The custom sort dialog helps sorting multiple columns in the selected range by utilizing the rich UI. This dialog will be appeared while choosing the Custom sort… from the Ribbon item or context menu item. By default, sort criteria with the first column name from the selected range will be appeared in the dialog on initial load and it cannot be removed.

You can add multiple criteria using the Add Column button at the bottom of the dialog. Thus, multiple columns can be specified with different sort order. The newly added sort criteria items can be removed using the delete icons at the end of each items.

You can refer to the Data contains header topic to learn more about Data contains header checkbox. To learn more about Case sensitive checkbox, you can refer to Case sensitive sort topic.

Passing sort criteria manually

The multi-column sorting can also be performed manually by passing sort options to the sort() method programmatically. The sortOption have the following arguments:

  • sortDescriptors – Sort criteria collection that holds the collection of field name, sort order, and sortComparer.

  • containsHeader – Boolean argument that specifies whether the range has headers in it.
  • caseSensitive – Boolean argument that specifies whether the range needs to consider case.
  • All the arguments are optional.
  • When a sortDescriptor is specified without field, the field of the first sortDescriptor from the collection will be assigned from active cell’s column name and others will be ignored. Hence, it will act as single column sorting.
import { Spreadsheet, SortDescriptor } from '@syncfusion/ej2-spreadsheet';
import { DataManager } from '@syncfusion/ej2-data';
import { tradeData } from './datasource.ts';

let spreadsheet: Spreadsheet = new Spreadsheet({
    sheets: [{ ranges: [{ dataSource: tradeData }] }],
    allowSorting: true,
    sortComplete: function (args) {
        spreadsheet.selectRange(args.range);
        // code here.
    },
    dataBound: function () {
    let sortDescriptors: SortDescriptor[] = [
        {
            field: 'F',
            order: 'Ascending'
        },
        {
            field: 'E',
            order: 'Ascending'
        },
        {
            field: 'C',
            order: 'Descending'
        }];
        if (spreadsheet.activeSheetIndex === 0) {
            spreadsheet.sort({ sortDescriptors: sortDescriptors, containsHeader: true }, 'A1:H30');
        }
    }
});
//Render the initialized Spreadsheet
spreadsheet.appendTo('#spreadsheet');
<!DOCTYPE html>
<html lang="en">

<head>
        <title>EJ2 SpreadSheet</title>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="description" content="Typescript UI Controls" />
        <meta name="author" content="Syncfusion" />
        <link rel="shortcut icon" href="resources/favicon.ico" />
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-base/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-inputs/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-buttons/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-lists/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-navigations/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-popups/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-grids/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-spreadsheet/styles/material.css" rel="stylesheet" />
        <link href="styles.css" rel="stylesheet" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/shim.min.js"></script>
        <script src="system.config.js"></script>
        <script src="es5-datasource.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
       <!--Element which is going to render-->
       <div id='loader'>Loading....</div>
       <div id='container'>
       <div id="spreadsheet"></div>
       </div>
</body>

</html>

Custom sort comparer

The sortDescriptor holds the sortComparer property, which is a function and it is used to customize the sort comparer for specific sort criteria. Each sortDescriptor can be customized using the custom sort comparer function.

By customizing sort comparer, you can define the sort action as desired.

  • The sortComparer is an optional property of sortDescriptor.

For custom sort comparer example, refer to the [Sort a range by custom list] below.

Sort a range by custom list

You can also define the sorting of cell values based on your own customized personal list. In this article, custom list is achieved using custom sort comparer.

In the following demo, the Trustworthiness column is sorted based on the custom lists Perfect, Sufficient, and Insufficient.

import { Spreadsheet, CellModel } from '@syncfusion/ej2-spreadsheet';
import { DataManager, DataUtil } from '@syncfusion/ej2-data';
import { tradeData } from './datasource.ts';

let spreadsheet: Spreadsheet = new Spreadsheet({
    sheets: [{ ranges: [{ dataSource: new DataManager(tradeData) }] }],
    dataBound: function () {
        if (spreadsheet.activeSheetIndex === 0) {
            spreadsheet.sort({sortDescriptors: { field: 'F',  sortComparer: mySortComparer }, containsHeader: true}, 'A1:H20');
        }
    },
    sortComplete: function (args) {
        spreadsheet.selectRange(args.range);
        // code here.
    }
});

// custom sort comparer to sort based on the custom list.
let customList: string[] = ['Perfect', 'Sufficient', 'Insufficient'];
function mySortComparer(x: CellModel, y: CellModel): number {
    let comparer: Function = DataUtil.fnSort('Ascending');
    return comparer(x ? customList.indexOf(x.value) : x, y ? customList.indexOf(y.value) : y);
};

//Render the initialized Spreadsheet
spreadsheet.appendTo('#spreadsheet');
<!DOCTYPE html>
<html lang="en">

<head>
        <title>EJ2 SpreadSheet</title>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta name="description" content="Typescript UI Controls" />
        <meta name="author" content="Syncfusion" />
        <link rel="shortcut icon" href="resources/favicon.ico" />
        <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-base/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-inputs/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-buttons/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-lists/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-navigations/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-popups/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-grids/styles/material.css" rel="stylesheet" />
        <link href="https://cdn.syncfusion.com/ej2/27.2.2/ej2-spreadsheet/styles/material.css" rel="stylesheet" />
        <link href="styles.css" rel="stylesheet" />
        <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/shim.min.js"></script>
        <script src="system.config.js"></script>
        <script src="es5-datasource.js" type="text/javascript"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
       <!--Element which is going to render-->
       <div id='loader'>Loading....</div>
       <div id='container'>
       <div id="spreadsheet"></div>
       </div>
</body>

</html>

Known error validations

The following errors have been handled for sorting,

  • Out of range validation: When the selected range is not a used range of the active sheet, it is considered as invalid and the out of range alert with the message Select a cell or range inside the used range and try again will be displayed. No sort will be performed if the range is invalid.

  • Empty field validation: When the sort criteria does not have a column selected (empty) in the custom sort dialog, it will become invalid, and an error message Sort criteria column should not be empty will be displayed on OK button click.

  • Duplicate field validation: When the column names of added sort criteria are repeated more than once in the custom sort dialog, it will become invalid and an error message <Column name> is mentioned more than once. Duplicate columns must be removed will be displayed on OK button click.

Limitations

  • Sorting is not supported with formula contained cells.

See Also