/*
    *
    * Wijmo Library 5.20173.409
    * http://wijmo.com/
    *
    * Copyright(c) GrapeCity, Inc.  All rights reserved.
    *
    * Licensed under the GrapeCity Commercial License.
    * sales@wijmo.com
    * wijmo.com/products/wijmo-5/license/
    *
    */
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet_1) {
            'use strict';
            /*
             * Defines the CalcEngine class.
             *
             * It deals with the calculation for the flexsheet control.
             */
            var _CalcEngine = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:CalcEngine class.
                 *
                 * @param owner The @see: FlexSheet control that the CalcEngine works for.
                 */
                function _CalcEngine(owner) {
                    this._expressionCache = {};
                    this._idChars = '$:!';
                    this._functionTable = {};
                    this._cacheSize = 0;
                    this._tableRefStart = false;
                    /*
                     * Occurs when the @see:_CalcEngine meets the unknown formula.
                     */
                    this.unknownFunction = new wijmo.Event();
                    this._owner = owner;
                    this._buildSymbolTable();
                    this._registerAggregateFunction();
                    this._registerMathFunction();
                    this._registerLogicalFunction();
                    this._registerTextFunction();
                    this._registerDateFunction();
                    this._registLookUpReferenceFunction();
                    this._registFinacialFunction();
                }
                /*
                 * Raises the unknownFunction event.
                 */
                _CalcEngine.prototype.onUnknownFunction = function (funcName, params) {
                    var paramsList, eventArgs;
                    if (params && params.length > 0) {
                        paramsList = [];
                        for (var i = 0; i < params.length; i++) {
                            paramsList[i] = params[i].evaluate(this._rowIndex, this._columnIndex);
                        }
                    }
                    eventArgs = new sheet_1.UnknownFunctionEventArgs(funcName, paramsList);
                    this.unknownFunction.raise(this, eventArgs);
                    if (eventArgs.value != null) {
                        return new sheet_1._Expression(eventArgs.value);
                    }
                    throw 'The function "' + funcName + '"' + ' has not supported in FlexSheet yet.';
                };
                /*
                 * Evaluates an expression.
                 *
                 * @param expression the expression need to be evaluated to value.
                 * @param format the format string used to convert raw values into display.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 */
                _CalcEngine.prototype.evaluate = function (expression, format, sheet, rowIndex, columnIndex) {
                    var expr, result;
                    try {
                        if (expression && expression.length > 1 && expression[0] === '=') {
                            this._containsCellRef = false;
                            this._rowIndex = rowIndex;
                            this._columnIndex = columnIndex;
                            expr = this._checkCache(expression);
                            result = expr.evaluate(rowIndex, columnIndex, sheet);
                            while (result instanceof sheet_1._Expression) {
                                result = result.evaluate(rowIndex, columnIndex, sheet);
                            }
                            if (format && wijmo.isPrimitive(result)) {
                                return wijmo.Globalize.format(result, format);
                            }
                            return result;
                        }
                        return expression ? expression : '';
                    }
                    catch (e) {
                        return "Error: " + e;
                    }
                };
                /*
                 * Add a custom function to the @see:_CalcEngine.
                 *
                 * @param name the name of the custom function, the function name should be lower case.
                 * @param func the custom function.
                 * @param minParamsCount the minimum count of the parameter that the function need.
                 * @param maxParamsCount the maximum count of the parameter that the function need.
                 *        If the count of the parameters in the custom function is arbitrary, the
                 *        minParamsCount and maxParamsCount should be set to null.
                 */
                _CalcEngine.prototype.addCustomFunction = function (name, func, minParamsCount, maxParamsCount) {
                    var self = this;
                    name = name.toLowerCase();
                    this._functionTable[name] = new _FunctionDefinition(function (params) {
                        var param, paramsList = [];
                        if (params.length > 0) {
                            for (var i = 0; i < params.length; i++) {
                                param = params[i];
                                if (param instanceof sheet_1._CellRangeExpression) {
                                    paramsList[i] = param.cells;
                                }
                                else {
                                    paramsList[i] = param.evaluate(self._rowIndex, self._columnIndex);
                                }
                            }
                        }
                        return func.apply(self, paramsList);
                    }, maxParamsCount, minParamsCount);
                };
                /*
                 * Add a custom function to the @see:_CalcEngine.
                 *
                 * @param name the name of the custom function, the function name should be lower case.
                 * @param func the custom function.
                 * @param minParamsCount the minimum count of the parameter that the function need.
                 * @param maxParamsCount the maximum count of the parameter that the function need.
                 *        If the count of the parameters in the custom function is arbitrary, the
                 *        minParamsCount and maxParamsCount should be set to null.
                 */
                _CalcEngine.prototype.addFunction = function (name, func, minParamsCount, maxParamsCount) {
                    var self = this;
                    name = name.toLowerCase();
                    this._functionTable[name] = new _FunctionDefinition(function (params) {
                        var param, paramsList = [];
                        if (params.length > 0) {
                            for (var i = 0; i < params.length; i++) {
                                param = params[i];
                                if (param instanceof sheet_1._CellRangeExpression) {
                                    paramsList[i] = param.getValuseWithTwoDimensions();
                                }
                                else {
                                    paramsList[i] = [[param.evaluate(self._rowIndex, self._columnIndex)]];
                                }
                            }
                        }
                        return func.apply(self, paramsList);
                    }, maxParamsCount, minParamsCount);
                };
                // Clear the expression cache.
                _CalcEngine.prototype._clearExpressionCache = function () {
                    this._expressionCache = null;
                    this._expressionCache = {};
                    this._cacheSize = 0;
                };
                // Parse the string expression to an Expression instance that can be evaluated to value.
                _CalcEngine.prototype._parse = function (expression) {
                    this._expression = expression;
                    this._expressLength = expression ? expression.length : 0;
                    this._pointer = 0;
                    // skip leading equals sign
                    if (this._expressLength > 0 && this._expression[0] === '=') {
                        this._pointer++;
                    }
                    return this._parseExpression();
                };
                // Build static token table.
                _CalcEngine.prototype._buildSymbolTable = function () {
                    if (!this._tokenTable) {
                        this._tokenTable = {};
                        this._addToken('+', _TokenID.ADD, _TokenType.ADDSUB);
                        this._addToken('-', _TokenID.SUB, _TokenType.ADDSUB);
                        this._addToken('(', _TokenID.OPEN, _TokenType.GROUP);
                        this._addToken(')', _TokenID.CLOSE, _TokenType.GROUP);
                        this._addToken('*', _TokenID.MUL, _TokenType.MULDIV);
                        this._addToken(',', _TokenID.COMMA, _TokenType.GROUP);
                        this._addToken('.', _TokenID.PERIOD, _TokenType.GROUP);
                        this._addToken('/', _TokenID.DIV, _TokenType.MULDIV);
                        this._addToken('\\', _TokenID.DIVINT, _TokenType.MULDIV);
                        this._addToken('=', _TokenID.EQ, _TokenType.COMPARE);
                        this._addToken('>', _TokenID.GT, _TokenType.COMPARE);
                        this._addToken('<', _TokenID.LT, _TokenType.COMPARE);
                        this._addToken('^', _TokenID.POWER, _TokenType.POWER);
                        this._addToken("<>", _TokenID.NE, _TokenType.COMPARE);
                        this._addToken(">=", _TokenID.GE, _TokenType.COMPARE);
                        this._addToken("<=", _TokenID.LE, _TokenType.COMPARE);
                        this._addToken('&', _TokenID.CONCAT, _TokenType.CONCAT);
                        this._addToken('[', _TokenID.OPEN, _TokenType.SQUAREBRACKETS);
                        this._addToken(']', _TokenID.CLOSE, _TokenType.SQUAREBRACKETS);
                    }
                };
                // Register the aggregate function for the CalcEngine.
                _CalcEngine.prototype._registerAggregateFunction = function () {
                    var self = this;
                    self._functionTable['sum'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.Sum, params, sheet);
                    });
                    self._functionTable['average'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.Avg, params, sheet);
                    });
                    self._functionTable['max'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.Max, params, sheet);
                    });
                    self._functionTable['min'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.Min, params, sheet);
                    });
                    self._functionTable['var'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.Var, params, sheet);
                    });
                    self._functionTable['varp'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.VarPop, params, sheet);
                    });
                    self._functionTable['stdev'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.Std, params, sheet);
                    });
                    self._functionTable['stdevp'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getAggregateResult(wijmo.Aggregate.StdPop, params, sheet);
                    });
                    self._functionTable['count'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.Count, params, sheet);
                    });
                    self._functionTable['counta'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.CountA, params, sheet);
                    });
                    self._functionTable['countblank'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.ConutBlank, params, sheet);
                    });
                    self._functionTable['countif'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.CountIf, params, sheet);
                    }, 2, 2);
                    self._functionTable['countifs'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.CountIfs, params, sheet);
                    }, 254, 2);
                    self._functionTable['sumif'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.SumIf, params, sheet);
                    }, 3, 2);
                    self._functionTable['sumifs'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.SumIfs, params, sheet);
                    }, 255, 2);
                    self._functionTable['rank'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.Rank, params, sheet);
                    }, 3, 2);
                    self._functionTable['product'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getFlexSheetAggregateResult(_FlexSheetAggregate.Product, params, sheet);
                    }, 255, 1);
                    self._functionTable['subtotal'] = new _FunctionDefinition(function (params, sheet) {
                        return self._handleSubtotal(params, sheet);
                    }, 255, 2);
                    self._functionTable['dcount'] = new _FunctionDefinition(function (params, sheet) {
                        return self._handleDCount(params, sheet);
                    }, 3, 3);
                    self._functionTable['sumproduct'] = new _FunctionDefinition(function (params, sheet) {
                        return self._getSumProduct(params, sheet);
                    }, 255, 1);
                };
                // Register the math function for the calcEngine.
                _CalcEngine.prototype._registerMathFunction = function () {
                    var self = this, unaryFuncs = ['abs', 'acos', 'asin', 'atan', 'cos', 'exp', 'ln', 'sin', 'sqrt', 'tan'], ceilingFloorFuncs = ['ceiling', 'floor'], roundFuncs = ['round', 'rounddown', 'roundup'];
                    self._functionTable['pi'] = new _FunctionDefinition(function () {
                        return Math.PI;
                    }, 0, 0);
                    self._functionTable['rand'] = new _FunctionDefinition(function () {
                        return Math.random();
                    }, 0, 0);
                    self._functionTable['power'] = new _FunctionDefinition(function (params, sheet) {
                        return Math.pow(sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet), sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet));
                    }, 2, 2);
                    self._functionTable['atan2'] = new _FunctionDefinition(function (params, sheet) {
                        var x = sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet), y = sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet);
                        if (x === 0 && y === 0) {
                            throw 'The x number and y number can\'t both be zero for the atan2 function';
                        }
                        return Math.atan2(y, x);
                    }, 2, 2);
                    self._functionTable['mod'] = new _FunctionDefinition(function (params, sheet) {
                        return sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet) % sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet);
                    }, 2, 2);
                    self._functionTable['trunc'] = new _FunctionDefinition(function (params, sheet) {
                        var num = sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet), precision = params.length === 2 ? sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet) : 0, multiple;
                        if (precision === 0) {
                            if (num >= 0) {
                                return Math.floor(num);
                            }
                            else {
                                return Math.ceil(num);
                            }
                        }
                        else {
                            multiple = Math.pow(10, precision);
                            if (num >= 0) {
                                return Math.floor(num * multiple) / multiple;
                            }
                            else {
                                return Math.ceil(num * multiple) / multiple;
                            }
                        }
                    }, 2, 1);
                    ceilingFloorFuncs.forEach(function (val) {
                        self._functionTable[val] = new _FunctionDefinition(function (params, sheet) {
                            var num = sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet), significance = params.length === 2 ? sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet) : 1, diff, precision, multiple;
                            if (isNaN(num)) {
                                throw 'Invalid Number!';
                            }
                            if (isNaN(significance)) {
                                throw 'Invalid Significance!';
                            }
                            if (num > 0 && significance < 0) {
                                throw 'The significance has to be positive, if the number is positive.';
                            }
                            if (num === 0 || significance === 0) {
                                return 0;
                            }
                            diff = significance - Math.floor(significance);
                            precision = 1;
                            if (diff !== 0) {
                                while (diff < 1) {
                                    precision *= 10;
                                    diff *= 10;
                                }
                            }
                            if (val === 'ceiling') {
                                multiple = Math.ceil(num / significance);
                            }
                            else {
                                multiple = Math.floor(num / significance);
                            }
                            return significance * precision * multiple / precision;
                        }, 2, 1);
                    });
                    roundFuncs.forEach(function (val) {
                        self._functionTable[val] = new _FunctionDefinition(function (params, sheet) {
                            var num = sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet), precision = sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet), result, format, multiple;
                            if (precision === 0) {
                                switch (val) {
                                    case 'rounddown':
                                        if (num >= 0) {
                                            result = Math.floor(num);
                                        }
                                        else {
                                            result = Math.ceil(num);
                                        }
                                        break;
                                    case 'roundup':
                                        if (num >= 0) {
                                            result = Math.ceil(num);
                                        }
                                        else {
                                            result = Math.floor(num);
                                        }
                                        break;
                                    case 'round':
                                        result = Math.round(num);
                                        break;
                                    default:
                                        result = Math.floor(num);
                                        break;
                                }
                                format = 'n0';
                            }
                            else if (precision > 0 && wijmo.isInt(precision)) {
                                multiple = Math.pow(10, precision);
                                switch (val) {
                                    case 'rounddown':
                                        if (num >= 0) {
                                            result = Math.floor(num * multiple) / multiple;
                                        }
                                        else {
                                            result = Math.ceil(num * multiple) / multiple;
                                        }
                                        break;
                                    case 'roundup':
                                        if (num >= 0) {
                                            result = Math.ceil(num * multiple) / multiple;
                                        }
                                        else {
                                            result = Math.floor(num * multiple) / multiple;
                                        }
                                        break;
                                    case 'round':
                                        result = Math.round(num * multiple) / multiple;
                                        break;
                                }
                                format = 'n' + precision;
                            }
                            if (result != null) {
                                return {
                                    value: result,
                                    format: format
                                };
                            }
                            throw 'Invalid precision!';
                        }, 2, 2);
                    });
                    unaryFuncs.forEach(function (val) {
                        self._functionTable[val] = new _FunctionDefinition(function (params, sheet) {
                            if (val === 'ln') {
                                return Math.log(sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet));
                            }
                            else {
                                return Math[val](sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet));
                            }
                        }, 1, 1);
                    });
                };
                // Register the logical function for the calcEngine.
                _CalcEngine.prototype._registerLogicalFunction = function () {
                    // and(true,true,false,...)
                    var self = this;
                    self._functionTable['and'] = new _FunctionDefinition(function (params, sheet) {
                        var result = true, index;
                        for (index = 0; index < params.length; index++) {
                            result = result && sheet_1._Expression.toBoolean(params[index], self._rowIndex, self._columnIndex, sheet);
                            if (!result) {
                                break;
                            }
                        }
                        return result;
                    }, Number.MAX_VALUE, 1);
                    // or(false,true,true,...)
                    self._functionTable['or'] = new _FunctionDefinition(function (params, sheet) {
                        var result = false, index;
                        for (index = 0; index < params.length; index++) {
                            result = result || sheet_1._Expression.toBoolean(params[index], self._rowIndex, self._columnIndex, sheet);
                            if (result) {
                                break;
                            }
                        }
                        return result;
                    }, Number.MAX_VALUE, 1);
                    // not(false)
                    self._functionTable['not'] = new _FunctionDefinition(function (params, sheet) {
                        return !sheet_1._Expression.toBoolean(params[0], self._rowIndex, self._columnIndex, sheet);
                    }, 1, 1);
                    // if(true,a,b)
                    self._functionTable['if'] = new _FunctionDefinition(function (params, sheet) {
                        if (params.length === 3) {
                            return sheet_1._Expression.toBoolean(params[0], self._rowIndex, self._columnIndex, sheet) ? params[1].evaluate(self._rowIndex, self._columnIndex, sheet) : params[2].evaluate(self._rowIndex, self._columnIndex, sheet);
                        }
                        else {
                            return sheet_1._Expression.toBoolean(params[0], self._rowIndex, self._columnIndex, sheet) ? params[1].evaluate(self._rowIndex, self._columnIndex, sheet) : false;
                        }
                    }, 3, 2);
                    // true()
                    self._functionTable['true'] = new _FunctionDefinition(function () {
                        return true;
                    }, 0, 0);
                    // false()
                    self._functionTable['false'] = new _FunctionDefinition(function () {
                        return false;
                    }, 0, 0);
                };
                // register the text process function
                _CalcEngine.prototype._registerTextFunction = function () {
                    // char(65, 66, 67,...) => "abc"
                    var self = this;
                    self._functionTable['char'] = new _FunctionDefinition(function (params, sheet) {
                        var index, result = '';
                        for (index = 0; index < params.length; index++) {
                            result += String.fromCharCode(sheet_1._Expression.toNumber(params[index], self._rowIndex, self._columnIndex, sheet));
                        }
                        return result;
                    }, Number.MAX_VALUE, 1);
                    // code("A")
                    self._functionTable['code'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (str && str.length > 0) {
                            return str.charCodeAt(0);
                        }
                        return -1;
                    }, 1, 1);
                    // concatenate("abc","def","ghi",...) => "abcdefghi"
                    self._functionTable['concatenate'] = new _FunctionDefinition(function (params, sheet) {
                        var index, result = '';
                        for (index = 0; index < params.length; index++) {
                            result = result.concat(sheet_1._Expression.toString(params[index], self._rowIndex, self._columnIndex, sheet));
                        }
                        return result;
                    }, Number.MAX_VALUE, 1);
                    // left("Abcdefgh", 5) => "Abcde"
                    self._functionTable['left'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), length = Math.floor(sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet));
                        if (str && str.length > 0) {
                            return str.slice(0, length);
                        }
                        return null;
                    }, 2, 2);
                    // right("Abcdefgh", 5) => "defgh"
                    self._functionTable['right'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), length = Math.floor(sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet));
                        if (str && str.length > 0) {
                            return str.slice(-length);
                        }
                        return null;
                    }, 2, 2);
                    // find("abc", "abcdefgh") 
                    // this function is case-sensitive.
                    self._functionTable['find'] = new _FunctionDefinition(function (params, sheet) {
                        var search = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), text = sheet_1._Expression.toString(params[1], self._rowIndex, self._columnIndex, sheet), startIndex = params[2] != null ? wijmo.asInt(sheet_1._Expression.toNumber(params[2], self._rowIndex, self._columnIndex, sheet)) : 0, result;
                        if (text != null && search != null) {
                            if (!isNaN(startIndex) && startIndex > 0 && startIndex < text.length) {
                                result = text.indexOf(search, startIndex);
                            }
                            else {
                                result = text.indexOf(search);
                            }
                            if (result > -1) {
                                return result + 1;
                            }
                        }
                        return -1;
                    }, 3, 2);
                    // search("abc", "ABCDEFGH") 
                    // this function is not case-sensitive.
                    self._functionTable['search'] = new _FunctionDefinition(function (params, sheet) {
                        var search = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), text = sheet_1._Expression.toString(params[1], self._rowIndex, self._columnIndex, sheet), startIndex = params[2] != null ? wijmo.asInt(sheet_1._Expression.toNumber(params[2], self._rowIndex, self._columnIndex, sheet)) : 0, adjustNum, searchRegExp, result;
                        if (text != null && search != null) {
                            searchRegExp = new RegExp(search, 'i');
                            if (!isNaN(startIndex) && startIndex > 0 && startIndex < text.length) {
                                text = text.substring(startIndex);
                                adjustNum = startIndex + 1;
                            }
                            else {
                                adjustNum = 1;
                            }
                            result = text.search(searchRegExp);
                            if (result > -1) {
                                return result + adjustNum;
                            }
                        }
                        return -1;
                    }, 3, 2);
                    // len("abcdefgh")
                    self._functionTable['len'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (str) {
                            return str.length;
                        }
                        return -1;
                    }, 1, 1);
                    //  mid("abcdefgh", 2, 3) => "bcd"
                    self._functionTable['mid'] = new _FunctionDefinition(function (params, sheet) {
                        var text = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), start = Math.floor(sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet)), length = Math.floor(sheet_1._Expression.toNumber(params[2], self._rowIndex, self._columnIndex, sheet));
                        if (text && text.length > 0 && start > 0) {
                            return text.substr(start - 1, length);
                        }
                        return null;
                    }, 3, 3);
                    // lower("ABCDEFGH")
                    self._functionTable['lower'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (str && str.length > 0) {
                            return str.toLowerCase();
                        }
                        return null;
                    }, 1, 1);
                    // upper("abcdefgh")
                    self._functionTable['upper'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (str && str.length > 0) {
                            return str.toUpperCase();
                        }
                        return null;
                    }, 1, 1);
                    // proper("abcdefgh") => "Abcdefgh"
                    self._functionTable['proper'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (str && str.length > 0) {
                            return str[0].toUpperCase() + str.substring(1).toLowerCase();
                        }
                        return null;
                    }, 1, 1);
                    // trim("   abcdefgh   ") => "abcdefgh"
                    self._functionTable['trim'] = new _FunctionDefinition(function (params, sheet) {
                        var str = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (str && str.length > 0) {
                            return str.trim();
                        }
                        return null;
                    }, 1, 1);
                    // replace("abcdefg", 2, 3, "xyz") => "axyzefg"
                    self._functionTable['replace'] = new _FunctionDefinition(function (params, sheet) {
                        var text = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), start = Math.floor(sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet)), length = Math.floor(sheet_1._Expression.toNumber(params[2], self._rowIndex, self._columnIndex, sheet)), replaceText = sheet_1._Expression.toString(params[3], self._rowIndex, self._columnIndex, sheet);
                        if (text && text.length > 0 && start > 0) {
                            return text.substring(0, start - 1) + replaceText + text.slice(start - 1 + length);
                        }
                        return null;
                    }, 4, 4);
                    // substitute("abcabcdabcdefgh", "ab", "xy") => "xycxycdxycdefg"
                    self._functionTable['substitute'] = new _FunctionDefinition(function (params, sheet) {
                        var text = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), oldText = sheet_1._Expression.toString(params[1], self._rowIndex, self._columnIndex, sheet), newText = sheet_1._Expression.toString(params[2], self._rowIndex, self._columnIndex, sheet), instanceNum = params.length === 4 ? sheet_1._Expression.toNumber(params[3], self._rowIndex, self._columnIndex, sheet) : null, replaceCnt = 0, searhRegExp;
                        if ((instanceNum != null && instanceNum < 1) || isNaN(instanceNum)) {
                            throw 'Invalid instance number.';
                        }
                        if (text && text.length > 0 && oldText && oldText.length > 0) {
                            searhRegExp = new RegExp(oldText, 'g');
                            return text.replace(searhRegExp, function (text) {
                                replaceCnt++;
                                if (instanceNum != null) {
                                    instanceNum = Math.floor(instanceNum);
                                    if (replaceCnt === instanceNum) {
                                        return newText;
                                    }
                                    else {
                                        return text;
                                    }
                                }
                                return newText;
                            });
                        }
                        return null;
                    }, 4, 3);
                    // rept("abc", 3) => "abcabcabc"
                    self._functionTable['rept'] = new _FunctionDefinition(function (params, sheet) {
                        var text = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), repeatTimes = Math.floor(sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet)), result = '', i;
                        if (text && text.length > 0 && repeatTimes > 0) {
                            for (i = 0; i < repeatTimes; i++) {
                                result = result.concat(text);
                            }
                        }
                        return result;
                    }, 2, 2);
                    // text("1234", "n2") => "1234.00"
                    self._functionTable['text'] = new _FunctionDefinition(function (params, sheet) {
                        var value = params[0].evaluate(self._rowIndex, self._columnIndex, sheet), format = sheet_1._Expression.toString(params[1], self._rowIndex, self._columnIndex, sheet), matches;
                        if (!wijmo.isPrimitive(value) && value) {
                            value = value.value;
                        }
                        if (wijmo.isDate(value)) {
                            format = format.replace(/\[\$\-.+\]/g, '')
                                .replace(/(\\)(.)/g, '$2')
                                .replace(/H+/g, function (str) {
                                return str.toLowerCase();
                            }).replace(/m+/g, function (str) {
                                return str.toUpperCase();
                            }).replace(/S+/g, function (str) {
                                return str.toLowerCase();
                            }).replace(/AM\/PM/gi, 'tt')
                                .replace(/A\/P/gi, 't')
                                .replace(/\.000/g, '.fff')
                                .replace(/\.00/g, '.ff')
                                .replace(/\.0/g, '.f')
                                .replace(/\\[\-\s,]/g, function (str) {
                                return str.substring(1);
                            }).replace(/Y+/g, function (str) {
                                return str.toLowerCase();
                            }).replace(/D+/g, function (str) {
                                return str.toLowerCase();
                            }).replace(/M+:?|:?M+/gi, function (str) {
                                if (str.indexOf(':') > -1) {
                                    return str.toLowerCase();
                                }
                                else {
                                    return str;
                                }
                            }).replace(/g+e/gi, function (str) {
                                return str.substring(0, str.length - 1) + 'yy';
                            });
                        }
                        else if (wijmo.isNumber(value)) {
                            matches = format.match(/^(\d+)(\.\d+)?\E\+(\d+)(\.\d+)?$/);
                            if (matches && matches.length === 5) {
                                return self._parseToScientificValue(value, matches[1], matches[2], matches[3], matches[4]);
                            }
                            else if (/M{1,4}|d{1,4}|y{1,4}/.test(format)) {
                                value = new Date(1900, 0, value - 1);
                            }
                            else {
                                if (!!format && format.indexOf('#') > -1) {
                                    format = wijmo.xlsx.Workbook.fromXlsxFormat(format)[0];
                                }
                            }
                        }
                        else {
                            return value;
                        }
                        if (wijmo.isDate(value)) {
                            switch (format) {
                                case 'd':
                                    return value.getDate();
                                case 'M':
                                    return value.getMonth() + 1;
                                case 'y':
                                    format = 'yy';
                                    break;
                                case 'yyy':
                                    format = 'yyyy';
                                    break;
                            }
                        }
                        return wijmo.Globalize.format(value, format);
                    }, 2, 2);
                    // value("1234") => 1234
                    self._functionTable['value'] = new _FunctionDefinition(function (params, sheet) {
                        var strVal = sheet_1._Expression.toString(params[0], self._rowIndex, self._columnIndex, sheet), val;
                        strVal = strVal.replace(/(\,\d{3})/g, function (text) {
                            return text.substring(1);
                        });
                        if (strVal.length > 0) {
                            if (strVal[0] === wijmo.culture.Globalize.numberFormat.currency.symbol) {
                                strVal = strVal.substring(1);
                                return +strVal;
                            }
                            if (strVal[strVal.length - 1] === '%') {
                                strVal = strVal.substring(0, strVal.length - 1);
                                return +strVal / 100;
                            }
                        }
                        val = +strVal;
                        return isNaN(val) ? sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet) : val;
                    }, 1, 1);
                };
                // Register the datetime function for the calcEngine.
                _CalcEngine.prototype._registerDateFunction = function () {
                    var self = this;
                    self._functionTable['now'] = new _FunctionDefinition(function () {
                        return {
                            value: new Date(),
                            format: 'M/d/yyyy h:mm'
                        };
                    }, 0, 0);
                    self._functionTable['today'] = new _FunctionDefinition(function () {
                        var now = new Date();
                        return {
                            value: new Date(now.getFullYear(), now.getMonth(), now.getDate()),
                            format: 'd'
                        };
                    }, 0, 0);
                    // year("11/25/2015") => 2015
                    self._functionTable['year'] = new _FunctionDefinition(function (params, sheet) {
                        var date = sheet_1._Expression.toDate(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (!wijmo.isPrimitive(date) && date) {
                            return date.value;
                        }
                        if (wijmo.isDate(date)) {
                            return date.getFullYear();
                        }
                        return 1900;
                    }, 1, 1);
                    // month("11/25/2015") => 11
                    self._functionTable['month'] = new _FunctionDefinition(function (params, sheet) {
                        var date = sheet_1._Expression.toDate(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (!wijmo.isPrimitive(date) && date) {
                            return date.value;
                        }
                        if (wijmo.isDate(date)) {
                            return date.getMonth() + 1;
                        }
                        return 1;
                    }, 1, 1);
                    // day("11/25/2015") => 25
                    self._functionTable['day'] = new _FunctionDefinition(function (params, sheet) {
                        var date = sheet_1._Expression.toDate(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (!wijmo.isPrimitive(date) && date) {
                            return date.value;
                        }
                        if (wijmo.isDate(date)) {
                            return date.getDate();
                        }
                        return 0;
                    }, 1, 1);
                    // hour("11/25/2015 16:50") => 16 or hour(0.5) => 12
                    self._functionTable['hour'] = new _FunctionDefinition(function (params, sheet) {
                        var val = params[0].evaluate(self._rowIndex, self._columnIndex, sheet);
                        if (wijmo.isNumber(val) && !isNaN(val)) {
                            return Math.floor(24 * (val - Math.floor(val)));
                        }
                        else if (wijmo.isDate(val)) {
                            return val.getHours();
                        }
                        val = sheet_1._Expression.toDate(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (!wijmo.isPrimitive(val) && val) {
                            val = val.value;
                        }
                        if (wijmo.isDate(val)) {
                            return val.getHours();
                        }
                        throw 'Invalid parameter.';
                    }, 1, 1);
                    // time(10, 23, 11) => 10:23:11 AM
                    self._functionTable['time'] = new _FunctionDefinition(function (params, sheet) {
                        var hour = params[0].evaluate(self._rowIndex, self._columnIndex, sheet), minute = params[1].evaluate(self._rowIndex, self._columnIndex, sheet), second = params[2].evaluate(self._rowIndex, self._columnIndex, sheet);
                        if (wijmo.isNumber(hour) && wijmo.isNumber(minute) && wijmo.isNumber(second)) {
                            hour %= 24;
                            minute %= 60;
                            second %= 60;
                            return {
                                value: new Date(0, 0, 0, hour, minute, second),
                                format: 't'
                            };
                        }
                        throw 'Invalid parameters.';
                    }, 3, 3);
                    // time(2015, 11, 25) => 11/25/2015
                    self._functionTable['date'] = new _FunctionDefinition(function (params, sheet) {
                        var year = params[0].evaluate(self._rowIndex, self._columnIndex, sheet), month = params[1].evaluate(self._rowIndex, self._columnIndex, sheet), day = params[2].evaluate(self._rowIndex, self._columnIndex, sheet);
                        if (wijmo.isNumber(year) && wijmo.isNumber(month) && wijmo.isNumber(day)) {
                            return {
                                value: new Date(year, month - 1, day),
                                format: 'd'
                            };
                        }
                        throw 'Invalid parameters.';
                    }, 3, 3);
                    self._functionTable['datedif'] = new _FunctionDefinition(function (params, sheet) {
                        var startDate = sheet_1._Expression.toDate(params[0], self._rowIndex, self._columnIndex, sheet), endDate = sheet_1._Expression.toDate(params[1], self._rowIndex, self._columnIndex, sheet), unit = params[2].evaluate(self._rowIndex, self._columnIndex, sheet), startDateTime, endDateTime, diffDays, diffMonths, diffYears;
                        if (!wijmo.isPrimitive(startDate) && startDate) {
                            startDate = startDate.value;
                        }
                        if (!wijmo.isPrimitive(endDate) && endDate) {
                            endDate = endDate.value;
                        }
                        if (wijmo.isDate(startDate) && wijmo.isDate(endDate) && wijmo.isString(unit)) {
                            startDateTime = startDate.getTime();
                            endDateTime = endDate.getTime();
                            if (startDateTime > endDateTime) {
                                throw 'Start date is later than end date.';
                            }
                            diffDays = endDate.getDate() - startDate.getDate();
                            diffMonths = endDate.getMonth() - startDate.getMonth();
                            diffYears = endDate.getFullYear() - startDate.getFullYear();
                            switch (unit.toUpperCase()) {
                                case 'Y':
                                    if (diffMonths > 0) {
                                        return diffYears;
                                    }
                                    else if (diffMonths < 0) {
                                        return diffYears - 1;
                                    }
                                    else {
                                        if (diffDays >= 0) {
                                            return diffYears;
                                        }
                                        else {
                                            return diffYears - 1;
                                        }
                                    }
                                case 'M':
                                    if (diffDays >= 0) {
                                        return diffYears * 12 + diffMonths;
                                    }
                                    else {
                                        return diffYears * 12 + diffMonths - 1;
                                    }
                                case 'D':
                                    return (endDateTime - startDateTime) / (1000 * 3600 * 24);
                                case 'YM':
                                    if (diffDays >= 0) {
                                        diffMonths = diffYears * 12 + diffMonths;
                                    }
                                    else {
                                        diffMonths = diffYears * 12 + diffMonths - 1;
                                    }
                                    return diffMonths % 12;
                                case 'YD':
                                    if (diffMonths > 0) {
                                        return (new Date(startDate.getFullYear(), endDate.getMonth(), endDate.getDate()).getTime() - startDate.getTime()) / (1000 * 3600 * 24);
                                    }
                                    else if (diffMonths < 0) {
                                        return (new Date(startDate.getFullYear() + 1, endDate.getMonth(), endDate.getDate()).getTime() - startDate.getTime()) / (1000 * 3600 * 24);
                                    }
                                    else {
                                        if (diffDays >= 0) {
                                            return diffDays;
                                        }
                                        else {
                                            return (new Date(startDate.getFullYear() + 1, endDate.getMonth(), endDate.getDate()).getTime() - startDate.getTime()) / (1000 * 3600 * 24);
                                        }
                                    }
                                case 'MD':
                                    if (diffDays >= 0) {
                                        return diffDays;
                                    }
                                    else {
                                        diffDays = new Date(endDate.getFullYear(), endDate.getMonth(), 0).getDate() - new Date(endDate.getFullYear(), endDate.getMonth() - 1, 1).getDate() + 1 + diffDays;
                                        return diffDays;
                                    }
                                default:
                                    throw 'Invalid unit.';
                            }
                        }
                        throw 'Invalid parameters.';
                    }, 3, 3);
                };
                // Register the cell reference and look up related functions for the calcEngine.
                _CalcEngine.prototype._registLookUpReferenceFunction = function () {
                    var self = this;
                    self._functionTable['column'] = new _FunctionDefinition(function (params, sheet, rowIndex, columnIndex) {
                        var cellExpr;
                        if (params == null) {
                            return columnIndex + 1;
                        }
                        cellExpr = params[0];
                        cellExpr = self._ensureNonFunctionExpression(cellExpr);
                        if (cellExpr instanceof sheet_1._CellRangeExpression) {
                            return cellExpr.cells.col + 1;
                        }
                        throw 'Invalid Cell Reference.';
                    }, 1, 0);
                    self._functionTable['columns'] = new _FunctionDefinition(function (params, sheet) {
                        var cellExpr = params[0];
                        cellExpr = self._ensureNonFunctionExpression(cellExpr);
                        if (cellExpr instanceof sheet_1._CellRangeExpression) {
                            return cellExpr.cells.columnSpan;
                        }
                        throw 'Invalid Cell Reference.';
                    }, 1, 1);
                    self._functionTable['row'] = new _FunctionDefinition(function (params, sheet, rowIndex, columnIndex) {
                        var cellExpr;
                        if (params == null) {
                            return rowIndex + 1;
                        }
                        cellExpr = params[0];
                        cellExpr = self._ensureNonFunctionExpression(cellExpr);
                        if (cellExpr instanceof sheet_1._CellRangeExpression) {
                            return cellExpr.cells.row + 1;
                        }
                        throw 'Invalid Cell Reference.';
                    }, 1, 0);
                    self._functionTable['rows'] = new _FunctionDefinition(function (params, sheet) {
                        var cellExpr = params[0];
                        cellExpr = self._ensureNonFunctionExpression(cellExpr);
                        if (cellExpr instanceof sheet_1._CellRangeExpression) {
                            return cellExpr.cells.rowSpan;
                        }
                        throw 'Invalid Cell Reference.';
                    }, 1, 1);
                    self._functionTable['choose'] = new _FunctionDefinition(function (params, sheet) {
                        var index = sheet_1._Expression.toNumber(params[0], self._rowIndex, self._columnIndex, sheet);
                        if (isNaN(index)) {
                            throw 'Invalid index number.';
                        }
                        if (index < 1 || index >= params.length) {
                            throw 'The index number is out of the list range.';
                        }
                        return params[index].evaluate(self._rowIndex, self._columnIndex, sheet);
                    }, 255, 2);
                    self._functionTable['index'] = new _FunctionDefinition(function (params, sheet) {
                        var cellExpr = params[0], cells, rowNum = sheet_1._Expression.toNumber(params[1], self._rowIndex, self._columnIndex, sheet), colNum = params[2] != null ? sheet_1._Expression.toNumber(params[2], self._rowIndex, self._columnIndex, sheet) : 0;
                        if (isNaN(rowNum) || rowNum < 0) {
                            throw 'Invalid Row Number.';
                        }
                        if (isNaN(colNum) || colNum < 0) {
                            throw 'Invalid Column Number.';
                        }
                        cellExpr = self._ensureNonFunctionExpression(cellExpr);
                        if (cellExpr instanceof sheet_1._CellRangeExpression) {
                            cells = cellExpr.cells;
                            if (rowNum > cells.rowSpan || colNum > cells.columnSpan) {
                                throw 'Index is out of the cell range.';
                            }
                            if (rowNum > 0 && colNum > 0) {
                                return self._owner.getCellValue(cells.topRow + rowNum - 1, cells.leftCol + colNum - 1, true, sheet);
                            }
                            if (rowNum === 0 && colNum === 0) {
                                return cellExpr;
                            }
                            if (rowNum === 0) {
                                return new sheet_1._CellRangeExpression(new grid.CellRange(cells.topRow, cells.leftCol + colNum - 1, cells.bottomRow, cells.leftCol + colNum - 1), cellExpr.sheetRef, self._owner);
                            }
                            if (colNum === 0) {
                                return new sheet_1._CellRangeExpression(new grid.CellRange(cells.topRow + rowNum - 1, cells.leftCol, cells.topRow + rowNum - 1, cells.rightCol), cellExpr.sheetRef, self._owner);
                            }
                        }
                        throw 'Invalid Cell Reference.';
                    }, 4, 2);
                    self._functionTable['hlookup'] = new _FunctionDefinition(function (params, sheet) {
                        return self._handleHLookup(params, sheet);
                    }, 4, 3);
                };
                // Register the finacial function for the calcEngine.
                _CalcEngine.prototype._registFinacialFunction = function () {
                    var self = this;
                    self._functionTable['rate'] = new _FunctionDefinition(function (params, sheet) {
                        var rate = self._calculateRate(params, sheet);
                        return {
                            value: rate,
                            format: 'p2'
                        };
                    }, 6, 3);
                };
                // Add token into the static token table.
                _CalcEngine.prototype._addToken = function (symbol, id, type) {
                    var token = new _Token(symbol, id, type);
                    this._tokenTable[symbol] = token;
                };
                // Parse expression
                _CalcEngine.prototype._parseExpression = function () {
                    this._getToken();
                    return this._parseCompareOrConcat();
                };
                // Parse compare expression
                _CalcEngine.prototype._parseCompareOrConcat = function () {
                    var x = this._parseAddSub(), t, exprArg;
                    while (this._token.tokenType === _TokenType.COMPARE || this._token.tokenType === _TokenType.CONCAT) {
                        t = this._token;
                        this._getToken();
                        exprArg = this._parseAddSub();
                        x = new sheet_1._BinaryExpression(t, x, exprArg);
                    }
                    return x;
                };
                // Parse add/sub expression.
                _CalcEngine.prototype._parseAddSub = function () {
                    var x = this._parseMulDiv(), t, exprArg;
                    while (this._token.tokenType === _TokenType.ADDSUB) {
                        t = this._token;
                        this._getToken();
                        exprArg = this._parseMulDiv();
                        x = new sheet_1._BinaryExpression(t, x, exprArg);
                    }
                    return x;
                };
                // Parse multiple/division expression.
                _CalcEngine.prototype._parseMulDiv = function () {
                    var x = this._parsePower(), t, exprArg;
                    while (this._token.tokenType === _TokenType.MULDIV) {
                        t = this._token;
                        this._getToken();
                        exprArg = this._parsePower();
                        x = new sheet_1._BinaryExpression(t, x, exprArg);
                    }
                    return x;
                };
                // Parse power expression.
                _CalcEngine.prototype._parsePower = function () {
                    var x = this._parseUnary(), t, exprArg;
                    while (this._token.tokenType === _TokenType.POWER) {
                        t = this._token;
                        this._getToken();
                        exprArg = this._parseUnary();
                        x = new sheet_1._BinaryExpression(t, x, exprArg);
                    }
                    return x;
                };
                // Parse unary expression
                _CalcEngine.prototype._parseUnary = function () {
                    var t, exprArg;
                    // unary plus and minus
                    if (this._token.tokenID === _TokenID.ADD || this._token.tokenID === _TokenID.SUB) {
                        t = this._token;
                        this._getToken();
                        exprArg = this._parseAtom();
                        return new sheet_1._UnaryExpression(t, exprArg);
                    }
                    // not unary, return atom
                    return this._parseAtom();
                };
                // Parse atomic expression
                _CalcEngine.prototype._parseAtom = function () {
                    var x = null, id, funcDefinition, params, pCnt, cellRef, definedName, orgExpression, orgExpressionLength, orgPointer, definedNameRefs, definedNameRef, sheetRef, table, tokenType = this._token.tokenType;
                    switch (tokenType) {
                        // literals
                        case _TokenType.LITERAL:
                            x = new sheet_1._Expression(this._token);
                            break;
                        // identifiers
                        case _TokenType.IDENTIFIER:
                            // get identifier
                            id = this._token.value.toString().toLowerCase();
                            funcDefinition = this._functionTable[id];
                            // look for functions
                            if (funcDefinition) {
                                params = this._getParameters();
                                if (this._token.tokenType === _TokenType.GROUP && this._token.tokenID === _TokenID.CLOSE) {
                                    pCnt = params ? params.length : 0;
                                    if (funcDefinition.paramMin !== -1 && pCnt < funcDefinition.paramMin) {
                                        throw 'Too few parameters.';
                                    }
                                    if (funcDefinition.paramMax !== -1 && pCnt > funcDefinition.paramMax) {
                                        throw 'Too many parameters.';
                                    }
                                    if (id === 'rand') {
                                        this._containsCellRef = true;
                                    }
                                    x = new sheet_1._FunctionExpression(funcDefinition, params);
                                    break;
                                }
                                else if (id === 'true' || id === 'false') {
                                    x = new sheet_1._FunctionExpression(funcDefinition, params, false);
                                    break;
                                }
                            }
                            // look for defined name
                            definedNameRefs = id.split('!');
                            if (definedNameRefs.length === 2) {
                                sheetRef = definedNameRefs[0];
                                definedNameRef = definedNameRefs[1];
                            }
                            else {
                                definedNameRef = definedNameRefs[0];
                            }
                            definedName = this._getDefinedName(definedNameRef, sheetRef || this._owner.selectedSheet.name.toLowerCase());
                            if (definedName) {
                                if (!definedName.sheetName || definedName.sheetName === this._owner.selectedSheet.name || definedName.sheetName.toLowerCase() === sheetRef) {
                                    orgPointer = this._pointer;
                                    orgExpressionLength = this._expressLength;
                                    orgExpression = this._expression;
                                    this._pointer = 0;
                                    x = this._checkCache(definedName.value);
                                    this._pointer = orgPointer;
                                    this._expressLength = orgExpressionLength;
                                    this._expression = orgExpression;
                                    break;
                                }
                                else {
                                    throw 'The defined name item works in ' + definedName.sheetName + '.  It does not work in current sheet.';
                                }
                            }
                            sheetRef = '';
                            table = this._owner._getTable(id);
                            if (table != null) {
                                sheetRef = this._getTableRelatedSheet(id);
                                if (sheetRef === '') {
                                    throw 'The Table(' + id + ') is not located in any sheet.';
                                }
                                this._getToken();
                                if (this._token.tokenType === _TokenType.SQUAREBRACKETS && this._token.tokenID === _TokenID.OPEN) {
                                    this._tableRefStart = true;
                                    x = this._getTableReference(table, sheetRef);
                                }
                                else {
                                    throw 'Invalid Table Reference.';
                                }
                                break;
                            }
                            // look for Cell Range.
                            cellRef = this._getCellRange(id);
                            if (cellRef) {
                                this._containsCellRef = true;
                                x = new sheet_1._CellRangeExpression(cellRef.cellRange, cellRef.sheetRef, this._owner);
                                break;
                            }
                            // trigger the unknownFunction event.
                            params = this._getParameters();
                            x = this.onUnknownFunction(id, params);
                            break;
                        // sub-expressions
                        case _TokenType.GROUP:
                            // anything other than opening parenthesis is illegal here
                            if (this._token.tokenID !== _TokenID.OPEN) {
                                throw 'Expression expected.';
                            }
                            // get expression
                            this._getToken();
                            x = this._parseCompareOrConcat();
                            // check that the parenthesis was closed
                            if (this._token.tokenID !== _TokenID.CLOSE) {
                                throw 'Unbalanced parenthesis.';
                            }
                            break;
                        case _TokenType.SQUAREBRACKETS:
                            if (this._token.tokenID !== _TokenID.OPEN) {
                                throw 'Table References expected.';
                            }
                            table = this._owner.selectedSheet.findTable(this._rowIndex, this._columnIndex);
                            if (table != null) {
                                sheetRef = this._getTableRelatedSheet(table.name.toLowerCase());
                                this._tableRefStart = true;
                                x = this._getTableReference(table, sheetRef);
                            }
                            break;
                    }
                    // make sure we got something...
                    if (x === null) {
                        throw '';
                    }
                    // done
                    this._getToken();
                    return x;
                };
                // Get token for the expression.
                _CalcEngine.prototype._getToken = function () {
                    var i, c, lastChar, isLetter, isDigit, id = '', sheetRef = '', 
                    // About the Japanese characters checking
                    // Please refer http://stackoverflow.com/questions/15033196/using-javascript-to-check-whether-a-string-contains-japanese-characters-includi
                    // And http://www.rikai.com/library/kanjitables/kanji_codes.unicode.shtml
                    japaneseRegExp = new RegExp('[\u3000-\u303f\u3040-\u309f\u30a0-\u30ff\uff00-\uff9f\u4e00-\u9faf\u3400-\u4dbf]');
                    // eat white space 
                    while (this._pointer < this._expressLength && this._expression[this._pointer] === ' ') {
                        this._pointer++;
                    }
                    // are we done?
                    if (this._pointer >= this._expressLength) {
                        this._token = new _Token(null, _TokenID.END, _TokenType.GROUP);
                        return;
                    }
                    // prepare to parse
                    c = this._expression[this._pointer];
                    // operators
                    // this gets called a lot, so it's pretty optimized.
                    // note that operators must start with non-letter/digit characters.
                    isLetter = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || japaneseRegExp.test(c);
                    isDigit = (c >= '0' && c <= '9') || c == '.';
                    if (!isLetter && !isDigit) {
                        var tk = this._tokenTable[c];
                        if (tk) {
                            // save token we found
                            this._token = tk;
                            this._pointer++;
                            // look for double-char tokens (special case)
                            if (this._pointer < this._expressLength && (c === '>' || c === '<')) {
                                tk = this._tokenTable[this._expression.substring(this._pointer - 1, this._pointer + 1)];
                                if (tk) {
                                    this._token = tk;
                                    this._pointer++;
                                }
                            }
                            return;
                        }
                    }
                    // parse numbers token
                    if (isDigit) {
                        this._parseDigit();
                        return;
                    }
                    // parse strings token
                    if (c === '\"') {
                        this._parseString();
                        return;
                    }
                    if (c === '\'') {
                        sheetRef = this._parseSheetRef();
                        if (!sheetRef) {
                            return;
                        }
                    }
                    // parse dates token
                    if (c === '#') {
                        this._parseDate();
                        return;
                    }
                    // identifiers (functions, objects) must start with alpha or underscore
                    if (!isLetter && c !== '_' && this._idChars.indexOf(c) < 0 && !sheetRef) {
                        throw 'Identifier expected.';
                    }
                    // and must contain only letters/digits/_idChars
                    for (i = 1; i + this._pointer < this._expressLength; i++) {
                        c = this._expression[this._pointer + i];
                        isLetter = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || japaneseRegExp.test(c);
                        isDigit = c >= '0' && c <= '9';
                        if (c === '\'' && lastChar === ':') {
                            id = sheetRef + this._expression.substring(this._pointer, this._pointer + i);
                            this._pointer += i;
                            sheetRef = this._parseSheetRef();
                            i = 0;
                            continue;
                        }
                        lastChar = c;
                        if (!isLetter && !isDigit && c !== '_' && this._idChars.indexOf(c) < 0) {
                            break;
                        }
                    }
                    // got identifier
                    id += sheetRef + this._expression.substring(this._pointer, this._pointer + i);
                    this._pointer += i;
                    this._token = new _Token(id, _TokenID.ATOM, _TokenType.IDENTIFIER);
                };
                // Get token for the table reference.
                _CalcEngine.prototype._getTableToken = function () {
                    var i, c, id, tableParamStart = false;
                    // eat white space 
                    while (this._pointer < this._expressLength && this._expression[this._pointer] === ' ') {
                        this._pointer++;
                    }
                    c = this._expression[this._pointer];
                    if (c === '[') {
                        tableParamStart = true;
                    }
                    for (i = 1; i + this._pointer < this._expressLength; i++) {
                        c = this._expression[this._pointer + i];
                        if ((tableParamStart && c === ',')) {
                            throw 'Invalid table reference.';
                        }
                        if (c === ',' || c === ']') {
                            break;
                        }
                    }
                    id = this._expression.substring(this._pointer + (tableParamStart ? 1 : 0), this._pointer + i);
                    this._pointer += i + (tableParamStart ? 1 : 0);
                    this._token = new _Token(id, _TokenID.ATOM, _TokenType.IDENTIFIER);
                };
                // Parse digit token
                _CalcEngine.prototype._parseDigit = function () {
                    var div = -1, sci = false, pct = false, val = 0.0, i, c, lit;
                    for (i = 0; i + this._pointer < this._expressLength; i++) {
                        c = this._expression[this._pointer + i];
                        // digits always OK
                        if (c >= '0' && c <= '9') {
                            val = val * 10 + (+c - 0);
                            if (div > -1) {
                                div *= 10;
                            }
                            continue;
                        }
                        // one decimal is OK
                        if (c === '.' && div < 0) {
                            div = 1;
                            continue;
                        }
                        // scientific notation?
                        if ((c === 'E' || c === 'e') && !sci) {
                            sci = true;
                            c = this._expression[this._pointer + i + 1];
                            if (c === '+' || c === '-')
                                i++;
                            continue;
                        }
                        // percentage?
                        if (c === '%') {
                            pct = true;
                            i++;
                            break;
                        }
                        // end of literal
                        break;
                    }
                    // end of number, get value
                    if (!sci) {
                        // much faster than ParseDouble
                        if (div > 1) {
                            val /= div;
                        }
                        if (pct) {
                            val /= 100.0;
                        }
                    }
                    else {
                        lit = this._expression.substring(this._pointer, this._pointer + i);
                        val = +lit;
                    }
                    // build token
                    this._token = new _Token(val, _TokenID.ATOM, _TokenType.LITERAL);
                    // advance pointer and return
                    this._pointer += i;
                };
                // Parse string token
                _CalcEngine.prototype._parseString = function () {
                    var i, c, cNext, lit;
                    // look for end quote, skip double quotes
                    for (i = 1; i + this._pointer < this._expressLength; i++) {
                        c = this._expression[this._pointer + i];
                        if (c !== '\"') {
                            continue;
                        }
                        cNext = i + this._pointer < this._expressLength - 1 ? this._expression[this._pointer + i + 1] : ' ';
                        if (cNext !== '\"') {
                            break;
                        }
                        i++;
                    }
                    // check that we got the end of the string
                    if (c !== '\"') {
                        throw 'Can\'t find final quote.';
                    }
                    // end of string
                    lit = this._expression.substring(this._pointer + 1, this._pointer + i);
                    this._pointer += i + 1;
                    if (this._expression[this._pointer] === '!') {
                        throw 'Illegal cross sheet reference.';
                    }
                    this._token = new _Token(lit.replace('\"\"', '\"'), _TokenID.ATOM, _TokenType.LITERAL);
                };
                // Parse datetime token
                _CalcEngine.prototype._parseDate = function () {
                    var i, c, lit;
                    // look for end #
                    for (i = 1; i + this._pointer < this._expressLength; i++) {
                        c = this._expression[this._pointer + i];
                        if (c === '#') {
                            break;
                        }
                    }
                    // check that we got the end of the date
                    if (c !== '#') {
                        throw 'Can\'t find final date delimiter ("#").';
                    }
                    // end of date
                    lit = this._expression.substring(this._pointer + 1, this._pointer + i);
                    this._pointer += i + 1;
                    this._token = new _Token(Date.parse(lit), _TokenID.ATOM, _TokenType.LITERAL);
                };
                // Parse the sheet reference.
                _CalcEngine.prototype._parseSheetRef = function () {
                    var i, c, cNext, lit;
                    // look for end quote, skip double quotes
                    for (i = 1; i + this._pointer < this._expressLength; i++) {
                        c = this._expression[this._pointer + i];
                        if (c !== '\'') {
                            continue;
                        }
                        cNext = i + this._pointer < this._expressLength - 1 ? this._expression[this._pointer + i + 1] : ' ';
                        if (cNext !== '\'') {
                            break;
                        }
                        i++;
                    }
                    // check that we got the end of the string
                    if (c !== '\'') {
                        throw 'Can\'t find final quote.';
                    }
                    // end of string
                    lit = this._expression.substring(this._pointer + 1, this._pointer + i);
                    this._pointer += i + 1;
                    if (this._expression[this._pointer] === '!') {
                        return lit.replace(/\'\'/g, '\'');
                    }
                    else {
                        return '';
                    }
                };
                // Gets the cell range by the identifier.
                // For e.g. A1:C3 to cellRange(row=0, col=0, row1=2, col1=2)
                _CalcEngine.prototype._getCellRange = function (identifier) {
                    var cells, cell, cell2, sheetRef, rng, rng2;
                    if (identifier) {
                        cells = identifier.split(':');
                        if (cells.length > 0 && cells.length < 3) {
                            cell = this._parseCell(cells[0]);
                            rng = cell.cellRange;
                            if (rng && cells.length === 2) {
                                cell2 = this._parseCell(cells[1]);
                                rng2 = cell2.cellRange;
                                if (cell.sheetRef && !cell2.sheetRef) {
                                    cell2.sheetRef = cell.sheetRef;
                                }
                                if (cell.sheetRef !== cell2.sheetRef) {
                                    throw 'The cell reference must be in the same sheet!';
                                }
                                if (rng2) {
                                    rng.col2 = rng2.col;
                                    rng.row2 = rng2.row;
                                }
                                else {
                                    rng = null;
                                }
                            }
                        }
                    }
                    if (rng == null) {
                        return null;
                    }
                    return {
                        cellRange: rng,
                        sheetRef: cell.sheetRef
                    };
                };
                // Parse the single string cell identifier to cell range;
                // For e.g. A1 to cellRange(row=0, col=0).
                _CalcEngine.prototype._parseCellRange = function (cell) {
                    var col = -1, row = -1, absCol = false, absRow = false, index, c;
                    // parse column
                    for (index = 0; index < cell.length; index++) {
                        c = cell[index];
                        if (c === '$' && !absCol) {
                            absCol = true;
                            continue;
                        }
                        if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) {
                            break;
                        }
                        if (col < 0) {
                            col = 0;
                        }
                        col = 26 * col + (c.toUpperCase().charCodeAt(0) - 'A'.charCodeAt(0) + 1);
                    }
                    // parse row
                    for (; index < cell.length; index++) {
                        c = cell[index];
                        if (c === '$' && !absRow) {
                            absRow = true;
                            continue;
                        }
                        if (!(c >= '0' && c <= '9')) {
                            break;
                        }
                        if (row < 0) {
                            row = 0;
                        }
                        row = 10 * row + (+c - 0);
                    }
                    // sanity
                    if (index < cell.length) {
                        row = col = -1;
                    }
                    if (row === -1 || col === -1) {
                        return null;
                    }
                    // done
                    return new grid.CellRange(row - 1, col - 1);
                };
                // Parse the single cell reference string to cell reference object.
                // For e.g. 'sheet1!A1' to { sheetRef: 'sheet1', cellRange: CellRange(row = 0, col = 0)}
                _CalcEngine.prototype._parseCell = function (cell) {
                    var rng, sheetRefIndex, cellsRef, sheetRef;
                    sheetRefIndex = cell.lastIndexOf('!');
                    if (sheetRefIndex > 0 && sheetRefIndex < cell.length - 1) {
                        sheetRef = cell.substring(0, sheetRefIndex);
                        cellsRef = cell.substring(sheetRefIndex + 1);
                    }
                    else if (sheetRefIndex <= 0) {
                        cellsRef = cell;
                    }
                    else {
                        return null;
                    }
                    rng = this._parseCellRange(cellsRef);
                    return {
                        cellRange: rng,
                        sheetRef: sheetRef
                    };
                };
                // Gets the parameters for the function.
                // e.g. myfun(a, b, c+2)
                _CalcEngine.prototype._getParameters = function () {
                    // check whether next token is a (, 
                    // restore state and bail if it's not
                    var pos = this._pointer, tk = this._token, parms, expr;
                    this._getToken();
                    if (this._token.tokenType === _TokenType.SQUAREBRACKETS && this._token.tokenID === _TokenID.OPEN) {
                        return;
                    }
                    if (this._token.tokenID !== _TokenID.OPEN) {
                        this._pointer = pos;
                        this._token = tk;
                        return null;
                    }
                    // check for empty Parameter list
                    pos = this._pointer;
                    this._getToken();
                    if (this._token.tokenID === _TokenID.CLOSE) {
                        return null;
                    }
                    this._pointer = pos;
                    // get Parameters until we reach the end of the list
                    parms = new Array();
                    expr = this._parseExpression();
                    parms.push(expr);
                    while (this._token.tokenID === _TokenID.COMMA) {
                        expr = this._parseExpression();
                        parms.push(expr);
                    }
                    // make sure the list was closed correctly
                    if (this._token.tokenID !== _TokenID.CLOSE) {
                        throw 'Syntax error.';
                    }
                    // done
                    return parms;
                };
                // Get table reference.
                _CalcEngine.prototype._getTableReference = function (table, sheetRef) {
                    var tableParams = [], param = this._getTableParameter(), isRange = false, refRange;
                    if (param == null) {
                        throw 'Invalid table reference.';
                    }
                    tableParams.push(param);
                    while (this._tableRefStart && (this._token.tokenID === _TokenID.COMMA || this._token.value === ':')) {
                        if (this._token.value === ':') {
                            isRange = true;
                        }
                        param = this._getTableParameter();
                        if (param == null) {
                            throw 'Invalid table reference.';
                        }
                        if (isRange) {
                            tableParams[tableParams.length - 1] += ':' + param;
                            isRange = false;
                        }
                        else {
                            tableParams.push(param);
                        }
                    }
                    if (this._token.tokenType === _TokenType.SQUAREBRACKETS && this._token.tokenID === _TokenID.CLOSE) {
                        this._tableRefStart = false;
                    }
                    else {
                        throw 'Unbalanced square brackets.';
                    }
                    refRange = this._getTableRange(table, tableParams);
                    this._containsCellRef = true;
                    return new sheet_1._CellRangeExpression(refRange, sheetRef.toLowerCase(), this._owner);
                };
                // Get parameters of the table reference.
                _CalcEngine.prototype._getTableParameter = function () {
                    var value, token, pos = this._pointer;
                    // eat white space 
                    while (this._pointer < this._expressLength && this._expression[this._pointer] === ' ') {
                        this._pointer++;
                    }
                    if (this._expression[this._pointer + 1] === ']') {
                        this._tableRefStart = false;
                        return null;
                    }
                    this._getTableToken();
                    value = this._token.value;
                    this._getToken();
                    return value;
                };
                // Get the range of the table reference.
                _CalcEngine.prototype._getTableRange = function (table, tableRefs) {
                    var ref, columnExisted, thisRowExisted, range, tmpRange, colRefs;
                    for (var i = 0; i < tableRefs.length; i++) {
                        if (columnExisted) {
                            throw 'Invalid Table Refernce.';
                        }
                        ref = tableRefs[i].toLowerCase();
                        tmpRange = null;
                        if (ref[0] === '#') {
                            if (thisRowExisted) {
                                throw 'Invalid Table Refernce.';
                            }
                            switch (ref) {
                                case '#all':
                                    tmpRange = table.range.clone();
                                    break;
                                case '#data':
                                    tmpRange = table.getDataRange();
                                    break;
                                case '#headers':
                                    tmpRange = table.getHeaderRange();
                                    break;
                                case '#totals':
                                    tmpRange = table.getTotalRange();
                                    break;
                                case '#this row':
                                    if (this._rowIndex >= table.range.topRow && this._rowIndex <= table.range.bottomRow) {
                                        tmpRange = new grid.CellRange(this._rowIndex, table.range.leftCol, this._rowIndex, table.range.rightCol);
                                    }
                                    else {
                                        throw 'The row is out of the table (' + table.name + ') range.';
                                    }
                                    break;
                                default:
                                    throw 'Invalid Table Refernce.';
                            }
                            if (tmpRange == null) {
                                throw 'Invalid Table Refernce.';
                            }
                            if (range == null) {
                                range = tmpRange;
                            }
                            else {
                                range.row = range.topRow < tmpRange.topRow ? range.topRow : tmpRange.topRow;
                                ;
                                range.row2 = range.bottomRow > tmpRange.bottomRow ? range.bottomRow : tmpRange.bottomRow;
                            }
                        }
                        else {
                            columnExisted = true;
                            colRefs = ref.split(':');
                            for (var j = 0; j < colRefs.length; j++) {
                                if (colRefs.length > 2) {
                                    throw 'Invalid Table Column Refernce.';
                                }
                                ref = colRefs[j];
                                if (ref[0] === '@') {
                                    if (colRefs.length > 1 || range != null) {
                                        throw 'Invalid Table Column Refernce.';
                                    }
                                    range = table.getColumnRange(ref.substring(1));
                                    if (range == null) {
                                        throw 'Invalid Table Refernce.';
                                    }
                                    if (this._rowIndex >= range.topRow && this._rowIndex <= range.bottomRow) {
                                        range.row = this._rowIndex;
                                        range.row2 = this._rowIndex;
                                        return range;
                                    }
                                    else {
                                        throw 'The row is out of the table (' + table.name + ') range.';
                                    }
                                }
                                else {
                                    tmpRange = table.getColumnRange(ref);
                                    if (tmpRange == null) {
                                        throw 'Invalid Table Refernce.';
                                    }
                                }
                                if (j === 0) {
                                    if (range == null) {
                                        range = tmpRange;
                                    }
                                    else {
                                        range.col = tmpRange.col;
                                    }
                                }
                                range.col2 = tmpRange.col;
                                tmpRange = null;
                            }
                        }
                    }
                    return range;
                };
                // Get the aggregate result for the CalcEngine.
                _CalcEngine.prototype._getAggregateResult = function (aggType, params, sheet) {
                    var list = this._getItemList(params, sheet), result;
                    result = wijmo.getAggregate(aggType, list.items);
                    if (list.isDate) {
                        result = new Date(result);
                    }
                    return result;
                };
                // Get the flexsheet aggregate result for the CalcEngine
                _CalcEngine.prototype._getFlexSheetAggregateResult = function (aggType, params, sheet) {
                    var list, sumList, num, order;
                    switch (aggType) {
                        case _FlexSheetAggregate.Count:
                            list = this._getItemList(params, sheet, true, false);
                            return this._countNumberCells(list.items);
                        case _FlexSheetAggregate.CountA:
                            list = this._getItemList(params, sheet, false, false);
                            return list.items.length;
                        case _FlexSheetAggregate.ConutBlank:
                            list = this._getItemList(params, sheet, false, true);
                            return this._countBlankCells(list.items);
                        case _FlexSheetAggregate.Rank:
                            num = sheet_1._Expression.toNumber(params[0], this._rowIndex, this._columnIndex, sheet);
                            order = params[2] ? sheet_1._Expression.toNumber(params[2], this._rowIndex, this._columnIndex, sheet) : 0;
                            if (isNaN(num)) {
                                throw 'Invalid number.';
                            }
                            if (isNaN(order)) {
                                throw 'Invalid order.';
                            }
                            params[1] = this._ensureNonFunctionExpression(params[1]);
                            if (params[1] instanceof sheet_1._CellRangeExpression) {
                                list = this._getItemList([params[1]], sheet);
                                return this._getRankOfCellRange(num, list.items, order);
                            }
                            throw 'Invalid Cell Reference.';
                        case _FlexSheetAggregate.CountIf:
                            params[0] = this._ensureNonFunctionExpression(params[0]);
                            if (params[0] instanceof sheet_1._CellRangeExpression) {
                                list = this._getItemList([params[0]], sheet, false);
                                return this._countCellsByCriterias([list.items], [params[1]], sheet);
                            }
                            throw 'Invalid Cell Reference.';
                        case _FlexSheetAggregate.CountIfs:
                            return this._handleCountIfs(params, sheet);
                        case _FlexSheetAggregate.SumIf:
                            params[0] = this._ensureNonFunctionExpression(params[0]);
                            if (params[0] instanceof sheet_1._CellRangeExpression) {
                                list = this._getItemList([params[0]], sheet, false);
                                params[2] = this._ensureNonFunctionExpression(params[2]);
                                if (params[2] != null && params[2] instanceof sheet_1._CellRangeExpression) {
                                    sumList = this._getItemList([params[2]], sheet);
                                }
                                return this._sumCellsByCriterias([list.items], [params[1]], sumList ? sumList.items : null, sheet);
                            }
                            throw 'Invalid Cell Reference.';
                        case _FlexSheetAggregate.SumIfs:
                            return this._handleSumIfs(params, sheet);
                        case _FlexSheetAggregate.Product:
                            list = this._getItemList(params, sheet);
                            return this._getProductOfNumbers(list.items);
                    }
                    throw 'Invalid aggregate type.';
                };
                // Get item list for aggregate processing.
                _CalcEngine.prototype._getItemList = function (params, sheet, needParseToNum, isGetEmptyValue, isGetHiddenValue, columnIndex) {
                    if (needParseToNum === void 0) { needParseToNum = true; }
                    if (isGetEmptyValue === void 0) { isGetEmptyValue = false; }
                    if (isGetHiddenValue === void 0) { isGetHiddenValue = true; }
                    var items = new Array(), item, index, cellIndex, cellValues, param, isDate = true;
                    for (index = 0; index < params.length; index++) {
                        param = params[index];
                        // When meets the CellRangeExpression, 
                        // we need set the value of the each cell in the cell range into the array to get the aggregate result.
                        param = this._ensureNonFunctionExpression(param);
                        if (param instanceof sheet_1._CellRangeExpression) {
                            cellValues = param.getValues(isGetHiddenValue, columnIndex, sheet);
                            cells: for (cellIndex = 0; cellIndex < cellValues.length; cellIndex++) {
                                item = cellValues[cellIndex];
                                if (!isGetEmptyValue && (item == null || item === '')) {
                                    continue cells;
                                }
                                isDate = isDate && (item instanceof Date);
                                item = needParseToNum && !wijmo.isBoolean(item) ? +item : item;
                                items.push(item);
                            }
                        }
                        else {
                            item = param instanceof sheet_1._Expression ? param.evaluate(this._rowIndex, this._columnIndex, sheet) : param;
                            if (!wijmo.isPrimitive(item)) {
                                item = item.value;
                            }
                            if (!isGetEmptyValue && (item == null || item === '')) {
                                continue;
                            }
                            isDate = isDate && (item instanceof Date);
                            item = needParseToNum ? +item : item;
                            items.push(item);
                        }
                    }
                    if (items.length === 0) {
                        isDate = false;
                    }
                    return {
                        isDate: isDate,
                        items: items
                    };
                };
                // Count blank cells
                _CalcEngine.prototype._countBlankCells = function (items) {
                    var i = 0, count = 0, item;
                    for (; i < items.length; i++) {
                        item = items[i];
                        if (item == null || (wijmo.isString(item) && item === '') || (wijmo.isNumber(item) && isNaN(item))) {
                            count++;
                        }
                    }
                    return count;
                };
                // Count number cells
                _CalcEngine.prototype._countNumberCells = function (items) {
                    var i = 0, count = 0, item;
                    for (; i < items.length; i++) {
                        item = items[i];
                        if (item != null && wijmo.isNumber(item) && !isNaN(item)) {
                            count++;
                        }
                    }
                    return count;
                };
                // Get the rank for the number in the cell range.
                _CalcEngine.prototype._getRankOfCellRange = function (num, items, order) {
                    if (order === void 0) { order = 0; }
                    var i = 0, rank = 0, item;
                    // Sort the items list
                    if (!order) {
                        items.sort(function (a, b) {
                            if (isNaN(a) || isNaN(b)) {
                                return 1;
                            }
                            return b - a;
                        });
                    }
                    else {
                        items.sort(function (a, b) {
                            if (isNaN(a) || isNaN(b)) {
                                return -1;
                            }
                            return a - b;
                        });
                    }
                    for (; i < items.length; i++) {
                        item = items[i];
                        if (isNaN(item)) {
                            continue;
                        }
                        rank++;
                        if (num === item) {
                            return rank;
                        }
                    }
                    throw num + ' is not in the cell range.';
                };
                // Handles the CountIfs function
                _CalcEngine.prototype._handleCountIfs = function (params, sheet) {
                    var i = 0, itemsList = [], critreiaList = [], list, cellExpr, rowCount, colCount;
                    if (params.length % 2 !== 0) {
                        throw 'Invalid params.';
                    }
                    for (; i < params.length / 2; i++) {
                        cellExpr = params[2 * i];
                        cellExpr = this._ensureNonFunctionExpression(cellExpr);
                        if (cellExpr instanceof sheet_1._CellRangeExpression) {
                            if (i === 0) {
                                if (cellExpr.cells) {
                                    rowCount = cellExpr.cells.rowSpan;
                                    colCount = cellExpr.cells.columnSpan;
                                }
                                else {
                                    throw 'Invalid Cell Reference.';
                                }
                            }
                            else {
                                if (!cellExpr.cells) {
                                    throw 'Invalid Cell Reference.';
                                }
                                else if (cellExpr.cells.rowSpan !== rowCount || cellExpr.cells.columnSpan !== colCount) {
                                    throw 'The row span and column span of each cell range has to be same with each other.';
                                }
                            }
                            list = this._getItemList([cellExpr], sheet, false);
                            itemsList[i] = list.items;
                            critreiaList[i] = params[2 * i + 1];
                        }
                        else {
                            throw 'Invalid Cell Reference.';
                        }
                    }
                    return this._countCellsByCriterias(itemsList, critreiaList, sheet);
                };
                // Count the cells that meet the criteria.
                _CalcEngine.prototype._countCellsByCriterias = function (itemsList, criterias, sheet, countItems) {
                    var i = 0, j = 0, count = 0, rangeLength = itemsList[0].length, parsedRightExprs = [], result, countItem, items, leftExpr, rightExpr;
                    for (; j < criterias.length; j++) {
                        rightExpr = sheet_1._Expression.toString(criterias[j], this._rowIndex, this._columnIndex, sheet);
                        if (rightExpr === '*') {
                            parsedRightExprs.push(rightExpr);
                        }
                        else {
                            parsedRightExprs.push(this._parseRightExpr(rightExpr));
                        }
                    }
                    for (; i < rangeLength; i++) {
                        result = false;
                        criteriaLoop: for (j = 0; j < itemsList.length; j++) {
                            items = itemsList[j];
                            leftExpr = items[i];
                            rightExpr = parsedRightExprs[j];
                            if (typeof rightExpr === 'string') {
                                if (rightExpr !== '*' && (leftExpr == null || leftExpr === '')) {
                                    result = false;
                                    break criteriaLoop;
                                }
                                result = rightExpr === '*' || this.evaluate(this._combineExpr(leftExpr, rightExpr), null, sheet, this._rowIndex, this._columnIndex);
                                if (!result) {
                                    break criteriaLoop;
                                }
                            }
                            else {
                                result = result = rightExpr.reg.test(leftExpr.toString()) === rightExpr.checkMathces;
                                if (!result) {
                                    break criteriaLoop;
                                }
                            }
                        }
                        if (result) {
                            if (countItems) {
                                countItem = countItems[i];
                                if (countItem != null && wijmo.isNumber(countItem) && !isNaN(countItem)) {
                                    count++;
                                }
                            }
                            else {
                                count++;
                            }
                        }
                    }
                    return count;
                };
                // Handles the SumIfs function
                _CalcEngine.prototype._handleSumIfs = function (params, sheet) {
                    var i = 1, itemsList = [], critreiaList = [], list, sumList, sumCellExpr, cellExpr, rowCount, colCount;
                    if (params.length % 2 !== 1) {
                        throw 'Invalid params.';
                    }
                    sumCellExpr = params[0];
                    sumCellExpr = this._ensureNonFunctionExpression(sumCellExpr);
                    if (sumCellExpr instanceof sheet_1._CellRangeExpression) {
                        if (sumCellExpr.cells) {
                            rowCount = sumCellExpr.cells.rowSpan;
                            colCount = sumCellExpr.cells.columnSpan;
                        }
                        else {
                            throw 'Invalid Sum Cell Reference.';
                        }
                        sumList = this._getItemList([sumCellExpr], sheet);
                    }
                    else {
                        throw 'Invalid Sum Cell Reference.';
                    }
                    for (; i < (params.length + 1) / 2; i++) {
                        cellExpr = params[2 * i - 1];
                        cellExpr = this._ensureNonFunctionExpression(cellExpr);
                        if (cellExpr instanceof sheet_1._CellRangeExpression) {
                            if (!cellExpr.cells) {
                                throw 'Invalid Criteria Cell Reference.';
                            }
                            else if (cellExpr.cells.rowSpan !== rowCount || cellExpr.cells.columnSpan !== colCount) {
                                throw 'The row span and column span of each cell range has to be same with each other.';
                            }
                            list = this._getItemList([cellExpr], sheet, false);
                            itemsList[i - 1] = list.items;
                            critreiaList[i - 1] = params[2 * i];
                        }
                        else {
                            throw 'Invalid Criteria Cell Reference.';
                        }
                    }
                    return this._sumCellsByCriterias(itemsList, critreiaList, sumList.items, sheet);
                };
                // Gets the sum of the numeric values in the cells specified by a given criteria.
                _CalcEngine.prototype._sumCellsByCriterias = function (itemsList, criterias, sumItems, sheet) {
                    var i = 0, j = 0, sum = 0, sumItem, rangeLength = itemsList[0].length, parsedRightExprs = [], result, items, leftExpr, rightExpr;
                    if (sumItems == null) {
                        sumItems = itemsList[0];
                    }
                    for (; j < criterias.length; j++) {
                        rightExpr = sheet_1._Expression.toString(criterias[j], this._rowIndex, this._columnIndex, sheet);
                        if (rightExpr === '*') {
                            parsedRightExprs.push(rightExpr);
                        }
                        else {
                            parsedRightExprs.push(this._parseRightExpr(rightExpr));
                        }
                    }
                    for (; i < rangeLength; i++) {
                        result = false;
                        sumItem = sumItems[i];
                        criteriaLoop: for (j = 0; j < itemsList.length; j++) {
                            items = itemsList[j];
                            leftExpr = items[i];
                            rightExpr = parsedRightExprs[j];
                            if (typeof rightExpr === 'string') {
                                if (rightExpr !== '*' && (leftExpr == null || leftExpr === '')) {
                                    result = false;
                                    break criteriaLoop;
                                }
                                result = rightExpr === '*' || this.evaluate(this._combineExpr(leftExpr, rightExpr), null, sheet, this._rowIndex, this._columnIndex);
                                if (!result) {
                                    break criteriaLoop;
                                }
                            }
                            else {
                                result = rightExpr.reg.test(leftExpr.toString()) === rightExpr.checkMathces;
                                if (!result) {
                                    break criteriaLoop;
                                }
                            }
                        }
                        if (result && wijmo.isNumber(sumItem) && !isNaN(sumItem)) {
                            sum += sumItem;
                        }
                    }
                    return sum;
                };
                // Get product for numbers
                _CalcEngine.prototype._getProductOfNumbers = function (items) {
                    var item, i = 0, product = 1, containsValidNum = false;
                    if (items) {
                        for (; i < items.length; i++) {
                            item = items[i];
                            if (wijmo.isNumber(item) && !isNaN(item)) {
                                product *= item;
                                containsValidNum = true;
                            }
                        }
                    }
                    if (containsValidNum) {
                        return product;
                    }
                    return 0;
                };
                //  Handle the subtotal function.
                _CalcEngine.prototype._handleSubtotal = function (params, sheet) {
                    var func, list, aggType, result, isGetHiddenValue = true;
                    func = sheet_1._Expression.toNumber(params[0], this._rowIndex, this._columnIndex, sheet);
                    if ((func >= 1 && func <= 11) || (func >= 101 && func <= 111)) {
                        if (func >= 101 && func <= 111) {
                            isGetHiddenValue = false;
                        }
                        func = wijmo.asEnum(func, _SubtotalFunction);
                        list = this._getItemList(params.slice(1), sheet, true, false, isGetHiddenValue);
                        switch (func) {
                            case _SubtotalFunction.Count:
                            case _SubtotalFunction.CountWithoutHidden:
                                return this._countNumberCells(list.items);
                            case _SubtotalFunction.CountA:
                            case _SubtotalFunction.CountAWithoutHidden:
                                return list.items.length;
                            case _SubtotalFunction.Product:
                            case _SubtotalFunction.ProductWithoutHidden:
                                return this._getProductOfNumbers(list.items);
                            case _SubtotalFunction.Average:
                            case _SubtotalFunction.AverageWithoutHidden:
                                aggType = wijmo.Aggregate.Avg;
                                break;
                            case _SubtotalFunction.Max:
                            case _SubtotalFunction.MaxWithoutHidden:
                                aggType = wijmo.Aggregate.Max;
                                break;
                            case _SubtotalFunction.Min:
                            case _SubtotalFunction.MinWithoutHidden:
                                aggType = wijmo.Aggregate.Min;
                                break;
                            case _SubtotalFunction.Std:
                            case _SubtotalFunction.StdWithoutHidden:
                                aggType = wijmo.Aggregate.Std;
                                break;
                            case _SubtotalFunction.StdPop:
                            case _SubtotalFunction.StdPopWithoutHidden:
                                aggType = wijmo.Aggregate.StdPop;
                                break;
                            case _SubtotalFunction.Sum:
                            case _SubtotalFunction.SumWithoutHidden:
                                aggType = wijmo.Aggregate.Sum;
                                break;
                            case _SubtotalFunction.Var:
                            case _SubtotalFunction.VarWithoutHidden:
                                aggType = wijmo.Aggregate.Var;
                                break;
                            case _SubtotalFunction.VarPop:
                            case _SubtotalFunction.VarPopWithoutHidden:
                                aggType = wijmo.Aggregate.VarPop;
                                break;
                        }
                        result = wijmo.getAggregate(aggType, list.items);
                        if (list.isDate) {
                            result = new Date(result);
                        }
                        return result;
                    }
                    throw 'Invalid Subtotal function.';
                };
                // Handle the DCount function.
                _CalcEngine.prototype._handleDCount = function (params, sheet) {
                    var cellExpr = params[0], criteriaCellExpr = params[2], count = 0, field, columnIndex, list;
                    cellExpr = this._ensureNonFunctionExpression(cellExpr);
                    criteriaCellExpr = this._ensureNonFunctionExpression(criteriaCellExpr);
                    if (cellExpr instanceof sheet_1._CellRangeExpression && criteriaCellExpr instanceof sheet_1._CellRangeExpression) {
                        field = params[1].evaluate(this._rowIndex, this._columnIndex, sheet);
                        columnIndex = this._getColumnIndexByField(cellExpr, field);
                        list = this._getItemList([cellExpr], sheet, true, false, true, columnIndex);
                        if (list.items && list.items.length > 1) {
                            return this._DCountWithCriterias(list.items.slice(1), cellExpr, criteriaCellExpr);
                        }
                    }
                    throw 'Invalid Count Cell Reference.';
                };
                // Counts the cells by the specified criterias.
                _CalcEngine.prototype._DCountWithCriterias = function (countItems, countRef, criteriaRef) {
                    var criteriaCells = criteriaRef.cells, count = 0, countSheet, criteriaSheet, fieldRowIndex, rowIndex, colIndex, criteriaColIndex, criteria, criteriaField, list, itemsList, criteriaList;
                    countSheet = this._getSheet(countRef.sheetRef);
                    criteriaSheet = this._getSheet(criteriaRef.sheetRef);
                    if (criteriaCells.rowSpan > 1) {
                        fieldRowIndex = criteriaCells.topRow;
                        for (rowIndex = criteriaCells.bottomRow; rowIndex > criteriaCells.topRow; rowIndex--) {
                            itemsList = [];
                            criteriaList = [];
                            for (colIndex = criteriaCells.leftCol; colIndex <= criteriaCells.rightCol; colIndex++) {
                                // Collects the criterias and related cell reference.
                                criteria = this._owner.getCellValue(rowIndex, colIndex, false, criteriaSheet);
                                if (criteria != null && criteria !== '') {
                                    criteriaList.push(new sheet_1._Expression(criteria));
                                    criteriaField = this._owner.getCellValue(fieldRowIndex, colIndex, false, criteriaSheet);
                                    criteriaColIndex = this._getColumnIndexByField(countRef, criteriaField);
                                    list = this._getItemList([countRef], countSheet, false, false, true, criteriaColIndex);
                                    if (list.items != null && list.items.length > 1) {
                                        itemsList.push(list.items.slice(1));
                                    }
                                    else {
                                        throw 'Invalid Count Cell Reference.';
                                    }
                                }
                            }
                            count += this._countCellsByCriterias(itemsList, criteriaList, countSheet, countItems);
                        }
                        return count;
                    }
                    throw 'Invalid Criteria Cell Reference.';
                };
                // Get column index of the count cell range by the field.
                _CalcEngine.prototype._getColumnIndexByField = function (cellExpr, field) {
                    var cells, sheet, columnIndex, value, rowIndex;
                    cells = cellExpr.cells;
                    rowIndex = cells.topRow;
                    if (rowIndex === -1) {
                        throw 'Invalid Count Cell Reference.';
                    }
                    if (wijmo.isInt(field) && !isNaN(field)) {
                        // if the field is integer, we consider the field it the column index of the count cell range.
                        if (field >= 1 && field <= cells.columnSpan) {
                            columnIndex = cells.leftCol + field - 1;
                            return columnIndex;
                        }
                    }
                    else {
                        sheet = this._getSheet(cellExpr.sheetRef);
                        for (columnIndex = cells.leftCol; columnIndex <= cells.rightCol; columnIndex++) {
                            value = this._owner.getCellValue(rowIndex, columnIndex, false, sheet);
                            field = wijmo.isString(field) ? field.toLowerCase() : field;
                            value = wijmo.isString(value) ? value.toLowerCase() : value;
                            if (field === value) {
                                return columnIndex;
                            }
                        }
                    }
                    throw 'Invalid field.';
                };
                // Gets the result of the sumProduct formula. 
                _CalcEngine.prototype._getSumProduct = function (params, sheet) {
                    var product, sum = 0, list = this._getItemListForSumProduct(params, sheet), xAxisCnt, yAxisCnt;
                    if (list.length > 0) {
                        xAxisCnt = list[0].length;
                        yAxisCnt = list.length;
                        for (var ci = 0; ci < xAxisCnt; ci++) {
                            product = 1;
                            for (var ri = 0; ri < yAxisCnt; ri++) {
                                product *= list[ri][ci];
                            }
                            sum += product;
                        }
                    }
                    return sum;
                };
                // Gets item list for the sumProduct formula.
                _CalcEngine.prototype._getItemListForSumProduct = function (params, sheet) {
                    var list = [new Array()], items, item, index, cellIndex, cellValues, param;
                    for (index = 0; index < params.length; index++) {
                        param = params[index];
                        items = new Array(),
                            // When meets the CellRangeExpression, 
                            // we need set the value of the each cell in the cell range into the array to get the aggregate result.
                            param = this._ensureNonFunctionExpression(param);
                        if (param instanceof sheet_1._CellRangeExpression) {
                            cellValues = param.getValues(true, null, sheet);
                            for (cellIndex = 0; cellIndex < cellValues.length; cellIndex++) {
                                item = cellValues[cellIndex];
                                items.push(+item);
                            }
                        }
                        else {
                            item = param instanceof sheet_1._Expression ? param.evaluate(this._rowIndex, this._columnIndex, sheet) : param;
                            items.push(+item);
                        }
                        if (index > 0) {
                            if (items.length !== list[0].length) {
                                throw 'The cell ranges of the sumProduct formula must have the same dimensions.';
                            }
                        }
                        list[index] = items;
                    }
                    return list;
                };
                // Gets the sheet by the sheetRef.
                _CalcEngine.prototype._getSheet = function (sheetRef) {
                    var i = 0, sheet;
                    if (sheetRef) {
                        for (; i < this._owner.sheets.length; i++) {
                            sheet = this._owner.sheets[i];
                            if (sheet.name === sheetRef) {
                                break;
                            }
                        }
                    }
                    return sheet;
                };
                // Parse the right expression for countif countifs sumif and sumifs function.
                _CalcEngine.prototype._parseRightExpr = function (rightExpr) {
                    var match, matchReg, checkMathces = false;
                    // Match the criteria that contains '?' such as '??match' and etc..
                    if (rightExpr.indexOf('?') > -1 || rightExpr.indexOf('*') > -1) {
                        match = rightExpr.match(/([\?\*]*)(\w+)([\?\*]*)(\w+)([\?\*]*)/);
                        if (match != null && match.length === 6) {
                            matchReg = new RegExp('^' + (match[1].length > 0 ? this._parseRegCriteria(match[1]) : '') + match[2]
                                + (match[3].length > 0 ? this._parseRegCriteria(match[3]) : '') + match[4]
                                + (match[5].length > 0 ? this._parseRegCriteria(match[5]) : '') + '$', 'i');
                        }
                        else {
                            throw 'Invalid Criteria.';
                        }
                        if (/^[<>=]/.test(rightExpr)) {
                            if (rightExpr.trim()[0] === '=') {
                                checkMathces = true;
                            }
                        }
                        else {
                            checkMathces = true;
                        }
                        return {
                            reg: matchReg,
                            checkMathces: checkMathces
                        };
                    }
                    else {
                        if (!isNaN(+rightExpr)) {
                            rightExpr = '=' + (+rightExpr);
                        }
                        else if (/^\w/.test(rightExpr)) {
                            rightExpr = '="' + rightExpr + '"';
                        }
                        else if (/^[<>=]{1,2}\s*-?.+$/.test(rightExpr)) {
                            rightExpr = rightExpr.replace(/([<>=]{1,2})\s*(-?.+)/, '$1"$2"');
                        }
                        else {
                            throw 'Invalid Criteria.';
                        }
                        return rightExpr;
                    }
                };
                // combine the left expression and right expression for countif countifs sumif and sumifs function.
                _CalcEngine.prototype._combineExpr = function (leftExpr, rightExpr) {
                    if (wijmo.isString(leftExpr) || wijmo.isDate(leftExpr)) {
                        leftExpr = '"' + leftExpr + '"';
                    }
                    leftExpr = '=' + leftExpr;
                    return leftExpr + rightExpr;
                };
                // Parse regex criteria for '?' and '*'
                _CalcEngine.prototype._parseRegCriteria = function (criteria) {
                    var i = 0, questionMarkCnt = 0, regString = '';
                    for (; i < criteria.length; i++) {
                        if (criteria[i] === '*') {
                            if (questionMarkCnt > 0) {
                                regString += '\\w{' + questionMarkCnt + '}';
                                questionMarkCnt = 0;
                            }
                            regString += '\\w*';
                        }
                        else if (criteria[i] === '?') {
                            questionMarkCnt++;
                        }
                    }
                    if (questionMarkCnt > 0) {
                        regString += '\\w{' + questionMarkCnt + '}';
                    }
                    return regString;
                };
                // Calculate the rate.
                // The algorithm of the rate calculation refers http://stackoverflow.com/questions/3198939/recreate-excel-rate-function-using-newtons-method
                _CalcEngine.prototype._calculateRate = function (params, sheet) {
                    var FINANCIAL_PRECISION = 0.0000001, FINANCIAL_MAX_ITERATIONS = 20, i = 0, x0 = 0, x1, rate, nper, pmt, pv, fv, type, guess, y, f, y0, y1;
                    nper = sheet_1._Expression.toNumber(params[0], this._rowIndex, this._columnIndex, sheet);
                    pmt = sheet_1._Expression.toNumber(params[1], this._rowIndex, this._columnIndex, sheet);
                    pv = sheet_1._Expression.toNumber(params[2], this._rowIndex, this._columnIndex, sheet);
                    fv = params[3] != null ? sheet_1._Expression.toNumber(params[3], this._rowIndex, this._columnIndex, sheet) : 0;
                    type = params[4] != null ? sheet_1._Expression.toNumber(params[4], this._rowIndex, this._columnIndex, sheet) : 0;
                    guess = params[5] != null ? sheet_1._Expression.toNumber(params[5], this._rowIndex, this._columnIndex, sheet) : 0.1;
                    rate = guess;
                    if (Math.abs(rate) < FINANCIAL_PRECISION) {
                        y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv;
                    }
                    else {
                        f = Math.exp(nper * Math.log(1 + rate));
                        y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
                    }
                    y0 = pv + pmt * nper + fv;
                    y1 = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
                    // find root by secant method
                    x1 = rate;
                    while ((Math.abs(y0 - y1) > FINANCIAL_PRECISION) && (i < FINANCIAL_MAX_ITERATIONS)) {
                        rate = (y1 * x0 - y0 * x1) / (y1 - y0);
                        x0 = x1;
                        x1 = rate;
                        if (Math.abs(rate) < FINANCIAL_PRECISION) {
                            y = pv * (1 + nper * rate) + pmt * (1 + rate * type) * nper + fv;
                        }
                        else {
                            f = Math.exp(nper * Math.log(1 + rate));
                            y = pv * f + pmt * (1 / rate + type) * (f - 1) + fv;
                        }
                        y0 = y1;
                        y1 = y;
                        ++i;
                    }
                    if (Math.abs(y0 - y1) > FINANCIAL_PRECISION && i === FINANCIAL_MAX_ITERATIONS) {
                        throw 'It is not able to calculate the rate with current parameters.';
                    }
                    return rate;
                };
                // Handle the hlookup function.
                _CalcEngine.prototype._handleHLookup = function (params, sheet) {
                    var lookupVal = params[0].evaluate(this._rowIndex, this._columnIndex, sheet), cellExpr = params[1], rowNum = sheet_1._Expression.toNumber(params[2], this._rowIndex, this._columnIndex, sheet), approximateMatch = params[3] != null ? sheet_1._Expression.toBoolean(params[3], this._rowIndex, this._columnIndex, sheet) : true, cells, colNum;
                    if (lookupVal == null || lookupVal == '') {
                        throw 'Invalid lookup value.';
                    }
                    if (isNaN(rowNum) || rowNum < 0) {
                        throw 'Invalid row index.';
                    }
                    cellExpr = this._ensureNonFunctionExpression(cellExpr);
                    if (cellExpr instanceof sheet_1._CellRangeExpression) {
                        cells = cellExpr.cells;
                        if (rowNum > cells.rowSpan) {
                            throw 'Row index is out of the cell range.';
                        }
                        if (approximateMatch) {
                            colNum = this._exactMatch(lookupVal, cells, sheet, false);
                            if (colNum === -1) {
                                colNum = this._approximateMatch(lookupVal, cells, sheet);
                            }
                        }
                        else {
                            colNum = this._exactMatch(lookupVal, cells, sheet);
                        }
                        if (colNum === -1) {
                            throw 'Lookup Value is not found.';
                        }
                        return this._owner.getCellValue(cells.topRow + rowNum - 1, colNum, false, sheet);
                    }
                    throw 'Invalid Cell Reference.';
                };
                // Handle the exact match for the hlookup.
                _CalcEngine.prototype._exactMatch = function (lookupValue, cells, sheet, needHandleWildCard) {
                    if (needHandleWildCard === void 0) { needHandleWildCard = true; }
                    var rowIndex = cells.topRow, colIndex, value, match, matchReg;
                    if (wijmo.isString(lookupValue)) {
                        lookupValue = lookupValue.toLowerCase();
                    }
                    // handle the wildcard question mark (?) and asterisk (*) for the lookup value.
                    if (needHandleWildCard && wijmo.isString(lookupValue) && (lookupValue.indexOf('?') > -1 || lookupValue.indexOf('*') > -1)) {
                        match = lookupValue.match(/([\?\*]*)(\w+)([\?\*]*)(\w+)([\?\*]*)/);
                        if (match != null && match.length === 6) {
                            matchReg = new RegExp('^' + (match[1].length > 0 ? this._parseRegCriteria(match[1]) : '') + match[2]
                                + (match[3].length > 0 ? this._parseRegCriteria(match[3]) : '') + match[4]
                                + (match[5].length > 0 ? this._parseRegCriteria(match[5]) : '') + '$', 'i');
                        }
                        else {
                            throw 'Invalid lookup value.';
                        }
                    }
                    for (colIndex = cells.leftCol; colIndex <= cells.rightCol; colIndex++) {
                        value = this._owner.getCellValue(rowIndex, colIndex, false, sheet);
                        if (matchReg != null) {
                            if (matchReg.test(value)) {
                                return colIndex;
                            }
                        }
                        else {
                            if (wijmo.isString(value)) {
                                value = value.toLowerCase();
                            }
                            if (lookupValue === value) {
                                return colIndex;
                            }
                        }
                    }
                    return -1;
                };
                // Handle the approximate match for the hlookup.
                _CalcEngine.prototype._approximateMatch = function (lookupValue, cells, sheet) {
                    var val, colIndex, rowIndex = cells.topRow, cellValues = [], i = 0;
                    if (wijmo.isString(lookupValue)) {
                        lookupValue = lookupValue.toLowerCase();
                    }
                    for (colIndex = cells.leftCol; colIndex <= cells.rightCol; colIndex++) {
                        val = this._owner.getCellValue(rowIndex, colIndex, false, sheet);
                        val = isNaN(+val) ? val : +val;
                        cellValues.push({ value: val, index: colIndex });
                    }
                    // Sort the cellValues array with descent order.
                    cellValues.sort(function (a, b) {
                        if (wijmo.isString(a.value)) {
                            a.value = a.value.toLowerCase();
                        }
                        if (wijmo.isString(b.value)) {
                            b.value = b.value.toLowerCase();
                        }
                        if (a.value > b.value) {
                            return -1;
                        }
                        else if (a.value === b.value) {
                            return b.index - a.index;
                        }
                        return 1;
                    });
                    for (; i < cellValues.length; i++) {
                        val = cellValues[i];
                        if (wijmo.isString(val.value)) {
                            val.value = val.value.toLowerCase();
                        }
                        // return the column index of the first value that less than lookup value.
                        if (lookupValue > val.value) {
                            return val.index;
                        }
                    }
                    throw 'Lookup Value is not found.';
                };
                // Parse the number value to scietific notation.
                _CalcEngine.prototype._parseToScientificValue = function (value, intCoefficientFmt, decimalCoefficientFmt, intExponentFmt, decimalExponentFmt) {
                    var coefficientNumber, sign, result, dotIndex, decimalLength, exponent = 0;
                    if (Math.abs(value) >= 1) {
                        sign = '+';
                        coefficientNumber = Math.pow(10, intCoefficientFmt.length);
                        while (value > coefficientNumber) {
                            value /= coefficientNumber;
                            exponent += intCoefficientFmt.length;
                        }
                    }
                    else {
                        sign = '-';
                        coefficientNumber = Math.pow(10, intCoefficientFmt.length);
                        while ((value * coefficientNumber) < coefficientNumber) {
                            value *= coefficientNumber;
                            exponent += intCoefficientFmt.length;
                        }
                    }
                    result = wijmo.Globalize.format(value, 'D' + intCoefficientFmt.length);
                    if (decimalCoefficientFmt) {
                        result += wijmo.Globalize.format(value - Math.floor(value), intCoefficientFmt + decimalCoefficientFmt).substring(1);
                        dotIndex = result.indexOf('.');
                        if (dotIndex > -1) {
                            decimalLength = result.length - 1 - result.indexOf('.');
                        }
                        else {
                            result += '.';
                            decimalLength = 0;
                        }
                        while (decimalLength < decimalCoefficientFmt.length - 1) {
                            result += '0';
                            decimalLength++;
                        }
                    }
                    result += 'E' + sign + wijmo.Globalize.format(exponent, 'D' + intExponentFmt.length);
                    if (decimalExponentFmt) {
                        result += '.';
                        for (var i = 1; i < decimalExponentFmt.length; i++) {
                            result += '0';
                        }
                    }
                    return result;
                };
                // Check the expression cache.
                _CalcEngine.prototype._checkCache = function (expression) {
                    var expr = this._expressionCache[expression] || this._expressionCache[this._rowIndex + '_' + this._columnIndex + ':' + expression];
                    if (expr) {
                        return expr;
                    }
                    expr = this._parse(expression);
                    if (this._token.tokenID !== _TokenID.END || this._token.tokenType !== _TokenType.GROUP) {
                        throw 'Invalid Expression: ' + expression;
                    }
                    // when the size of the expression cache is greater than 10000,
                    // We will release the expression cache.
                    if (this._cacheSize > 10000) {
                        this._clearExpressionCache();
                    }
                    this._expressionCache[(this._containsCellRef ? this._rowIndex + '_' + this._columnIndex + ':' : '') + expression] = expr;
                    this._cacheSize++;
                    return expr;
                };
                // Ensure current is not function expression.
                _CalcEngine.prototype._ensureNonFunctionExpression = function (expr, sheet) {
                    while (expr instanceof sheet_1._FunctionExpression) {
                        expr = expr.evaluate(this._rowIndex, this._columnIndex, sheet);
                    }
                    return expr;
                };
                // Gets the defined name item of FlexSheet by its name.
                _CalcEngine.prototype._getDefinedName = function (name, sheetName) {
                    var item, globalItem;
                    for (var i = 0; i < this._owner.definedNames.length; i++) {
                        item = this._owner.definedNames[i];
                        if (item.name.toLowerCase() === name) {
                            if (item.sheetName) {
                                if (item.sheetName.toLowerCase() === sheetName) {
                                    return item;
                                }
                            }
                            else {
                                globalItem = item;
                            }
                        }
                    }
                    return globalItem;
                };
                // Gets the name of sheet where the table is located in.
                _CalcEngine.prototype._getTableRelatedSheet = function (tableName) {
                    for (var sheetIndex = 0; sheetIndex < this._owner.sheets.length; sheetIndex++) {
                        var sheet = this._owner.sheets[sheetIndex];
                        for (var index = 0; index < sheet.tableNames.length; index++) {
                            if (sheet.tableNames[index].toLowerCase() === tableName) {
                                return sheet.name;
                            }
                        }
                    }
                    return '';
                };
                return _CalcEngine;
            }());
            sheet_1._CalcEngine = _CalcEngine;
            /*
             * Defines the Token class.
             *
             * It assists the expression instance to evaluate value.
             */
            var _Token = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:Token class.
                 *
                 * @param val The value of the token.
                 * @param tkID The @see:TokenID value of the token.
                 * @param tkType The @see:TokenType value of the token.
                 */
                function _Token(val, tkID, tkType) {
                    this._value = val;
                    this._tokenID = tkID;
                    this._tokenType = tkType;
                }
                Object.defineProperty(_Token.prototype, "value", {
                    /*
                     * Gets the value of the token instance.
                     */
                    get: function () {
                        return this._value;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(_Token.prototype, "tokenID", {
                    /*
                     * Gets the token ID of the token instance.
                     */
                    get: function () {
                        return this._tokenID;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(_Token.prototype, "tokenType", {
                    /*
                     * Gets the token type of the token instance.
                     */
                    get: function () {
                        return this._tokenType;
                    },
                    enumerable: true,
                    configurable: true
                });
                return _Token;
            }());
            sheet_1._Token = _Token;
            /*
             * Function definition class (keeps function name, parameter counts, and function).
             */
            var _FunctionDefinition = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:FunctionDefinition class.
                 *
                 * @param func The function will be invoked by the CalcEngine.
                 * @param paramMax The maximum count of the parameter that the function need.
                 * @param paramMin The minimum count of the parameter that the function need.
                 */
                function _FunctionDefinition(func, paramMax, paramMin) {
                    this._paramMax = Number.MAX_VALUE;
                    this._paramMin = Number.MIN_VALUE;
                    this._func = func;
                    if (wijmo.isNumber(paramMax) && !isNaN(paramMax)) {
                        this._paramMax = paramMax;
                    }
                    if (wijmo.isNumber(paramMin) && !isNaN(paramMin)) {
                        this._paramMin = paramMin;
                    }
                }
                Object.defineProperty(_FunctionDefinition.prototype, "paramMax", {
                    /*
                     * Gets the paramMax of the FunctionDefinition instance.
                     */
                    get: function () {
                        return this._paramMax;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(_FunctionDefinition.prototype, "paramMin", {
                    /*
                     * Gets the paramMin of the FunctionDefinition instance.
                     */
                    get: function () {
                        return this._paramMin;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(_FunctionDefinition.prototype, "func", {
                    /*
                     * Gets the func of the FunctionDefinition instance.
                     */
                    get: function () {
                        return this._func;
                    },
                    enumerable: true,
                    configurable: true
                });
                return _FunctionDefinition;
            }());
            sheet_1._FunctionDefinition = _FunctionDefinition;
            /*
             * Token types (used when building expressions, sequence defines operator priority)
             */
            var _TokenType;
            (function (_TokenType) {
                /*
                 * This token type includes '<', '>', '=', '<=', '>=' and '<>'.
                 */
                _TokenType[_TokenType["COMPARE"] = 0] = "COMPARE";
                /*
                 * This token type includes '+' and '-'.
                 */
                _TokenType[_TokenType["ADDSUB"] = 1] = "ADDSUB";
                /*
                 * This token type includes '*' and '/'.
                 */
                _TokenType[_TokenType["MULDIV"] = 2] = "MULDIV";
                /*
                 * This token type includes '^'.
                 */
                _TokenType[_TokenType["POWER"] = 3] = "POWER";
                /*
                 * This token type includes '&'.
                 */
                _TokenType[_TokenType["CONCAT"] = 4] = "CONCAT";
                /*
                 * This token type includes '(' and ')'.
                 */
                _TokenType[_TokenType["GROUP"] = 5] = "GROUP";
                /*
                 * This token type includes number value, string value and etc..
                 */
                _TokenType[_TokenType["LITERAL"] = 6] = "LITERAL";
                /*
                 * This token type includes function.
                 */
                _TokenType[_TokenType["IDENTIFIER"] = 7] = "IDENTIFIER";
                /*
                 * This token includes '[' and ']'
                 */
                _TokenType[_TokenType["SQUAREBRACKETS"] = 8] = "SQUAREBRACKETS";
            })(_TokenType = sheet_1._TokenType || (sheet_1._TokenType = {}));
            /*
             * Token ID (used when evaluating expressions)
             */
            var _TokenID;
            (function (_TokenID) {
                /*
                 * Greater than.
                 */
                _TokenID[_TokenID["GT"] = 0] = "GT";
                /*
                 * Less than.
                 */
                _TokenID[_TokenID["LT"] = 1] = "LT";
                /*
                 * Greater than or equal to.
                 */
                _TokenID[_TokenID["GE"] = 2] = "GE";
                /*
                 * Less than or equal to.
                 */
                _TokenID[_TokenID["LE"] = 3] = "LE";
                /*
                 * Equal to.
                 */
                _TokenID[_TokenID["EQ"] = 4] = "EQ";
                /*
                 * Not equal to.
                 */
                _TokenID[_TokenID["NE"] = 5] = "NE";
                /*
                 * Addition.
                 */
                _TokenID[_TokenID["ADD"] = 6] = "ADD";
                /*
                 * Subtraction.
                 */
                _TokenID[_TokenID["SUB"] = 7] = "SUB";
                /*
                 * Multiplication.
                 */
                _TokenID[_TokenID["MUL"] = 8] = "MUL";
                /*
                 * Division.
                 */
                _TokenID[_TokenID["DIV"] = 9] = "DIV";
                /*
                 * Gets quotient of division.
                 */
                _TokenID[_TokenID["DIVINT"] = 10] = "DIVINT";
                /*
                 * Gets remainder of division.
                 */
                _TokenID[_TokenID["MOD"] = 11] = "MOD";
                /*
                 * Power.
                 */
                _TokenID[_TokenID["POWER"] = 12] = "POWER";
                /*
                 * String concat.
                 */
                _TokenID[_TokenID["CONCAT"] = 13] = "CONCAT";
                /*
                 * Opening bracket.
                 */
                _TokenID[_TokenID["OPEN"] = 14] = "OPEN";
                /*
                 * Closing bracket.
                 */
                _TokenID[_TokenID["CLOSE"] = 15] = "CLOSE";
                /*
                 * Group end.
                 */
                _TokenID[_TokenID["END"] = 16] = "END";
                /*
                 * Comma.
                 */
                _TokenID[_TokenID["COMMA"] = 17] = "COMMA";
                /*
                 * Period.
                 */
                _TokenID[_TokenID["PERIOD"] = 18] = "PERIOD";
                /*
                 * Literal token
                 */
                _TokenID[_TokenID["ATOM"] = 19] = "ATOM";
            })(_TokenID = sheet_1._TokenID || (sheet_1._TokenID = {}));
            /*
             * Specifies the type of aggregate for flexsheet.
             */
            var _FlexSheetAggregate;
            (function (_FlexSheetAggregate) {
                /*
                 * Counts the number of cells that contain numbers, and counts numbers within the list of arguments.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["Count"] = 0] = "Count";
                /*
                 * Returns the number of cells that are not empty in a range.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["CountA"] = 1] = "CountA";
                /*
                 * Returns the number of empty cells in a specified range of cells.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["ConutBlank"] = 2] = "ConutBlank";
                /*
                 * Returns the number of the cells that meet the criteria you specify in the argument.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["CountIf"] = 3] = "CountIf";
                /*
                 * Returns the number of the cells that meet multiple criteria.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["CountIfs"] = 4] = "CountIfs";
                /*
                 * Returns the rank of a number in a list of numbers.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["Rank"] = 5] = "Rank";
                /*
                 * Returns the sum of the numeric values in the cells specified by a given criteria.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["SumIf"] = 6] = "SumIf";
                /*
                 * Returns the sum of the numeric values in the cells specified by a multiple criteria.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["SumIfs"] = 7] = "SumIfs";
                /*
                 * Multiplies all the numbers given as arguments and returns the product.
                 */
                _FlexSheetAggregate[_FlexSheetAggregate["Product"] = 8] = "Product";
            })(_FlexSheetAggregate || (_FlexSheetAggregate = {}));
            /*
             * Specifies the type of subtotal f to calculate over a group of values.
             */
            var _SubtotalFunction;
            (function (_SubtotalFunction) {
                /*
                 * Returns the average value of the numeric values in the group.
                 */
                _SubtotalFunction[_SubtotalFunction["Average"] = 1] = "Average";
                /*
                 * Counts the number of cells that contain numbers, and counts numbers within the list of arguments.
                 */
                _SubtotalFunction[_SubtotalFunction["Count"] = 2] = "Count";
                /*
                 * Counts the number of cells that are not empty in a range.
                 */
                _SubtotalFunction[_SubtotalFunction["CountA"] = 3] = "CountA";
                /*
                 * Returns the maximum value in the group.
                 */
                _SubtotalFunction[_SubtotalFunction["Max"] = 4] = "Max";
                /*
                 * Returns the minimum value in the group.
                 */
                _SubtotalFunction[_SubtotalFunction["Min"] = 5] = "Min";
                /*
                 * Multiplies all the numbers given as arguments and returns the product.
                 */
                _SubtotalFunction[_SubtotalFunction["Product"] = 6] = "Product";
                /*
                 *Returns the sample standard deviation of the numeric values in the group
                 * (uses the formula based on n-1).
                 */
                _SubtotalFunction[_SubtotalFunction["Std"] = 7] = "Std";
                /*
                 *Returns the population standard deviation of the values in the group
                 * (uses the formula based on n).
                 */
                _SubtotalFunction[_SubtotalFunction["StdPop"] = 8] = "StdPop";
                /*
                 * Returns the sum of the numeric values in the group.
                 */
                _SubtotalFunction[_SubtotalFunction["Sum"] = 9] = "Sum";
                /*
                 * Returns the sample variance of the numeric values in the group
                 * (uses the formula based on n-1).
                 */
                _SubtotalFunction[_SubtotalFunction["Var"] = 10] = "Var";
                /*
                 * Returns the population variance of the values in the group
                 * (uses the formula based on n).
                 */
                _SubtotalFunction[_SubtotalFunction["VarPop"] = 11] = "VarPop";
                /*
                 * Returns the average value of the numeric values in the group and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["AverageWithoutHidden"] = 101] = "AverageWithoutHidden";
                /*
                 * Counts the number of cells that contain numbers, and counts numbers within the list of arguments and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["CountWithoutHidden"] = 102] = "CountWithoutHidden";
                /*
                 * Counts the number of cells that are not empty in a range and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["CountAWithoutHidden"] = 103] = "CountAWithoutHidden";
                /*
                 * Returns the maximum value in the group and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["MaxWithoutHidden"] = 104] = "MaxWithoutHidden";
                /*
                 * Multiplies all the numbers given as arguments and returns the product and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["MinWithoutHidden"] = 105] = "MinWithoutHidden";
                /*
                 * Multiplies all the numbers given as arguments and returns the product and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["ProductWithoutHidden"] = 106] = "ProductWithoutHidden";
                /*
                 *Returns the sample standard deviation of the numeric values in the group
                 * (uses the formula based on n-1) and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["StdWithoutHidden"] = 107] = "StdWithoutHidden";
                /*
                 *Returns the population standard deviation of the values in the group
                 * (uses the formula based on n) and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["StdPopWithoutHidden"] = 108] = "StdPopWithoutHidden";
                /*
                 * Returns the sum of the numeric values in the group and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["SumWithoutHidden"] = 109] = "SumWithoutHidden";
                /*
                 * Returns the sample variance of the numeric values in the group
                 * (uses the formula based on n-1) and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["VarWithoutHidden"] = 110] = "VarWithoutHidden";
                /*
                 * Returns the population variance of the values in the group
                 * (uses the formula based on n) and ignores the hidden rows and columns.
                 */
                _SubtotalFunction[_SubtotalFunction["VarPopWithoutHidden"] = 111] = "VarPopWithoutHidden";
            })(_SubtotalFunction || (_SubtotalFunction = {}));
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet_1) {
            'use strict';
            /*
             * Defines the base class that represents parsed expressions.
             */
            var _Expression = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:Expression class.
                 *
                 * @param arg This parameter is used to build the token for the expression.
                 */
                function _Expression(arg) {
                    if (arg) {
                        if (arg instanceof sheet_1._Token) {
                            this._token = arg;
                        }
                        else {
                            this._token = new sheet_1._Token(arg, sheet_1._TokenID.ATOM, sheet_1._TokenType.LITERAL);
                        }
                    }
                    else {
                        this._token = new sheet_1._Token(null, sheet_1._TokenID.ATOM, sheet_1._TokenType.IDENTIFIER);
                    }
                }
                Object.defineProperty(_Expression.prototype, "token", {
                    /*
                     * Gets the token of the expression.
                     */
                    get: function () {
                        return this._token;
                    },
                    enumerable: true,
                    configurable: true
                });
                /*
                 * Evaluates the expression.
                 *
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _Expression.prototype.evaluate = function (rowIndex, columnIndex, sheet) {
                    if (this._token.tokenType !== sheet_1._TokenType.LITERAL) {
                        throw 'Bad expression.';
                    }
                    return this._token.value;
                };
                /*
                 * Parse the expression to a string value.
                 *
                 * @param x The @see:Expression need be parsed to string value.
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _Expression.toString = function (x, rowIndex, columnIndex, sheet) {
                    var v = x.evaluate(rowIndex, columnIndex, sheet);
                    if (!wijmo.isPrimitive(v)) {
                        v = v.value;
                    }
                    return v != null ? v.toString() : '';
                };
                /*
                 * Parse the expression to a number value.
                 *
                 * @param x The @see:Expression need be parsed to number value.
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _Expression.toNumber = function (x, rowIndex, columnIndex, sheet) {
                    // evaluate
                    var v = x.evaluate(rowIndex, columnIndex, sheet), monthArray = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                    if (!wijmo.isPrimitive(v)) {
                        v = v.value;
                    }
                    // handle numbers
                    if (wijmo.isNumber(v)) {
                        return v;
                    }
                    // handle booleans
                    if (wijmo.isBoolean(v)) {
                        return v ? 1 : 0;
                    }
                    // handle dates
                    if (wijmo.isDate(v)) {
                        return this._toOADate(v);
                    }
                    // handle strings
                    if (wijmo.isString(v)) {
                        if (v) {
                            if (!isNaN(+v)) {
                                return +v;
                            }
                            else {
                                for (var item in monthArray) {
                                    if (v.indexOf(monthArray[item]) > -1) {
                                        return this._toOADate(new Date(v));
                                    }
                                }
                                return +v;
                            }
                        }
                        else {
                            return 0;
                        }
                    }
                    // handle everything else
                    return wijmo.changeType(v, wijmo.DataType.Number, '');
                };
                /*
                 * Parse the expression to a boolean value.
                 *
                 * @param x The @see:Expression need be parsed to boolean value.
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _Expression.toBoolean = function (x, rowIndex, columnIndex, sheet) {
                    // evaluate
                    var v = x.evaluate(rowIndex, columnIndex, sheet);
                    if (!wijmo.isPrimitive(v)) {
                        v = v.value;
                    }
                    // handle booleans
                    if (wijmo.isBoolean(v)) {
                        return v;
                    }
                    // handle numbers
                    if (wijmo.isNumber(v)) {
                        return v === 0 ? false : true;
                    }
                    // handle everything else
                    return wijmo.changeType(v, wijmo.DataType.Boolean, '');
                };
                /*
                 * Parse the expression to a date value.
                 *
                 * @param x The @see:Expression need be parsed to date value.
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _Expression.toDate = function (x, rowIndex, columnIndex, sheet) {
                    // evaluate
                    var v = x.evaluate(rowIndex, columnIndex, sheet);
                    if (!wijmo.isPrimitive(v)) {
                        v = v.value;
                    }
                    // handle dates
                    if (wijmo.isDate(v)) {
                        return v;
                    }
                    // handle numbers
                    if (wijmo.isNumber(v)) {
                        return this._fromOADate(v);
                    }
                    // handle everything else
                    return wijmo.changeType(v, wijmo.DataType.Date, '');
                };
                // convert the common date to OLE Automation date.
                _Expression._toOADate = function (val) {
                    var epoch = Date.UTC(1899, 11, 30), // 1899-12-30T00:00:00
                    currentUTC = Date.UTC(val.getFullYear(), val.getMonth(), val.getDate(), val.getHours(), val.getMinutes(), val.getSeconds(), val.getMilliseconds());
                    return (currentUTC - epoch) / 8.64e7;
                };
                // convert the OLE Automation date to common date.
                _Expression._fromOADate = function (oADate) {
                    var epoch = Date.UTC(1899, 11, 30), date = new Date(), offset = oADate >= 60 ? 0 : 8.64e7;
                    return new Date(oADate * 8.64e7 + epoch + date.getTimezoneOffset() * 60000 + offset);
                };
                return _Expression;
            }());
            sheet_1._Expression = _Expression;
            /*
             * Defines the unary expression class.
             * For e.g. -1.23.
             */
            var _UnaryExpression = /** @class */ (function (_super) {
                __extends(_UnaryExpression, _super);
                /*
                 * Initializes a new instance of the @see:UnaryExpression class.
                 *
                 * @param arg This parameter is used to build the token for the expression.
                 * @param expr The @see:Expression instance for evaluating the UnaryExpression.
                 */
                function _UnaryExpression(arg, expr) {
                    var _this = _super.call(this, arg) || this;
                    _this._expr = expr;
                    return _this;
                }
                /*
                 * Overrides the evaluate function of base class.
                 *
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _UnaryExpression.prototype.evaluate = function (rowIndex, columnIndex, sheet) {
                    if (this.token.tokenID === sheet_1._TokenID.SUB) {
                        if (this._evaluatedValue == null) {
                            this._evaluatedValue = -_Expression.toNumber(this._expr, rowIndex, columnIndex, sheet);
                        }
                        return this._evaluatedValue;
                    }
                    if (this.token.tokenID === sheet_1._TokenID.ADD) {
                        if (this._evaluatedValue == null) {
                            this._evaluatedValue = +_Expression.toNumber(this._expr, rowIndex, columnIndex, sheet);
                        }
                        return this._evaluatedValue;
                    }
                    throw 'Bad expression.';
                };
                return _UnaryExpression;
            }(_Expression));
            sheet_1._UnaryExpression = _UnaryExpression;
            /*
             * Defines the binary expression class.
             * For e.g. 1 + 1.
             */
            var _BinaryExpression = /** @class */ (function (_super) {
                __extends(_BinaryExpression, _super);
                /*
                 * Initializes a new instance of the @see:BinaryExpression class.
                 *
                 * @param arg This parameter is used to build the token for the expression.
                 * @param leftExpr The @see:Expression instance for evaluating the BinaryExpression.
                 * @param rightExpr The @see:Expression instance for evaluating the BinaryExpression.
                 */
                function _BinaryExpression(arg, leftExpr, rightExpr) {
                    var _this = _super.call(this, arg) || this;
                    _this._leftExpr = leftExpr;
                    _this._rightExpr = rightExpr;
                    return _this;
                }
                /*
                 * Overrides the evaluate function of base class.
                 *
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _BinaryExpression.prototype.evaluate = function (rowIndex, columnIndex, sheet) {
                    var strLeftVal, strRightVal, orgLeftVal, orgRightVal, leftValue, rightValue, compareVal, isDate = false;
                    if (this._evaluatedValue != null) {
                        return this._evaluatedValue;
                    }
                    strLeftVal = _Expression.toString(this._leftExpr, rowIndex, columnIndex, sheet);
                    strRightVal = _Expression.toString(this._rightExpr, rowIndex, columnIndex, sheet);
                    if (this.token.tokenType === sheet_1._TokenType.CONCAT) {
                        this._evaluatedValue = strLeftVal + strRightVal;
                        return this._evaluatedValue;
                    }
                    orgLeftVal = this._leftExpr.evaluate(rowIndex, columnIndex, sheet);
                    orgRightVal = this._rightExpr.evaluate(rowIndex, columnIndex, sheet);
                    isDate = this._isDateValue(orgLeftVal) || this._isDateValue(orgRightVal);
                    leftValue = _Expression.toNumber(this._leftExpr, rowIndex, columnIndex, sheet);
                    rightValue = _Expression.toNumber(this._rightExpr, rowIndex, columnIndex, sheet);
                    compareVal = leftValue - rightValue;
                    // handle comparisons
                    if (this.token.tokenType === sheet_1._TokenType.COMPARE) {
                        switch (this.token.tokenID) {
                            case sheet_1._TokenID.GT: return compareVal > 0;
                            case sheet_1._TokenID.LT: return compareVal < 0;
                            case sheet_1._TokenID.GE: return compareVal >= 0;
                            case sheet_1._TokenID.LE: return compareVal <= 0;
                            case sheet_1._TokenID.EQ:
                                if (isNaN(compareVal)) {
                                    this._evaluatedValue = strLeftVal.toLowerCase() === strRightVal.toLowerCase();
                                    return this._evaluatedValue;
                                }
                                else {
                                    this._evaluatedValue = compareVal === 0;
                                    return this._evaluatedValue;
                                }
                            case sheet_1._TokenID.NE:
                                if (isNaN(compareVal)) {
                                    this._evaluatedValue = strLeftVal.toLowerCase() !== strRightVal.toLowerCase();
                                    return this._evaluatedValue;
                                }
                                else {
                                    this._evaluatedValue = compareVal !== 0;
                                    return this._evaluatedValue;
                                }
                        }
                    }
                    // handle everything else
                    switch (this.token.tokenID) {
                        case sheet_1._TokenID.ADD:
                            this._evaluatedValue = leftValue + rightValue;
                            break;
                        case sheet_1._TokenID.SUB:
                            this._evaluatedValue = leftValue - rightValue;
                            break;
                        case sheet_1._TokenID.MUL:
                            this._evaluatedValue = leftValue * rightValue;
                            break;
                        case sheet_1._TokenID.DIV:
                            this._evaluatedValue = leftValue / rightValue;
                            break;
                        case sheet_1._TokenID.DIVINT:
                            this._evaluatedValue = Math.floor(leftValue / rightValue);
                            break;
                        case sheet_1._TokenID.MOD:
                            this._evaluatedValue = Math.floor(leftValue % rightValue);
                            break;
                        case sheet_1._TokenID.POWER:
                            if (rightValue === 0.0) {
                                this._evaluatedValue = 1.0;
                            }
                            if (rightValue === 0.5) {
                                this._evaluatedValue = Math.sqrt(leftValue);
                            }
                            if (rightValue === 1.0) {
                                this._evaluatedValue = leftValue;
                            }
                            if (rightValue === 2.0) {
                                this._evaluatedValue = leftValue * leftValue;
                            }
                            if (rightValue === 3.0) {
                                this._evaluatedValue = leftValue * leftValue * leftValue;
                            }
                            if (rightValue === 4.0) {
                                this._evaluatedValue = leftValue * leftValue * leftValue * leftValue;
                            }
                            this._evaluatedValue = Math.pow(leftValue, rightValue);
                            break;
                        default:
                            this._evaluatedValue = NaN;
                            break;
                    }
                    if (!isNaN(this._evaluatedValue)) {
                        if (isDate) {
                            this._evaluatedValue = {
                                value: _Expression._fromOADate(this._evaluatedValue),
                                format: orgLeftVal.format || orgRightVal.format
                            };
                        }
                        return this._evaluatedValue;
                    }
                    throw 'Bad expression.';
                };
                // Check whether the value is date.
                _BinaryExpression.prototype._isDateValue = function (val) {
                    if (wijmo.isPrimitive(val)) {
                        return wijmo.isDate(val);
                    }
                    else {
                        return wijmo.isDate(val.value);
                    }
                };
                return _BinaryExpression;
            }(_Expression));
            sheet_1._BinaryExpression = _BinaryExpression;
            /*
             * Defines the cell range expression class.
             * For e.g. A1 or A1:B2.
             */
            var _CellRangeExpression = /** @class */ (function (_super) {
                __extends(_CellRangeExpression, _super);
                /*
                 * Initializes a new instance of the @see:CellRangeExpression class.
                 *
                 * @param cells The @see:CellRange instance represents the cell range for the CellRangeExpression.
                 * @param sheetRef The sheet name of the sheet which the cells range refers.
                 * @param flex The @see:FlexSheet instance for evaluating the value for the CellRangeExpression.
                 */
                function _CellRangeExpression(cells, sheetRef, flex) {
                    var _this = _super.call(this) || this;
                    _this._cells = cells;
                    _this._sheetRef = sheetRef;
                    _this._flex = flex;
                    _this._evalutingRange = {};
                    return _this;
                }
                /*
                 * Overrides the evaluate function of base class.
                 *
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _CellRangeExpression.prototype.evaluate = function (rowIndex, columnIndex, sheet) {
                    if (this._evaluatedValue == null) {
                        this._evaluatedValue = this._getCellValue(this._cells, sheet, rowIndex, columnIndex);
                    }
                    return this._evaluatedValue;
                };
                /*
                 * Gets the value list for each cell inside the cell range.
                 *
                 * @param isGetHiddenValue indicates whether get the cell value of the hidden row or hidden column.
                 * @param columnIndex indicates which column of the cell range need be get.
                 * @param sheet The @see:Sheet whose value to evaluate. If not specified then the data from current sheet
                 */
                _CellRangeExpression.prototype.getValues = function (isGetHiddenValue, columnIndex, sheet) {
                    if (isGetHiddenValue === void 0) { isGetHiddenValue = true; }
                    var cellValue, vals = [], valIndex = 0, rowIndex, columnIndex, startColumnIndex, endColumnIndex;
                    startColumnIndex = columnIndex != null && !isNaN(+columnIndex) ? columnIndex : this._cells.leftCol;
                    endColumnIndex = columnIndex != null && !isNaN(+columnIndex) ? columnIndex : this._cells.rightCol;
                    sheet = this._getSheet() || sheet || this._flex.selectedSheet;
                    if (!sheet) {
                        return null;
                    }
                    for (rowIndex = this._cells.topRow; rowIndex <= this._cells.bottomRow; rowIndex++) {
                        if (rowIndex >= sheet.grid.rows.length) {
                            throw 'The cell reference is out of the cell range of the flexsheet.';
                        }
                        if (!isGetHiddenValue && sheet.grid.rows[rowIndex].isVisible === false) {
                            continue;
                        }
                        for (columnIndex = startColumnIndex; columnIndex <= endColumnIndex; columnIndex++) {
                            if (columnIndex >= sheet.grid.columns.length) {
                                throw 'The cell reference is out of the cell range of the flexsheet.';
                            }
                            if (!isGetHiddenValue && sheet.grid.columns[columnIndex].isVisible === false) {
                                continue;
                            }
                            cellValue = this._getCellValue(new grid.CellRange(rowIndex, columnIndex), sheet);
                            if (!wijmo.isPrimitive(cellValue)) {
                                cellValue = cellValue.value;
                            }
                            vals[valIndex] = cellValue;
                            valIndex++;
                        }
                    }
                    return vals;
                };
                /*
                 * Gets the two-dimensional value list for each cell inside the cell range.
                 *
                 * @param isGetHiddenValue indicates whether get the cell value of the hidden row or hidden column.
                 * @param sheet The @see:Sheet whose value to evaluate. If not specified then the data from current sheet
                 */
                _CellRangeExpression.prototype.getValuseWithTwoDimensions = function (isGetHiddenValue, sheet) {
                    if (isGetHiddenValue === void 0) { isGetHiddenValue = true; }
                    var cellValue, vals = [], rowVals, rowValIndex = 0, valIndex = 0, rowIndex, columnIndex;
                    sheet = this._getSheet() || sheet || this._flex.selectedSheet;
                    if (!sheet) {
                        return null;
                    }
                    for (rowIndex = this._cells.topRow; rowIndex <= this._cells.bottomRow; rowIndex++) {
                        if (rowIndex >= sheet.grid.rows.length) {
                            throw 'The cell reference is out of the cell range of the flexsheet.';
                        }
                        if (!isGetHiddenValue && sheet.grid.rows[rowIndex].isVisible === false) {
                            rowValIndex++;
                            continue;
                        }
                        rowVals = [];
                        valIndex = 0;
                        for (columnIndex = this._cells.leftCol; columnIndex <= this._cells.rightCol; columnIndex++) {
                            if (columnIndex >= sheet.grid.columns.length) {
                                throw 'The cell reference is out of the cell range of the flexsheet.';
                            }
                            if (!isGetHiddenValue && sheet.grid.columns[columnIndex].isVisible === false) {
                                valIndex++;
                                continue;
                            }
                            cellValue = this._getCellValue(new grid.CellRange(rowIndex, columnIndex), sheet);
                            if (!wijmo.isPrimitive(cellValue)) {
                                cellValue = cellValue.value;
                            }
                            rowVals[valIndex] = cellValue;
                            valIndex++;
                        }
                        vals[rowValIndex] = rowVals;
                        rowValIndex++;
                    }
                    return vals;
                };
                Object.defineProperty(_CellRangeExpression.prototype, "cells", {
                    /*
                     * Gets the cell range of the CellRangeExpression.
                     */
                    get: function () {
                        return this._cells;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(_CellRangeExpression.prototype, "sheetRef", {
                    /*
                     * Gets the sheet reference of the CellRangeExpression.
                     */
                    get: function () {
                        return this._sheetRef;
                    },
                    enumerable: true,
                    configurable: true
                });
                // Get cell value for a cell.
                _CellRangeExpression.prototype._getCellValue = function (cell, sheet, rowIndex, columnIndex) {
                    var sheet, cellKey, row, col;
                    sheet = this._getSheet() || sheet || this._flex.selectedSheet;
                    if (!sheet) {
                        return null;
                    }
                    if (cell.isSingleCell) {
                        row = cell.row;
                        col = cell.col;
                    }
                    else {
                        if (rowIndex != null) {
                            if (rowIndex >= cell.topRow && rowIndex <= cell.bottomRow && cell.col === cell.col2) {
                                row = rowIndex;
                                col = cell.col;
                            }
                        }
                        if (columnIndex != null) {
                            if (columnIndex >= cell.leftCol && columnIndex <= cell.rightCol && cell.row === cell.row2) {
                                row = cell.row;
                                col = columnIndex;
                            }
                        }
                    }
                    if (row == null || col == null) {
                        throw 'Invalid Cell Reference.';
                    }
                    cellKey = sheet.name + ':' + row + ',' + col + '-' + row + ',' + col;
                    if (this._evalutingRange[cellKey]) {
                        throw 'Circular Reference';
                    }
                    try {
                        if (this._flex) {
                            this._evalutingRange[cellKey] = true;
                            return this._flex.getCellValue(row, col, false, sheet);
                        }
                    }
                    finally {
                        delete this._evalutingRange[cellKey];
                    }
                };
                // Gets the sheet by the sheetRef.
                _CellRangeExpression.prototype._getSheet = function () {
                    var i = 0, sheet;
                    if (!this._sheetRef) {
                        return null;
                    }
                    for (; i < this._flex.sheets.length; i++) {
                        sheet = this._flex.sheets[i];
                        if (sheet.name.toLowerCase() === this._sheetRef) {
                            return sheet;
                        }
                    }
                    throw 'Invalid sheet reference';
                };
                return _CellRangeExpression;
            }(_Expression));
            sheet_1._CellRangeExpression = _CellRangeExpression;
            /*
             * Defines the function expression class.
             * For e.g. sum(1,2,3).
             */
            var _FunctionExpression = /** @class */ (function (_super) {
                __extends(_FunctionExpression, _super);
                /*
                 * Initializes a new instance of the @see:FunctionExpression class.
                 *
                 * @param func The @see:FunctionDefinition instance keeps function name, parameter counts, and function.
                 * @param params The parameter list that the function of the @see:FunctionDefinition instance needs.
                 * @param needCacheEvaluatedVal indicates whether the _FunctionExpression need cache the evaluated value.
                 */
                function _FunctionExpression(func, params, needCacheEvaluatedVal) {
                    if (needCacheEvaluatedVal === void 0) { needCacheEvaluatedVal = true; }
                    var _this = _super.call(this) || this;
                    _this._funcDefinition = func;
                    _this._params = params;
                    _this._needCacheEvaluatedVal = needCacheEvaluatedVal;
                    return _this;
                }
                /*
                 * Overrides the evaluate function of base class.
                 *
                 * @param rowIndex The row index of the cell where the expression located in.
                 * @param columnIndex The column index of the cell where the expression located in.
                 * @param sheet The @see:Sheet is referenced by the @see:Expression.
                 */
                _FunctionExpression.prototype.evaluate = function (rowIndex, columnIndex, sheet) {
                    if (!this._needCacheEvaluatedVal) {
                        return this._funcDefinition.func(this._params, sheet, rowIndex, columnIndex);
                    }
                    if (this._evaluatedValue == null) {
                        this._evaluatedValue = this._funcDefinition.func(this._params, sheet, rowIndex, columnIndex);
                    }
                    return this._evaluatedValue;
                };
                return _FunctionExpression;
            }(_Expression));
            sheet_1._FunctionExpression = _FunctionExpression;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Base class for @see:FlexSheet undo/redo actions.
             */
            var _UndoAction = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:_UndoAction class.
                 *
                 * @param owner The @see:FlexSheet control that the @see:_UndoAction works for.
                 */
                function _UndoAction(owner) {
                    this._owner = owner;
                    this._sheetIndex = owner.selectedSheetIndex;
                }
                Object.defineProperty(_UndoAction.prototype, "sheetIndex", {
                    /*
                     * Gets the index of the sheet that the undo action wokrs for.
                     */
                    get: function () {
                        return this._sheetIndex;
                    },
                    enumerable: true,
                    configurable: true
                });
                /*
                 * Executes undo of the undo action
                 */
                _UndoAction.prototype.undo = function () {
                    throw 'This abstract method must be overridden.';
                };
                /*
                 * Executes redo of the undo action
                 */
                _UndoAction.prototype.redo = function () {
                    throw 'This abstract method must be overridden.';
                };
                /*
                 * Saves the current FlexSheet state.
                 */
                _UndoAction.prototype.saveNewState = function () {
                    throw 'This abstract method must be overridden.';
                };
                return _UndoAction;
            }());
            sheet._UndoAction = _UndoAction;
            /*
             * Defines the _EditAction class.
             *
             * It deals with the undo/redo for editing values in FlexSheet cells.
             */
            var _EditAction = /** @class */ (function (_super) {
                __extends(_EditAction, _super);
                /*
                 * Initializes a new instance of the @see:_EditAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _EditAction works for.
                 * @param selection The @CellRange of current editing cell.
                 */
                function _EditAction(owner, selection) {
                    var _this = this;
                    var index, selection, rowIndex, colIndex, val;
                    _this = _super.call(this, owner) || this;
                    _this._isPaste = false;
                    _this._selections = selection ? [selection] : owner.selectedSheet.selectionRanges.slice();
                    _this._oldValues = {};
                    _this._mergeAction = new _CellMergeAction(owner);
                    if (owner.rows.length > 0 && owner.columns.length > 0) {
                        for (index = 0; index < _this._selections.length; index++) {
                            selection = _this._selections[index];
                            for (rowIndex = selection.topRow; rowIndex <= selection.bottomRow; rowIndex++) {
                                for (colIndex = selection.leftCol; colIndex <= selection.rightCol; colIndex++) {
                                    val = owner.getCellData(rowIndex, colIndex, owner.columns[colIndex] && !!owner.columns[colIndex].dataMap);
                                    val = val == null ? '' : val;
                                    _this._oldValues['r' + rowIndex + '_c' + colIndex] = {
                                        row: rowIndex,
                                        col: colIndex,
                                        value: val
                                    };
                                }
                            }
                        }
                    }
                    return _this;
                }
                Object.defineProperty(_EditAction.prototype, "isPaste", {
                    /*
                     * Gets the isPaste state to indicate the edit action works for edit cell or copy/paste.
                     */
                    get: function () {
                        return this._isPaste;
                    },
                    enumerable: true,
                    configurable: true
                });
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _EditAction.prototype.undo = function () {
                    var self = this;
                    self._owner._clearCalcEngine();
                    self._owner.selectedSheet.selectionRanges.clear();
                    self._owner.deferUpdate(function () {
                        var tableIndex, table, index, selection;
                        if (self._deletedTables && self._deletedTables.length > 0) {
                            for (tableIndex = 0; tableIndex < self._deletedTables.length; tableIndex++) {
                                table = self._deletedTables[tableIndex];
                                self._owner.tables.push(table);
                                self._owner.selectedSheet.tableNames.push(table.name);
                            }
                        }
                        for (index = 0; index < self._selections.length; index++) {
                            selection = self._selections[index];
                            self._owner.selectedSheet.selectionRanges.push(selection);
                        }
                        Object.keys(self._oldValues).forEach(function (key) {
                            var item = self._oldValues[key];
                            self._owner.setCellData(item.row, item.col, item.value);
                        });
                        self._mergeAction.undo();
                        self._owner.refresh(false);
                    });
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _EditAction.prototype.redo = function () {
                    var self = this;
                    self._owner._clearCalcEngine();
                    self._owner.selectedSheet.selectionRanges.clear();
                    self._owner.deferUpdate(function () {
                        var tableIndex, table, index, selection;
                        if (self._deletedTables && self._deletedTables.length > 0) {
                            for (tableIndex = 0; tableIndex < self._deletedTables.length; tableIndex++) {
                                table = self._deletedTables[tableIndex];
                                self._owner.selectedSheet.tableNames.splice(self._owner.selectedSheet.tableNames.indexOf(table.name), 1);
                                self._owner.tables.remove(table);
                            }
                        }
                        for (index = 0; index < self._selections.length; index++) {
                            selection = self._selections[index];
                            self._owner.selectedSheet.selectionRanges.push(selection);
                        }
                        Object.keys(self._newValues).forEach(function (key) {
                            var item = self._newValues[key];
                            self._owner.setCellData(item.row, item.col, item.value);
                        });
                        self._mergeAction.redo();
                        self._owner.refresh(false);
                    });
                };
                /*
                 * Overrides the saveNewState of its base class @see:_UndoAction.
                 */
                _EditAction.prototype.saveNewState = function () {
                    var index, selection, currentCol, rowIndex, colIndex, val;
                    this._newValues = {};
                    for (index = 0; index < this._selections.length; index++) {
                        selection = this._selections[index];
                        for (rowIndex = selection.topRow; rowIndex <= selection.bottomRow; rowIndex++) {
                            for (colIndex = selection.leftCol; colIndex <= selection.rightCol; colIndex++) {
                                currentCol = this._owner.columns[colIndex];
                                if (!currentCol) {
                                    return false;
                                }
                                val = this._owner.getCellData(rowIndex, colIndex, !!currentCol.dataMap);
                                val = val == null ? '' : val;
                                this._newValues['r' + rowIndex + '_c' + colIndex] = {
                                    row: rowIndex,
                                    col: colIndex,
                                    value: val
                                };
                            }
                        }
                    }
                    this._mergeAction.saveNewState();
                    return !this._checkActionState();
                };
                /*
                 * Mark the cell edit action works for paste action.
                 */
                _EditAction.prototype.markIsPaste = function () {
                    this._isPaste = true;
                };
                /*
                 * Update the edit action for pasting.
                 *
                 * @param rng the @see:CellRange used to update the edit action
                 */
                _EditAction.prototype.updateForPasting = function (rng) {
                    var selection = this._selections[this._selections.length - 1], val = this._owner.getCellData(rng.row, rng.col, !!this._owner.columns[rng.col].dataMap);
                    if (!selection) {
                        selection = this._owner.selection;
                        this._selections = [selection];
                    }
                    val = val == null ? '' : val;
                    this._oldValues['r' + rng.row + '_c' + rng.col] = {
                        row: rng.row,
                        col: rng.col,
                        value: val
                    };
                    selection.row = Math.min(selection.topRow, rng.topRow);
                    selection.row2 = Math.max(selection.bottomRow, rng.bottomRow);
                    selection.col = Math.min(selection.leftCol, rng.leftCol);
                    selection.col2 = Math.max(selection.rightCol, rng.rightCol);
                };
                // Store the deleted table.
                _EditAction.prototype._storeDeletedTables = function (table) {
                    if (this._deletedTables == null) {
                        this._deletedTables = [];
                    }
                    this._deletedTables.push(table);
                };
                // Check whether the values changed after editing.
                _EditAction.prototype._checkActionState = function () {
                    var self = this, ret = true;
                    Object.keys(self._oldValues).forEach(function (key) {
                        var oldItem, newItem;
                        if (ret) {
                            oldItem = self._oldValues[key];
                            newItem = self._newValues[key];
                            if (oldItem && newItem && oldItem.value !== newItem.value) {
                                ret = false;
                            }
                        }
                    });
                    return ret;
                };
                return _EditAction;
            }(_UndoAction));
            sheet._EditAction = _EditAction;
            /*
             * Defines the _ColumnResizeAction class.
             *
             * It deals with the undo/redo for resize the column of the FlexSheet.
             */
            var _ColumnResizeAction = /** @class */ (function (_super) {
                __extends(_ColumnResizeAction, _super);
                /*
                 * Initializes a new instance of the @see:_ColumnResizeAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _ColumnResizeAction works for.
                 * @param panel The @see: GridPanel indicates the resizing column belongs to which part of the FlexSheet.
                 * @param colIndex it indicates which column is resizing.
                 */
                function _ColumnResizeAction(owner, panel, colIndex) {
                    var _this = _super.call(this, owner) || this;
                    _this._panel = panel;
                    _this._colIndex = colIndex;
                    _this._oldColWidth = panel.columns[colIndex].width;
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _ColumnResizeAction.prototype.undo = function () {
                    var column = this._panel.columns[this._colIndex];
                    if (column) {
                        column.width = this._oldColWidth;
                    }
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _ColumnResizeAction.prototype.redo = function () {
                    var column = this._panel.columns[this._colIndex];
                    if (column) {
                        column.width = this._newColWidth;
                    }
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _ColumnResizeAction.prototype.saveNewState = function () {
                    this._newColWidth = this._panel.columns[this._colIndex].width;
                    if (this._oldColWidth === this._newColWidth) {
                        return false;
                    }
                    return true;
                };
                return _ColumnResizeAction;
            }(_UndoAction));
            sheet._ColumnResizeAction = _ColumnResizeAction;
            /*
             * Defines the _RowResizeAction class.
             *
             * It deals with the undo\redo for resize the row of the FlexSheet.
             */
            var _RowResizeAction = /** @class */ (function (_super) {
                __extends(_RowResizeAction, _super);
                /*
                 * Initializes a new instance of the @see:_RowResizeAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _RowResizeAction works for.
                 * @param panel The @see: GridPanel indicates the resizing row belongs to which part of the FlexSheet.
                 * @param rowIndex it indicates which row is resizing.
                 */
                function _RowResizeAction(owner, panel, rowIndex) {
                    var _this = _super.call(this, owner) || this;
                    _this._panel = panel;
                    _this._rowIndex = rowIndex;
                    _this._oldRowHeight = panel.rows[rowIndex].height;
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _RowResizeAction.prototype.undo = function () {
                    var row = this._panel.rows[this._rowIndex];
                    if (row) {
                        row.height = this._oldRowHeight;
                    }
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _RowResizeAction.prototype.redo = function () {
                    var row = this._panel.rows[this._rowIndex];
                    if (row) {
                        row.height = this._newRowHeight;
                    }
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _RowResizeAction.prototype.saveNewState = function () {
                    this._newRowHeight = this._panel.rows[this._rowIndex].height;
                    if (this._oldRowHeight === this._newRowHeight) {
                        return false;
                    }
                    return true;
                };
                return _RowResizeAction;
            }(_UndoAction));
            sheet._RowResizeAction = _RowResizeAction;
            /*
             * Defines the _ColumnsChangedAction class.
             *
             * It deals with the undo\redo for insert or delete column of the FlexSheet.
             */
            var _ColumnsChangedAction = /** @class */ (function (_super) {
                __extends(_ColumnsChangedAction, _super);
                /*
                 * Initializes a new instance of the @see:_ColumnsChangedAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _ColumnsChangedAction works for.
                 */
                function _ColumnsChangedAction(owner) {
                    var _this = this;
                    var colIndex, tableIndex, tableName, table, columns = [], tableRanges = [];
                    _this = _super.call(this, owner) || this;
                    for (colIndex = 0; colIndex < owner.columns.length; colIndex++) {
                        columns.push(owner.columns[colIndex]);
                    }
                    if (owner.selectedSheet.tableNames && owner.selectedSheet.tableNames.length > 0) {
                        for (tableIndex = 0; tableIndex < owner.selectedSheet.tableNames.length; tableIndex++) {
                            tableName = owner.selectedSheet.tableNames[tableIndex];
                            table = owner._getTable(tableName);
                            if (table) {
                                tableRanges.push({
                                    name: tableName,
                                    range: table.range,
                                    columns: table.columns.slice()
                                });
                            }
                        }
                    }
                    _this._oldValue = {
                        columns: columns,
                        sortList: owner.sortManager._committedList.slice(),
                        styledCells: owner.selectedSheet ? JSON.parse(JSON.stringify(owner.selectedSheet._styledCells)) : null,
                        mergedCells: owner._cloneMergedCells(),
                        tableRanges: tableRanges,
                        selection: owner.selection
                    };
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _ColumnsChangedAction.prototype.undo = function () {
                    var colIndex, i, tableIndex, tableSetting, table, formulaObj, oldFormulas, oldDefinedNameVals, definedNameObj, nameIndex, self = this;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._isUndoing = true;
                    self._owner._clearCalcEngine();
                    self._owner.finishEditing();
                    self._owner.columns.clear();
                    self._owner.selectedSheet._styledCells = undefined;
                    self._owner.selectedSheet._mergedRanges = undefined;
                    self._owner.columns.beginUpdate();
                    for (colIndex = 0; colIndex < self._oldValue.columns.length; colIndex++) {
                        self._owner.columns.push(self._oldValue.columns[colIndex]);
                    }
                    self._owner.columns.endUpdate();
                    self._owner.selectedSheet._styledCells = JSON.parse(JSON.stringify(self._oldValue.styledCells));
                    self._owner.selectedSheet._mergedRanges = self._oldValue.mergedCells;
                    for (tableIndex = 0; tableIndex < this._oldValue.tableRanges.length; tableIndex++) {
                        tableSetting = this._oldValue.tableRanges[tableIndex];
                        table = this._owner._getTable(tableSetting.name);
                        if (table) {
                            table._setTableRange(tableSetting.range, tableSetting.columns);
                        }
                    }
                    if (self._affectedFormulas) {
                        oldFormulas = self._affectedFormulas.oldFormulas;
                    }
                    self._owner.deferUpdate(function () {
                        // Set the 'old' formulas for undo.
                        if (!!oldFormulas && oldFormulas.length > 0) {
                            for (i = 0; i < oldFormulas.length; i++) {
                                formulaObj = oldFormulas[i];
                                if (formulaObj.point != null) {
                                    if (formulaObj.sheet.name === self._owner.selectedSheet.name) {
                                        self._owner.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                    else {
                                        formulaObj.sheet.grid.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                }
                                else {
                                    formulaObj.row._ubv[formulaObj.column._hash] = formulaObj.formula;
                                }
                            }
                        }
                        if (self._deletedTables && self._deletedTables.length > 0) {
                            for (tableIndex = 0; tableIndex < self._deletedTables.length; tableIndex++) {
                                table = self._deletedTables[tableIndex];
                                self._owner.tables.push(table);
                                self._owner.selectedSheet.tableNames.push(table.name);
                            }
                        }
                    });
                    // Update defined names
                    if (self._affectedDefinedNameVals) {
                        oldDefinedNameVals = self._affectedDefinedNameVals.oldDefinedNameVals;
                    }
                    if (oldDefinedNameVals && oldDefinedNameVals.length > 0) {
                        for (i = 0; i < oldDefinedNameVals.length; i++) {
                            definedNameObj = oldDefinedNameVals[i];
                            nameIndex = self._owner._getDefinedNameIndexByName(definedNameObj.name);
                            if (nameIndex > -1) {
                                self._owner.definedNames[nameIndex].value = definedNameObj.value;
                            }
                        }
                    }
                    // Synch the cell style for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].styledCells = self._owner.selectedSheet._styledCells;
                    // Synch the merged range for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].mergedRanges = self._owner.selectedSheet._mergedRanges;
                    self._owner.sortManager.sortDescriptions.sourceCollection = self._oldValue.sortList.slice();
                    self._owner.sortManager.commitSort(false);
                    self._owner.sortManager._refresh();
                    self._owner.selection = self._oldValue.selection;
                    self._owner.refresh(true);
                    self._owner._isUndoing = false;
                    // AlexI - TFS 292673
                    self._owner._copyColumnsToSelectedSheet();
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _ColumnsChangedAction.prototype.redo = function () {
                    var colIndex, i, tableIndex, tableSetting, table, formulaObj, newFormulas, newDefinedNameVals, definedNameObj, nameIndex, self = this;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._isUndoing = true;
                    self._owner._clearCalcEngine();
                    self._owner.finishEditing();
                    self._owner.columns.clear();
                    self._owner.selectedSheet._styledCells = undefined;
                    self._owner.selectedSheet._mergedRanges = undefined;
                    self._owner.columns.beginUpdate();
                    for (colIndex = 0; colIndex < self._newValue.columns.length; colIndex++) {
                        self._owner.columns.push(self._newValue.columns[colIndex]);
                    }
                    self._owner.columns.endUpdate();
                    self._owner.selectedSheet._styledCells = JSON.parse(JSON.stringify(self._newValue.styledCells));
                    self._owner.selectedSheet._mergedRanges = self._newValue.mergedCells;
                    for (tableIndex = 0; tableIndex < this._newValue.tableRanges.length; tableIndex++) {
                        tableSetting = this._newValue.tableRanges[tableIndex];
                        table = this._owner._getTable(tableSetting.name);
                        if (table) {
                            table._setTableRange(tableSetting.range, tableSetting.columns);
                        }
                    }
                    if (self._affectedFormulas) {
                        newFormulas = self._affectedFormulas.newFormulas;
                    }
                    self._owner.deferUpdate(function () {
                        // Set the 'new' formulas for redo.
                        if (!!newFormulas && newFormulas.length > 0) {
                            for (i = 0; i < newFormulas.length; i++) {
                                formulaObj = newFormulas[i];
                                if (formulaObj.point != null) {
                                    if (formulaObj.sheet.name === self._owner.selectedSheet.name) {
                                        self._owner.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                    else {
                                        formulaObj.sheet.grid.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                }
                                else {
                                    formulaObj.row._ubv[formulaObj.column._hash] = formulaObj.formula;
                                }
                            }
                        }
                        if (self._deletedTables && self._deletedTables.length > 0) {
                            for (tableIndex = 0; tableIndex < self._deletedTables.length; tableIndex++) {
                                table = self._deletedTables[tableIndex];
                                self._owner.selectedSheet.tableNames.splice(self._owner.selectedSheet.tableNames.indexOf(table.name), 1);
                                self._owner.tables.remove(table);
                            }
                        }
                    });
                    // Update defined names
                    if (self._affectedDefinedNameVals) {
                        newDefinedNameVals = self._affectedDefinedNameVals.newDefinedNameVals;
                    }
                    if (newDefinedNameVals && newDefinedNameVals.length > 0) {
                        for (i = 0; i < newDefinedNameVals.length; i++) {
                            definedNameObj = newDefinedNameVals[i];
                            nameIndex = self._owner._getDefinedNameIndexByName(definedNameObj.name);
                            if (nameIndex > -1) {
                                self._owner.definedNames[nameIndex].value = definedNameObj.value;
                            }
                        }
                    }
                    // Synch the cell style for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].styledCells = self._owner.selectedSheet._styledCells;
                    // Synch the merged range for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].mergedRanges = self._owner.selectedSheet._mergedRanges;
                    self._owner.sortManager.sortDescriptions.sourceCollection = self._newValue.sortList.slice();
                    self._owner.sortManager.commitSort(false);
                    self._owner.sortManager._refresh();
                    self._owner.selection = self._newValue.selection;
                    self._owner.refresh(true);
                    self._owner._isUndoing = false;
                    self._owner._copyColumnsToSelectedSheet();
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _ColumnsChangedAction.prototype.saveNewState = function () {
                    var colIndex, tableIndex, tableName, table, columns = [], tableRanges = [];
                    for (colIndex = 0; colIndex < this._owner.columns.length; colIndex++) {
                        columns.push(this._owner.columns[colIndex]);
                    }
                    if (this._owner.selectedSheet.tableNames && this._owner.selectedSheet.tableNames.length > 0) {
                        for (tableIndex = 0; tableIndex < this._owner.selectedSheet.tableNames.length; tableIndex++) {
                            tableName = this._owner.selectedSheet.tableNames[tableIndex];
                            table = this._owner._getTable(tableName);
                            if (table) {
                                tableRanges.push({
                                    name: tableName,
                                    range: table.range,
                                    columns: table.columns.slice()
                                });
                            }
                        }
                    }
                    this._newValue = {
                        columns: columns,
                        sortList: this._owner.sortManager._committedList.slice(),
                        styledCells: this._owner.selectedSheet ? JSON.parse(JSON.stringify(this._owner.selectedSheet._styledCells)) : null,
                        mergedCells: this._owner._cloneMergedCells(),
                        tableRanges: tableRanges,
                        selection: this._owner.selection
                    };
                    return true;
                };
                return _ColumnsChangedAction;
            }(_UndoAction));
            sheet._ColumnsChangedAction = _ColumnsChangedAction;
            /*
             * Defines the _RowsChangedAction class.
             *
             * It deals with the undo\redo for insert or delete row of the FlexSheet.
             */
            var _RowsChangedAction = /** @class */ (function (_super) {
                __extends(_RowsChangedAction, _super);
                /*
                 * Initializes a new instance of the @see:_RowsChangedAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _RowsChangedAction works for.
                 */
                function _RowsChangedAction(owner) {
                    var _this = this;
                    var rowIndex, colIndex, tableIndex, tableName, table, items, rows = [], columns = [], tableSettings = [];
                    _this = _super.call(this, owner) || this;
                    for (rowIndex = 0; rowIndex < owner.rows.length; rowIndex++) {
                        rows.push(owner.rows[rowIndex]);
                    }
                    for (colIndex = 0; colIndex < owner.columns.length; colIndex++) {
                        columns.push(owner.columns[colIndex]);
                    }
                    if (owner.selectedSheet.tableNames && owner.selectedSheet.tableNames.length > 0) {
                        for (tableIndex = 0; tableIndex < owner.selectedSheet.tableNames.length; tableIndex++) {
                            tableName = owner.selectedSheet.tableNames[tableIndex];
                            table = owner._getTable(tableName);
                            if (table) {
                                tableSettings.push({
                                    name: tableName,
                                    range: table.range,
                                    setting: {
                                        showHeaderRow: table.showHeaderRow,
                                        showTotalRow: table.showTotalRow
                                    }
                                });
                            }
                        }
                    }
                    if (owner.itemsSource) {
                        if (owner.itemsSource instanceof wijmo.collections.CollectionView) {
                            items = owner.itemsSource.items.slice();
                        }
                        else {
                            items = owner.itemsSource.slice();
                        }
                    }
                    _this._oldValue = {
                        rows: rows,
                        columns: columns,
                        itemsSource: items,
                        styledCells: owner.selectedSheet ? JSON.parse(JSON.stringify(owner.selectedSheet._styledCells)) : null,
                        mergedCells: owner._cloneMergedCells(),
                        tableSettings: tableSettings,
                        selection: owner.selection
                    };
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _RowsChangedAction.prototype.undo = function () {
                    var rowIndex, colIndex, i, tableIndex, tableSetting, table, formulaObj, oldFormulas, oldDefinedNameVals, definedNameObj, nameIndex, self = this, dataSourceBinding = !!self._oldValue.itemsSource, args;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._isUndoing = true;
                    self._owner._clearCalcEngine();
                    self._owner.finishEditing();
                    self._owner.columns.clear();
                    self._owner.rows.clear();
                    self._owner.selectedSheet._styledCells = undefined;
                    self._owner.selectedSheet._mergedRanges = undefined;
                    if (dataSourceBinding) {
                        self._owner.collectionView.beginUpdate();
                        self._owner.autoGenerateColumns = false;
                        if (self._owner.itemsSource instanceof wijmo.collections.CollectionView) {
                            args = [0, self._owner.itemsSource.items.length].concat(self._oldValue.itemsSource);
                            Array.prototype.splice.apply(self._owner.itemsSource.items, args);
                        }
                        else {
                            self._owner.itemsSource = self._oldValue.itemsSource.slice();
                        }
                        self._owner.collectionView.endUpdate();
                    }
                    else {
                        self._owner.rows.beginUpdate();
                        for (rowIndex = 0; rowIndex < self._oldValue.rows.length; rowIndex++) {
                            self._owner.rows.push(self._oldValue.rows[rowIndex]);
                        }
                    }
                    for (colIndex = 0; colIndex < self._oldValue.columns.length; colIndex++) {
                        self._owner.columns.push(self._oldValue.columns[colIndex]);
                    }
                    self._owner.rows.endUpdate();
                    self._owner.selectedSheet._styledCells = JSON.parse(JSON.stringify(self._oldValue.styledCells));
                    self._owner.selectedSheet._mergedRanges = self._oldValue.mergedCells;
                    for (tableIndex = 0; tableIndex < this._oldValue.tableSettings.length; tableIndex++) {
                        tableSetting = this._oldValue.tableSettings[tableIndex];
                        table = this._owner._getTable(tableSetting.name);
                        if (table) {
                            table['_showHeaderRow'] = tableSetting.setting.showHeaderRow;
                            table['_showTotalRow'] = tableSetting.setting.showTotalRow;
                            table._setTableRange(tableSetting.range);
                        }
                    }
                    if (self._affectedFormulas) {
                        oldFormulas = self._affectedFormulas.oldFormulas;
                    }
                    self._owner.deferUpdate(function () {
                        // Set the 'old' formulas for undo.
                        if (!!oldFormulas && oldFormulas.length > 0) {
                            for (i = 0; i < oldFormulas.length; i++) {
                                formulaObj = oldFormulas[i];
                                if (formulaObj.point != null) {
                                    if (formulaObj.sheet.name === self._owner.selectedSheet.name) {
                                        self._owner.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                    else {
                                        formulaObj.sheet.grid.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                }
                                else {
                                    formulaObj.row._ubv[formulaObj.column._hash] = formulaObj.formula;
                                }
                            }
                        }
                        if (self._deletedTables && self._deletedTables.length > 0) {
                            for (tableIndex = 0; tableIndex < self._deletedTables.length; tableIndex++) {
                                table = self._deletedTables[tableIndex];
                                self._owner.tables.push(table);
                                self._owner.selectedSheet.tableNames.push(table.name);
                            }
                        }
                    });
                    // Update defined names
                    if (self._affectedDefinedNameVals) {
                        oldDefinedNameVals = self._affectedDefinedNameVals.oldDefinedNameVals;
                    }
                    if (oldDefinedNameVals && oldDefinedNameVals.length > 0) {
                        for (i = 0; i < oldDefinedNameVals.length; i++) {
                            definedNameObj = oldDefinedNameVals[i];
                            nameIndex = self._owner._getDefinedNameIndexByName(definedNameObj.name);
                            if (nameIndex > -1) {
                                self._owner.definedNames[nameIndex].value = definedNameObj.value;
                            }
                        }
                    }
                    // Synch the cell style for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].styledCells = self._owner.selectedSheet._styledCells;
                    // Synch the merged range for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].mergedRanges = self._owner.selectedSheet._mergedRanges;
                    self._owner.selection = self._oldValue.selection;
                    self._owner.refresh(true);
                    self._owner._isUndoing = false;
                    self._owner._copyRowsToSelectedSheet();
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _RowsChangedAction.prototype.redo = function () {
                    var rowIndex, colIndex, i, tableIndex, tableSetting, table, formulaObj, newFormulas, newDefinedNameVals, definedNameObj, nameIndex, self = this, dataSourceBinding = !!self._newValue.itemsSource, args;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._isUndoing = true;
                    self._owner._clearCalcEngine();
                    self._owner.finishEditing();
                    self._owner.columns.clear();
                    self._owner.rows.clear();
                    self._owner.selectedSheet._styledCells = undefined;
                    self._owner.selectedSheet._mergedRanges = undefined;
                    if (dataSourceBinding) {
                        self._owner.collectionView.beginUpdate();
                        self._owner.autoGenerateColumns = false;
                        if (self._owner.itemsSource instanceof wijmo.collections.CollectionView) {
                            args = [0, self._owner.itemsSource.items.length].concat(self._newValue.itemsSource);
                            Array.prototype.splice.apply(self._owner.itemsSource.items, args);
                        }
                        else {
                            self._owner.itemsSource = self._newValue.itemsSource.slice();
                        }
                        self._owner.collectionView.endUpdate();
                    }
                    else {
                        self._owner.rows.beginUpdate();
                        for (rowIndex = 0; rowIndex < self._newValue.rows.length; rowIndex++) {
                            self._owner.rows.push(self._newValue.rows[rowIndex]);
                        }
                    }
                    for (colIndex = 0; colIndex < self._newValue.columns.length; colIndex++) {
                        self._owner.columns.push(self._newValue.columns[colIndex]);
                    }
                    self._owner.rows.endUpdate();
                    self._owner.selectedSheet._styledCells = JSON.parse(JSON.stringify(self._newValue.styledCells));
                    self._owner.selectedSheet._mergedRanges = self._newValue.mergedCells;
                    for (tableIndex = 0; tableIndex < this._newValue.tableSettings.length; tableIndex++) {
                        tableSetting = this._newValue.tableSettings[tableIndex];
                        table = this._owner._getTable(tableSetting.name);
                        if (table) {
                            table['_showHeaderRow'] = tableSetting.setting.showHeaderRow;
                            table['_showTotalRow'] = tableSetting.setting.showTotalRow;
                            table._setTableRange(tableSetting.range);
                        }
                    }
                    if (self._affectedFormulas) {
                        newFormulas = self._affectedFormulas.newFormulas;
                    }
                    self._owner.deferUpdate(function () {
                        // Set the 'new' formulas for redo.
                        if (!!newFormulas && newFormulas.length > 0) {
                            for (i = 0; i < newFormulas.length; i++) {
                                formulaObj = newFormulas[i];
                                if (formulaObj.point != null) {
                                    if (formulaObj.sheet.name === self._owner.selectedSheet.name) {
                                        self._owner.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                    else {
                                        formulaObj.sheet.grid.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                    }
                                }
                                else {
                                    formulaObj.row._ubv[formulaObj.column._hash] = formulaObj.formula;
                                }
                            }
                        }
                        if (self._deletedTables && self._deletedTables.length > 0) {
                            for (tableIndex = 0; tableIndex < self._deletedTables.length; tableIndex++) {
                                table = self._deletedTables[tableIndex];
                                self._owner.selectedSheet.tableNames.splice(self._owner.selectedSheet.tableNames.indexOf(table.name), 1);
                                self._owner.tables.remove(table);
                            }
                        }
                    });
                    // Update defined names
                    if (self._affectedDefinedNameVals) {
                        newDefinedNameVals = self._affectedDefinedNameVals.newDefinedNameVals;
                    }
                    if (newDefinedNameVals && newDefinedNameVals.length > 0) {
                        for (i = 0; i < newDefinedNameVals.length; i++) {
                            definedNameObj = newDefinedNameVals[i];
                            nameIndex = self._owner._getDefinedNameIndexByName(definedNameObj.name);
                            if (nameIndex > -1) {
                                self._owner.definedNames[nameIndex].value = definedNameObj.value;
                            }
                        }
                    }
                    // Synch the cell style for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].styledCells = self._owner.selectedSheet._styledCells;
                    // Synch the merged range for current sheet.
                    self._owner.selectedSheet.grid['wj_sheetInfo'].mergedRanges = self._owner.selectedSheet._mergedRanges;
                    self._owner.selection = self._newValue.selection;
                    self._owner.refresh(true);
                    self._owner._isUndoing = false;
                    self._owner._copyRowsToSelectedSheet();
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _RowsChangedAction.prototype.saveNewState = function () {
                    var rowIndex, colIndex, tableIndex, tableName, table, items, rows = [], columns = [], tableRanges = [];
                    for (rowIndex = 0; rowIndex < this._owner.rows.length; rowIndex++) {
                        rows.push(this._owner.rows[rowIndex]);
                    }
                    for (colIndex = 0; colIndex < this._owner.columns.length; colIndex++) {
                        columns.push(this._owner.columns[colIndex]);
                    }
                    if (this._owner.selectedSheet.tableNames && this._owner.selectedSheet.tableNames.length > 0) {
                        for (tableIndex = 0; tableIndex < this._owner.selectedSheet.tableNames.length; tableIndex++) {
                            tableName = this._owner.selectedSheet.tableNames[tableIndex];
                            table = this._owner._getTable(tableName);
                            if (table) {
                                tableRanges.push({
                                    name: tableName,
                                    range: table.range,
                                    setting: {
                                        showHeaderRow: table.showHeaderRow,
                                        showTotalRow: table.showTotalRow
                                    }
                                });
                            }
                        }
                    }
                    if (this._owner.itemsSource) {
                        if (this._owner.itemsSource instanceof wijmo.collections.CollectionView) {
                            items = this._owner.itemsSource.items.slice();
                        }
                        else {
                            items = this._owner.itemsSource.slice();
                        }
                    }
                    this._newValue = {
                        rows: rows,
                        columns: columns,
                        itemsSource: items,
                        styledCells: this._owner.selectedSheet ? JSON.parse(JSON.stringify(this._owner.selectedSheet._styledCells)) : null,
                        mergedCells: this._owner._cloneMergedCells(),
                        tableSettings: tableRanges,
                        selection: this._owner.selection
                    };
                    return true;
                };
                return _RowsChangedAction;
            }(_UndoAction));
            sheet._RowsChangedAction = _RowsChangedAction;
            /*
             * Defines the _CellStyleAction class.
             *
             * It deals with the undo\redo for applying style for the cells of the FlexSheet.
             */
            var _CellStyleAction = /** @class */ (function (_super) {
                __extends(_CellStyleAction, _super);
                /*
                 * Initializes a new instance of the @see:_CellStyleAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _CellStyleAction works for.
                 * @param styledCells Current styled cells of the @see: FlexSheet control.
                 */
                function _CellStyleAction(owner, styledCells) {
                    var _this = _super.call(this, owner) || this;
                    _this._oldStyledCells = styledCells ? JSON.parse(JSON.stringify(styledCells)) : (owner.selectedSheet ? JSON.parse(JSON.stringify(owner.selectedSheet._styledCells)) : null);
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _CellStyleAction.prototype.undo = function () {
                    if (!this._owner.selectedSheet) {
                        return;
                    }
                    this._owner.selectedSheet._styledCells = JSON.parse(JSON.stringify(this._oldStyledCells));
                    this._owner.selectedSheet.grid['wj_sheetInfo'].styledCells = this._owner.selectedSheet._styledCells;
                    this._owner.refresh(false);
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _CellStyleAction.prototype.redo = function () {
                    if (!this._owner.selectedSheet) {
                        return;
                    }
                    this._owner.selectedSheet._styledCells = JSON.parse(JSON.stringify(this._newStyledCells));
                    this._owner.selectedSheet.grid['wj_sheetInfo'].styledCells = this._owner.selectedSheet._styledCells;
                    this._owner.refresh(false);
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _CellStyleAction.prototype.saveNewState = function () {
                    this._newStyledCells = this._owner.selectedSheet ? JSON.parse(JSON.stringify(this._owner.selectedSheet._styledCells)) : null;
                    return true;
                };
                return _CellStyleAction;
            }(_UndoAction));
            sheet._CellStyleAction = _CellStyleAction;
            /*
             * Defines the _CellMergeAction class.
             *
             * It deals with the undo\redo for merging the cells of the FlexSheet.
             */
            var _CellMergeAction = /** @class */ (function (_super) {
                __extends(_CellMergeAction, _super);
                /*
                 * Initializes a new instance of the @see:_CellMergeAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _CellMergeAction works for.
                 */
                function _CellMergeAction(owner) {
                    var _this = _super.call(this, owner) || this;
                    _this._oldMergedCells = owner._cloneMergedCells();
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _CellMergeAction.prototype.undo = function () {
                    if (!this._owner.selectedSheet) {
                        return;
                    }
                    this._owner._clearCalcEngine();
                    this._owner.selectedSheet._mergedRanges = this._oldMergedCells;
                    this._owner.selectedSheet.grid['wj_sheetInfo'].mergedRanges = this._owner.selectedSheet._mergedRanges;
                    this._owner.refresh(true);
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _CellMergeAction.prototype.redo = function () {
                    if (!this._owner.selectedSheet) {
                        return;
                    }
                    this._owner._clearCalcEngine();
                    this._owner.selectedSheet._mergedRanges = this._newMergedCells;
                    this._owner.selectedSheet.grid['wj_sheetInfo'].mergedRanges = this._owner.selectedSheet._mergedRanges;
                    this._owner.refresh(true);
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _CellMergeAction.prototype.saveNewState = function () {
                    this._newMergedCells = this._owner._cloneMergedCells();
                    return true;
                };
                return _CellMergeAction;
            }(_UndoAction));
            sheet._CellMergeAction = _CellMergeAction;
            /*
             * Defines the _SortColumnAction class.
             *
             * It deals with the undo\redo for sort columns of the FlexSheet.
             */
            var _SortColumnAction = /** @class */ (function (_super) {
                __extends(_SortColumnAction, _super);
                /*
                 * Initializes a new instance of the @see:_CellMergeAction class.
                 *
                 * @param owner The @see: FlexSheet control that the @see:_CellMergeAction works for.
                 */
                function _SortColumnAction(owner) {
                    var _this = this;
                    var rowIndex, colIndex, columns = [], rows = [];
                    _this = _super.call(this, owner) || this;
                    if (!owner.itemsSource) {
                        for (rowIndex = 0; rowIndex < owner.rows.length; rowIndex++) {
                            rows.push(owner.rows[rowIndex]);
                        }
                        for (colIndex = 0; colIndex < owner.columns.length; colIndex++) {
                            columns.push(owner.columns[colIndex]);
                        }
                    }
                    _this._oldValue = {
                        sortList: owner.sortManager._committedList.slice(),
                        rows: rows,
                        columns: columns,
                        formulas: owner._scanFormulas()
                    };
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _SortColumnAction.prototype.undo = function () {
                    var self = this, rowIndex, colIndex, row, column;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._isUndoing = true;
                    self._owner.deferUpdate(function () {
                        self._owner._clearCalcEngine();
                        self._owner.sortManager.sortDescriptions.sourceCollection = self._oldValue.sortList.slice();
                        self._owner.sortManager.commitSort(false);
                        self._owner.sortManager._refresh();
                        if (!self._owner.itemsSource) {
                            self._owner.rows.clear();
                            self._owner.columns.clear();
                            self._owner.selectedSheet.grid.rows.clear();
                            self._owner.selectedSheet.grid.columns.clear();
                            for (rowIndex = 0; rowIndex < self._oldValue.rows.length; rowIndex++) {
                                row = self._oldValue.rows[rowIndex];
                                self._owner.rows.push(row);
                                // Synch the rows of the grid for current sheet.
                                self._owner.selectedSheet.grid.rows.push(row);
                            }
                            for (colIndex = 0; colIndex < self._oldValue.columns.length; colIndex++) {
                                column = self._oldValue.columns[colIndex];
                                self._owner.columns.push(column);
                                // Synch the columns of the grid for current sheet.
                                self._owner.selectedSheet.grid.columns.push(column);
                            }
                            self._owner._resetFormulas(self._oldValue.formulas);
                            self._owner._isUndoing = false;
                            setTimeout(function () {
                                self._owner._setFlexSheetToDirty();
                                self._owner.refresh(true);
                            }, 10);
                        }
                    });
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _SortColumnAction.prototype.redo = function () {
                    var self = this, rowIndex, colIndex, row, column;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._isUndoing = true;
                    self._owner.deferUpdate(function () {
                        self._owner._clearCalcEngine();
                        self._owner.sortManager.sortDescriptions.sourceCollection = self._newValue.sortList.slice();
                        self._owner.sortManager.commitSort(false);
                        self._owner.sortManager._refresh();
                        if (!self._owner.itemsSource) {
                            self._owner.rows.clear();
                            self._owner.columns.clear();
                            self._owner.selectedSheet.grid.rows.clear();
                            self._owner.selectedSheet.grid.columns.clear();
                            for (rowIndex = 0; rowIndex < self._newValue.rows.length; rowIndex++) {
                                row = self._newValue.rows[rowIndex];
                                self._owner.rows.push(row);
                                // Synch the rows of the grid for current sheet.
                                self._owner.selectedSheet.grid.rows.push(row);
                            }
                            for (colIndex = 0; colIndex < self._newValue.columns.length; colIndex++) {
                                column = self._newValue.columns[colIndex];
                                self._owner.columns.push(column);
                                // Synch the columns of the grid for current sheet.
                                self._owner.selectedSheet.grid.columns.push(column);
                            }
                            self._owner._resetFormulas(self._newValue.formulas);
                            self._owner._isUndoing = false;
                            setTimeout(function () {
                                self._owner._setFlexSheetToDirty();
                                self._owner.refresh(true);
                            }, 10);
                        }
                    });
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _SortColumnAction.prototype.saveNewState = function () {
                    var rowIndex, colIndex, columns = [], rows = [];
                    if (!this._owner.itemsSource) {
                        for (rowIndex = 0; rowIndex < this._owner.rows.length; rowIndex++) {
                            rows.push(this._owner.rows[rowIndex]);
                        }
                        for (colIndex = 0; colIndex < this._owner.columns.length; colIndex++) {
                            columns.push(this._owner.columns[colIndex]);
                        }
                    }
                    this._newValue = {
                        sortList: this._owner.sortManager._committedList.slice(),
                        rows: rows,
                        columns: columns,
                        formulas: this._owner._scanFormulas()
                    };
                    return true;
                };
                return _SortColumnAction;
            }(_UndoAction));
            sheet._SortColumnAction = _SortColumnAction;
            /*
             * Defines the _MoveCellsAction class.
             *
             * It deals with drag & drop the rows or columns to move or copy the cells action.
             */
            var _MoveCellsAction = /** @class */ (function (_super) {
                __extends(_MoveCellsAction, _super);
                /*
                 * Initializes a new instance of the @see:_MoveCellsAction class.
                 *
                 * @param owner The @see: FlexSheet control that the @see:_MoveCellsAction works for.
                 * @param draggingCells The @see: CellRange contains dragging target cells.
                 * @param droppingCells The @see: CellRange contains the dropping target cells.
                 * @param isCopyCells Indicates whether the action is moving or copying the cells.
                 */
                function _MoveCellsAction(owner, draggingCells, droppingCells, isCopyCells) {
                    var _this = this;
                    var rowIndex, colIndex, cellIndex, val, cellStyle, table;
                    _this = _super.call(this, owner) || this;
                    if (!owner.selectedSheet) {
                        return;
                    }
                    if (draggingCells.topRow === 0 && draggingCells.bottomRow === owner.rows.length - 1) {
                        _this._isDraggingColumns = true;
                    }
                    else {
                        _this._isDraggingColumns = false;
                    }
                    _this._isCopyCells = isCopyCells;
                    _this._dragRange = draggingCells;
                    _this._dropRange = droppingCells;
                    _this._oldDroppingCells = [];
                    _this._oldDroppingColumnSetting = {};
                    for (rowIndex = droppingCells.topRow; rowIndex <= droppingCells.bottomRow; rowIndex++) {
                        for (colIndex = droppingCells.leftCol; colIndex <= droppingCells.rightCol; colIndex++) {
                            if (_this._isDraggingColumns) {
                                if (!_this._oldDroppingColumnSetting[colIndex]) {
                                    _this._oldDroppingColumnSetting[colIndex] = {
                                        dataType: owner.columns[colIndex].dataType,
                                        align: owner.columns[colIndex].align,
                                        format: owner.columns[colIndex].format
                                    };
                                }
                            }
                            cellIndex = rowIndex * _this._owner.columns.length + colIndex;
                            if (_this._owner.selectedSheet._styledCells[cellIndex]) {
                                cellStyle = JSON.parse(JSON.stringify(_this._owner.selectedSheet._styledCells[cellIndex]));
                            }
                            else {
                                cellStyle = null;
                            }
                            val = _this._owner.getCellData(rowIndex, colIndex, false);
                            _this._oldDroppingCells.push({
                                rowIndex: rowIndex,
                                columnIndex: colIndex,
                                cellContent: val,
                                cellStyle: cellStyle
                            });
                        }
                    }
                    if (isCopyCells) {
                        if (_this._isDraggingColumns) {
                            for (rowIndex = draggingCells.topRow; rowIndex <= draggingCells.bottomRow; rowIndex++) {
                                for (colIndex = draggingCells.leftCol; colIndex <= draggingCells.rightCol; colIndex++) {
                                    table = _this._owner.selectedSheet.findTable(rowIndex, colIndex);
                                    if (table && table.showHeaderRow && rowIndex === table.range.topRow) {
                                        if (!_this._draggingTableColumns) {
                                            _this._draggingTableColumns = [];
                                        }
                                        _this._draggingTableColumns.push({
                                            rowIndex: rowIndex,
                                            columnIndex: colIndex,
                                            cellContent: table.columns[colIndex - table.range.leftCol].name
                                        });
                                    }
                                }
                            }
                        }
                    }
                    else {
                        _this._draggingCells = [];
                        _this._draggingColumnSetting = {};
                        for (rowIndex = draggingCells.topRow; rowIndex <= draggingCells.bottomRow; rowIndex++) {
                            for (colIndex = draggingCells.leftCol; colIndex <= draggingCells.rightCol; colIndex++) {
                                if (_this._isDraggingColumns) {
                                    if (!_this._draggingColumnSetting[colIndex]) {
                                        _this._draggingColumnSetting[colIndex] = {
                                            dataType: owner.columns[colIndex].dataType,
                                            align: owner.columns[colIndex].align,
                                            format: owner.columns[colIndex].format
                                        };
                                    }
                                }
                                cellIndex = rowIndex * _this._owner.columns.length + colIndex;
                                if (_this._owner.selectedSheet._styledCells[cellIndex]) {
                                    cellStyle = JSON.parse(JSON.stringify(_this._owner.selectedSheet._styledCells[cellIndex]));
                                }
                                else {
                                    cellStyle = null;
                                }
                                val = _this._owner.getCellData(rowIndex, colIndex, false);
                                _this._draggingCells.push({
                                    rowIndex: rowIndex,
                                    columnIndex: colIndex,
                                    cellContent: val,
                                    cellStyle: cellStyle
                                });
                            }
                        }
                    }
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _MoveCellsAction.prototype.undo = function () {
                    var self = this, index, moveCellActionValue, cellIndex, val, cellStyle, srcColIndex, descColIndex, oldFormulas, formulaObj, oldDefinedNameVals, definedNameObj, nameIndex;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._clearCalcEngine();
                    self._owner.deferUpdate(function () {
                        var table;
                        // Update the formulas.
                        if (self._affectedFormulas) {
                            oldFormulas = self._affectedFormulas.oldFormulas;
                        }
                        // Set the 'new' formulas for redo.
                        if (!!oldFormulas && oldFormulas.length > 0) {
                            for (index = 0; index < oldFormulas.length; index++) {
                                formulaObj = oldFormulas[index];
                                if (formulaObj.sheet.name === self._owner.selectedSheet.name) {
                                    self._owner.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                }
                                else {
                                    formulaObj.sheet.grid.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                }
                            }
                        }
                        // Update defined names
                        if (self._affectedDefinedNameVals) {
                            oldDefinedNameVals = self._affectedDefinedNameVals.oldDefinedNameVals;
                        }
                        if (oldDefinedNameVals && oldDefinedNameVals.length > 0) {
                            for (index = 0; index < oldDefinedNameVals.length; index++) {
                                definedNameObj = oldDefinedNameVals[index];
                                nameIndex = self._owner._getDefinedNameIndexByName(definedNameObj.name);
                                if (nameIndex > -1) {
                                    self._owner.definedNames[nameIndex].value = definedNameObj.value;
                                }
                            }
                        }
                        for (index = 0; index < self._oldDroppingCells.length; index++) {
                            moveCellActionValue = self._oldDroppingCells[index];
                            self._owner.setCellData(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex, moveCellActionValue.cellContent);
                            table = self._owner.selectedSheet.findTable(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex);
                            if (table && table.showHeaderRow && moveCellActionValue.rowIndex === table.range.topRow) {
                                table.columns[moveCellActionValue.columnIndex - table.range.leftCol].name = moveCellActionValue.cellContent;
                            }
                            cellIndex = moveCellActionValue.rowIndex * self._owner.columns.length + moveCellActionValue.columnIndex;
                            if (moveCellActionValue.cellStyle) {
                                self._owner.selectedSheet._styledCells[cellIndex] = moveCellActionValue.cellStyle;
                            }
                            else {
                                delete self._owner.selectedSheet._styledCells[cellIndex];
                            }
                        }
                        if (self._isDraggingColumns && !!self._oldDroppingColumnSetting) {
                            Object.keys(self._oldDroppingColumnSetting).forEach(function (key) {
                                self._owner.columns[+key].dataType = self._oldDroppingColumnSetting[+key].dataType ? self._oldDroppingColumnSetting[+key].dataType : wijmo.DataType.Object;
                                self._owner.columns[+key].align = self._oldDroppingColumnSetting[+key].align;
                                self._owner.columns[+key].format = self._oldDroppingColumnSetting[+key].format;
                            });
                        }
                        if (self._isCopyCells) {
                            if (self._draggingTableColumns && self._draggingTableColumns.length > 0) {
                                for (index = 0; index < self._draggingTableColumns.length; index++) {
                                    moveCellActionValue = self._draggingTableColumns[index];
                                    table = self._owner.selectedSheet.findTable(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex);
                                    if (table && table.showHeaderRow && moveCellActionValue.rowIndex === table.range.topRow) {
                                        self._owner.setCellData(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex, moveCellActionValue.cellContent);
                                        table.columns[moveCellActionValue.columnIndex - table.range.leftCol].name = moveCellActionValue.cellContent;
                                    }
                                }
                            }
                        }
                        else {
                            for (index = 0; index < self._draggingCells.length; index++) {
                                moveCellActionValue = self._draggingCells[index];
                                self._owner.setCellData(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex, moveCellActionValue.cellContent);
                                table = self._owner.selectedSheet.findTable(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex);
                                if (table && table.showHeaderRow && moveCellActionValue.rowIndex === table.range.topRow) {
                                    table.columns[moveCellActionValue.columnIndex - table.range.leftCol].name = moveCellActionValue.cellContent;
                                }
                                cellIndex = moveCellActionValue.rowIndex * self._owner.columns.length + moveCellActionValue.columnIndex;
                                if (moveCellActionValue.cellStyle) {
                                    self._owner.selectedSheet._styledCells[cellIndex] = moveCellActionValue.cellStyle;
                                }
                            }
                            if (self._isDraggingColumns && !!self._draggingColumnSetting) {
                                Object.keys(self._draggingColumnSetting).forEach(function (key) {
                                    self._owner.columns[+key].dataType = self._draggingColumnSetting[+key].dataType ? self._draggingColumnSetting[+key].dataType : wijmo.DataType.Object;
                                    self._owner.columns[+key].align = self._draggingColumnSetting[+key].align;
                                    self._owner.columns[+key].format = self._draggingColumnSetting[+key].format;
                                });
                            }
                            if (self._isDraggingColumns) {
                                if (self._dragRange.leftCol < self._dropRange.leftCol) {
                                    descColIndex = self._dragRange.leftCol;
                                    for (srcColIndex = self._dropRange.leftCol; srcColIndex <= self._dropRange.rightCol; srcColIndex++) {
                                        self._owner._updateColumnFiler(srcColIndex, descColIndex);
                                        descColIndex++;
                                    }
                                }
                                else {
                                    descColIndex = self._dragRange.rightCol;
                                    for (srcColIndex = self._dropRange.rightCol; srcColIndex >= self._dropRange.leftCol; srcColIndex--) {
                                        self._owner._updateColumnFiler(srcColIndex, descColIndex);
                                        descColIndex--;
                                    }
                                }
                            }
                        }
                    });
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _MoveCellsAction.prototype.redo = function () {
                    var self = this, index, moveCellActionValue, cellIndex, val, cellStyle, srcColIndex, descColIndex, newFormulas, formulaObj, newDefinedNameVals, definedNameObj, nameIndex, table;
                    if (!self._owner.selectedSheet) {
                        return;
                    }
                    self._owner._clearCalcEngine();
                    self._owner.deferUpdate(function () {
                        // Update the formulas
                        if (self._affectedFormulas) {
                            newFormulas = self._affectedFormulas.newFormulas;
                        }
                        // Set the 'new' formulas for redo.
                        if (!!newFormulas && newFormulas.length > 0) {
                            for (index = 0; index < newFormulas.length; index++) {
                                formulaObj = newFormulas[index];
                                if (formulaObj.sheet.name === self._owner.selectedSheet.name) {
                                    self._owner.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                }
                                else {
                                    formulaObj.sheet.grid.setCellData(formulaObj.point.x, formulaObj.point.y, formulaObj.formula);
                                }
                            }
                        }
                        // Update defined names
                        if (self._affectedDefinedNameVals) {
                            newDefinedNameVals = self._affectedDefinedNameVals.newDefinedNameVals;
                        }
                        if (newDefinedNameVals && newDefinedNameVals.length > 0) {
                            for (index = 0; index < newDefinedNameVals.length; index++) {
                                definedNameObj = newDefinedNameVals[index];
                                nameIndex = self._owner._getDefinedNameIndexByName(definedNameObj.name);
                                if (nameIndex > -1) {
                                    self._owner.definedNames[nameIndex].value = definedNameObj.value;
                                }
                            }
                        }
                        if (self._isCopyCells) {
                            if (self._draggingTableColumns && self._draggingTableColumns.length > 0) {
                                for (index = 0; index < self._draggingTableColumns.length; index++) {
                                    moveCellActionValue = self._draggingTableColumns[index];
                                    table = self._owner.selectedSheet.findTable(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex);
                                    if (table && table.showHeaderRow && moveCellActionValue.rowIndex === table.range.topRow) {
                                        self._owner.setCellData(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex, moveCellActionValue.updatedCellContent);
                                        table.columns[moveCellActionValue.columnIndex - table.range.leftCol].name = moveCellActionValue.updatedCellContent;
                                    }
                                }
                            }
                        }
                        else {
                            for (index = 0; index < self._draggingCells.length; index++) {
                                moveCellActionValue = self._draggingCells[index];
                                table = self._owner.selectedSheet.findTable(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex);
                                if (table && table.showHeaderRow && moveCellActionValue.rowIndex === table.range.topRow) {
                                    self._owner.setCellData(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex, moveCellActionValue.updatedCellContent);
                                    table.columns[moveCellActionValue.columnIndex - table.range.leftCol].name = moveCellActionValue.updatedCellContent;
                                }
                                else {
                                    self._owner.setCellData(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex, null);
                                }
                                cellIndex = moveCellActionValue.rowIndex * self._owner.columns.length + moveCellActionValue.columnIndex;
                                if (self._owner.selectedSheet._styledCells[cellIndex]) {
                                    delete self._owner.selectedSheet._styledCells[cellIndex];
                                }
                            }
                            if (self._isDraggingColumns && !!self._draggingColumnSetting) {
                                Object.keys(self._draggingColumnSetting).forEach(function (key) {
                                    self._owner.columns[+key].dataType = wijmo.DataType.Object;
                                    self._owner.columns[+key].align = null;
                                    self._owner.columns[+key].format = null;
                                });
                            }
                        }
                        for (index = 0; index < self._newDroppingCells.length; index++) {
                            moveCellActionValue = self._newDroppingCells[index];
                            self._owner.setCellData(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex, moveCellActionValue.cellContent);
                            table = self._owner.selectedSheet.findTable(moveCellActionValue.rowIndex, moveCellActionValue.columnIndex);
                            if (table && table.showHeaderRow && moveCellActionValue.rowIndex === table.range.topRow) {
                                table.columns[moveCellActionValue.columnIndex - table.range.leftCol].name = moveCellActionValue.cellContent;
                            }
                            cellIndex = moveCellActionValue.rowIndex * self._owner.columns.length + moveCellActionValue.columnIndex;
                            if (moveCellActionValue.cellStyle) {
                                self._owner.selectedSheet._styledCells[cellIndex] = moveCellActionValue.cellStyle;
                            }
                            else {
                                delete self._owner.selectedSheet._styledCells[cellIndex];
                            }
                        }
                        if (self._isDraggingColumns && !!self._newDroppingColumnSetting) {
                            Object.keys(self._newDroppingColumnSetting).forEach(function (key) {
                                self._owner.columns[+key].dataType = self._newDroppingColumnSetting[+key].dataType ? self._newDroppingColumnSetting[+key].dataType : wijmo.DataType.Object;
                                self._owner.columns[+key].align = self._newDroppingColumnSetting[+key].align;
                                self._owner.columns[+key].format = self._newDroppingColumnSetting[+key].format;
                            });
                        }
                        if (self._isDraggingColumns && !self._isCopyCells) {
                            if (self._dragRange.leftCol > self._dropRange.leftCol) {
                                descColIndex = self._dropRange.leftCol;
                                for (srcColIndex = self._dragRange.leftCol; srcColIndex <= self._dragRange.rightCol; srcColIndex++) {
                                    self._owner._updateColumnFiler(srcColIndex, descColIndex);
                                    descColIndex++;
                                }
                            }
                            else {
                                descColIndex = self._dropRange.rightCol;
                                for (srcColIndex = self._dragRange.rightCol; srcColIndex >= self._dragRange.leftCol; srcColIndex--) {
                                    self._owner._updateColumnFiler(srcColIndex, descColIndex);
                                    descColIndex--;
                                }
                            }
                        }
                    });
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _MoveCellsAction.prototype.saveNewState = function () {
                    var rowIndex, colIndex, cellIndex, val, cellStyle, index, draggingCell, table;
                    if (!this._owner.selectedSheet) {
                        return false;
                    }
                    if (this._dropRange) {
                        this._newDroppingCells = [];
                        this._newDroppingColumnSetting = {};
                        for (rowIndex = this._dropRange.topRow; rowIndex <= this._dropRange.bottomRow; rowIndex++) {
                            for (colIndex = this._dropRange.leftCol; colIndex <= this._dropRange.rightCol; colIndex++) {
                                if (this._isDraggingColumns) {
                                    if (!this._newDroppingColumnSetting[colIndex]) {
                                        this._newDroppingColumnSetting[colIndex] = {
                                            dataType: this._owner.columns[colIndex].dataType,
                                            align: this._owner.columns[colIndex].align,
                                            format: this._owner.columns[colIndex].format
                                        };
                                    }
                                }
                                cellIndex = rowIndex * this._owner.columns.length + colIndex;
                                if (this._owner.selectedSheet._styledCells[cellIndex]) {
                                    cellStyle = JSON.parse(JSON.stringify(this._owner.selectedSheet._styledCells[cellIndex]));
                                }
                                else {
                                    cellStyle = null;
                                }
                                val = this._owner.getCellData(rowIndex, colIndex, false);
                                this._newDroppingCells.push({
                                    rowIndex: rowIndex,
                                    columnIndex: colIndex,
                                    cellContent: val,
                                    cellStyle: cellStyle
                                });
                            }
                        }
                        if (this._isDraggingColumns) {
                            if (this._isCopyCells) {
                                if (this._draggingTableColumns && this._draggingTableColumns.length > 0) {
                                    if (this._draggingTableColumns && this._draggingTableColumns.length > 0) {
                                        for (index = 0; index < this._draggingTableColumns.length; index++) {
                                            draggingCell = this._draggingTableColumns[index];
                                            table = this._owner.selectedSheet.findTable(draggingCell.rowIndex, draggingCell.columnIndex);
                                            if (table && table.showHeaderRow && draggingCell.rowIndex === table.range.topRow) {
                                                draggingCell.updatedCellContent = table.columns[draggingCell.columnIndex - table.range.leftCol].name;
                                            }
                                        }
                                    }
                                }
                            }
                            else {
                                if (this._draggingCells && this._draggingCells.length > 0) {
                                    for (index = 0; index < this._draggingCells.length; index++) {
                                        draggingCell = this._draggingCells[index];
                                        table = this._owner.selectedSheet.findTable(draggingCell.rowIndex, draggingCell.columnIndex);
                                        if (table && table.showHeaderRow && draggingCell.rowIndex === table.range.topRow) {
                                            draggingCell.updatedCellContent = table.columns[draggingCell.columnIndex - table.range.leftCol].name;
                                        }
                                    }
                                }
                            }
                        }
                        return true;
                    }
                    return false;
                };
                return _MoveCellsAction;
            }(_UndoAction));
            sheet._MoveCellsAction = _MoveCellsAction;
            /*
             * Defines the _CutAction class.
             *
             * It deals with the undo/redo for cutting pasting values in FlexSheet cells.
             */
            var _CutAction = /** @class */ (function (_super) {
                __extends(_CutAction, _super);
                /*
                 * Initializes a new instance of the @see:_CutAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _CutAction works for.
                 */
                function _CutAction(owner) {
                    var _this = this;
                    var rowIndex, colIndex, val, cutSource;
                    _this = _super.call(this, owner) || this;
                    _this._oldValues = [];
                    _this._oldCutValues = [];
                    _this._mergeAction = new _CellMergeAction(owner);
                    _this._cutSheet = owner._copiedSheet;
                    _this._selection = owner.selection;
                    _this._cutSelection = owner._copiedRanges[0];
                    cutSource = _this._cutSheet === owner.selectedSheet ? owner : _this._cutSheet.grid;
                    for (rowIndex = _this._cutSelection.topRow; rowIndex <= _this._cutSelection.bottomRow; rowIndex++) {
                        if (cutSource.rows[rowIndex] == null) {
                            continue;
                        }
                        for (colIndex = _this._cutSelection.leftCol; colIndex <= _this._cutSelection.rightCol; colIndex++) {
                            val = cutSource.getCellData(rowIndex, colIndex, !!cutSource.columns[colIndex].dataMap);
                            val = val == null ? '' : val;
                            _this._oldCutValues.push({
                                row: rowIndex,
                                col: colIndex,
                                value: val
                            });
                        }
                    }
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _CutAction.prototype.undo = function () {
                    var self = this;
                    self._owner._clearCalcEngine();
                    self._owner.selectedSheet.selectionRanges.clear();
                    self._owner.deferUpdate(function () {
                        var i, item, cutSource = self._cutSheet === self._owner.selectedSheet ? self._owner : self._cutSheet.grid;
                        self._owner.selectedSheet.selectionRanges.push(self._selection);
                        for (i = 0; i < self._oldCutValues.length; i++) {
                            item = self._oldCutValues[i];
                            cutSource.setCellData(item.row, item.col, item.value);
                        }
                        for (i = 0; i < self._oldValues.length; i++) {
                            item = self._oldValues[i];
                            self._owner.setCellData(item.row, item.col, item.value);
                        }
                        self._mergeAction.undo();
                        self._owner.refresh(false);
                    });
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _CutAction.prototype.redo = function () {
                    var self = this;
                    self._owner._clearCalcEngine();
                    self._owner.selectedSheet.selectionRanges.clear();
                    self._owner.deferUpdate(function () {
                        var i, item, cutSource = self._cutSheet === self._owner.selectedSheet ? self._owner : self._cutSheet.grid;
                        self._owner.selectedSheet.selectionRanges.push(self._selection);
                        for (i = 0; i < self._newCutValues.length; i++) {
                            item = self._newCutValues[i];
                            cutSource.setCellData(item.row, item.col, item.value);
                        }
                        for (i = 0; i < self._newValues.length; i++) {
                            item = self._newValues[i];
                            self._owner.setCellData(item.row, item.col, item.value);
                        }
                        self._mergeAction.redo();
                        self._owner.refresh(false);
                    });
                };
                /*
                 * Overrides the saveNewState of its base class @see:_UndoAction.
                 */
                _CutAction.prototype.saveNewState = function () {
                    var rowIndex, colIndex, currentCol, val, cutSource = this._cutSheet === this._owner.selectedSheet ? this._owner : this._cutSheet.grid;
                    this._newCutValues = [];
                    for (rowIndex = this._cutSelection.topRow; rowIndex <= this._cutSelection.bottomRow; rowIndex++) {
                        if (cutSource.rows[rowIndex] == null) {
                            continue;
                        }
                        for (colIndex = this._cutSelection.leftCol; colIndex <= this._cutSelection.rightCol; colIndex++) {
                            val = cutSource.getCellData(rowIndex, colIndex, !!cutSource.columns[colIndex].dataMap);
                            val = val == null ? '' : val;
                            this._newCutValues.push({
                                row: rowIndex,
                                col: colIndex,
                                value: val
                            });
                        }
                    }
                    this._newValues = [];
                    for (rowIndex = this._selection.topRow; rowIndex <= this._selection.bottomRow; rowIndex++) {
                        for (colIndex = this._selection.leftCol; colIndex <= this._selection.rightCol; colIndex++) {
                            currentCol = this._owner.columns[colIndex];
                            if (!currentCol) {
                                return false;
                            }
                            val = this._owner.getCellData(rowIndex, colIndex, !!this._owner.columns[colIndex].dataMap);
                            val = val == null ? '' : val;
                            this._newValues.push({
                                row: rowIndex,
                                col: colIndex,
                                value: val
                            });
                        }
                    }
                    this._mergeAction.saveNewState();
                    return true;
                };
                /*
                 * Update the cut action for pasting.
                 *
                 * @param rng the @see:CellRange used to update the cut action
                 */
                _CutAction.prototype.updateForPasting = function (rng) {
                    var val = this._owner.getCellData(rng.row, rng.col, !!this._owner.columns[rng.col].dataMap);
                    val = val == null ? '' : val;
                    this._oldValues.push({
                        row: rng.row,
                        col: rng.col,
                        value: val
                    });
                    this._selection.row = Math.min(this._selection.topRow, rng.topRow);
                    this._selection.row2 = Math.max(this._selection.bottomRow, rng.bottomRow);
                    this._selection.col = Math.min(this._selection.leftCol, rng.leftCol);
                    this._selection.col2 = Math.max(this._selection.rightCol, rng.rightCol);
                };
                return _CutAction;
            }(_UndoAction));
            sheet._CutAction = _CutAction;
            /*
             * Defines the _TableSettingAction class.
             *
             * It deals with the undo/redo for updating the table settings.
             */
            var _TableSettingAction = /** @class */ (function (_super) {
                __extends(_TableSettingAction, _super);
                /*
                 * Initializes a new instance of the @see:_TableSettingAction class.
                 *
                 * @param owner The @see:FlexSheet control that the _TableSettingAction works for.
                 * @param table The @see:Table need do undo/redo action.
                 */
                function _TableSettingAction(owner, table) {
                    var _this = _super.call(this, owner) || this;
                    _this._table = table;
                    _this._oldTableSetting = {
                        name: table.name,
                        style: table.style,
                        showHeaderRow: table.showHeaderRow,
                        showTotalRow: table.showTotalRow,
                        showbandedRows: table.showBandedRows,
                        showBandedColumns: table.showBandedColumns,
                        showFirstColumn: table.showFirstColumn,
                        showLastColumn: table.showLastColumn
                    };
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _TableSettingAction.prototype.undo = function () {
                    this._owner._isUndoing = true;
                    this._table.name = this._oldTableSetting.name;
                    this._table.style = this._oldTableSetting.style;
                    this._table.showHeaderRow = this._oldTableSetting.showHeaderRow;
                    this._table.showTotalRow = this._oldTableSetting.showTotalRow;
                    this._table.showBandedRows = this._oldTableSetting.showbandedRows;
                    this._table.showBandedColumns = this._oldTableSetting.showBandedColumns;
                    this._table.showFirstColumn = this._oldTableSetting.showFirstColumn;
                    this._table.showLastColumn = this._oldTableSetting.showLastColumn;
                    this._owner._isUndoing = false;
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _TableSettingAction.prototype.redo = function () {
                    this._owner._isUndoing = true;
                    this._table.name = this._newTableSetting.name;
                    this._table.style = this._newTableSetting.style;
                    this._table.showHeaderRow = this._newTableSetting.showHeaderRow;
                    this._table.showTotalRow = this._newTableSetting.showTotalRow;
                    this._table.showBandedRows = this._newTableSetting.showbandedRows;
                    this._table.showBandedColumns = this._newTableSetting.showBandedColumns;
                    this._table.showFirstColumn = this._newTableSetting.showFirstColumn;
                    this._table.showLastColumn = this._newTableSetting.showLastColumn;
                    this._owner._isUndoing = false;
                };
                /*
                 * Overrides the saveNewState of its base class @see:_UndoAction.
                 */
                _TableSettingAction.prototype.saveNewState = function () {
                    this._newTableSetting = {
                        name: this._table.name,
                        style: this._table.style,
                        showHeaderRow: this._table.showHeaderRow,
                        showTotalRow: this._table.showTotalRow,
                        showbandedRows: this._table.showBandedRows,
                        showBandedColumns: this._table.showBandedColumns,
                        showFirstColumn: this._table.showFirstColumn,
                        showLastColumn: this._table.showLastColumn
                    };
                    return true;
                };
                return _TableSettingAction;
            }(_UndoAction));
            sheet._TableSettingAction = _TableSettingAction;
            /*
             * Defines the _TableAction class.
             *
             * It deals with the undo/redo for adding table.
             */
            var _TableAction = /** @class */ (function (_super) {
                __extends(_TableAction, _super);
                /*
                 * Initializes a new instance of the @see:_TableSettingAction class.
                 *
                 * @param owner The @see:FlexSheet control that the _TableAction works for.
                 * @param table The @see:Table need do undo/redo action.
                 */
                function _TableAction(owner, table) {
                    var _this = _super.call(this, owner) || this;
                    _this._addedTable = table;
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _TableAction.prototype.undo = function () {
                    var colIndex, tableRange;
                    if (this._addedTable.showHeaderRow) {
                        tableRange = this._addedTable.range;
                        for (colIndex = 0; colIndex < tableRange.columnSpan; colIndex++) {
                            this._owner.setCellData(tableRange.topRow, tableRange.leftCol + colIndex, '');
                        }
                    }
                    this._owner.selectedSheet.tableNames.splice(this._owner.selectedSheet.tableNames.indexOf(this._addedTable.name), 1);
                    this._owner.tables.remove(this._addedTable);
                    this._owner.refresh();
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _TableAction.prototype.redo = function () {
                    var colIndex, tableRange;
                    if (this._addedTable.showHeaderRow) {
                        tableRange = this._addedTable.range;
                        for (colIndex = 0; colIndex < tableRange.columnSpan; colIndex++) {
                            this._owner.setCellData(tableRange.topRow, tableRange.leftCol + colIndex, this._addedTable.columns[colIndex].name);
                        }
                    }
                    this._owner.tables.push(this._addedTable);
                    this._owner.selectedSheet.tableNames.push(this._addedTable.name);
                    this._owner.refresh();
                };
                return _TableAction;
            }(_UndoAction));
            sheet._TableAction = _TableAction;
            /*
             * Defines the _FilteringAction class.
             *
             * It deals with the undo/redo for filtering in FlexSheet.
             */
            var _FilteringAction = /** @class */ (function (_super) {
                __extends(_FilteringAction, _super);
                /*
                 * Initializes a new instance of the @see:_FilteringAction class.
                 *
                 * @param owner The @see: FlexSheet control that the _FilteringAction works for.
                 */
                function _FilteringAction(owner) {
                    var _this = _super.call(this, owner) || this;
                    _this._oldFilterDefinition = owner._filter.filterDefinition;
                    return _this;
                }
                /*
                 * Overrides the undo method of its base class @see:_UndoAction.
                 */
                _FilteringAction.prototype.undo = function () {
                    this._owner._filter.filterDefinition = this._oldFilterDefinition;
                };
                /*
                 * Overrides the redo method of its base class @see:_UndoAction.
                 */
                _FilteringAction.prototype.redo = function () {
                    this._owner._filter.filterDefinition = this._newFilterDefinition;
                };
                /*
                 * Overrides the saveNewState method of its base class @see:_UndoAction.
                 */
                _FilteringAction.prototype.saveNewState = function () {
                    if (this._oldFilterDefinition !== this._owner._filter.filterDefinition) {
                        this._newFilterDefinition = this._owner._filter.filterDefinition;
                        return true;
                    }
                    return false;
                };
                return _FilteringAction;
            }(_UndoAction));
            sheet._FilteringAction = _FilteringAction;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Defines the ContextMenu for a @see:FlexSheet control.
             */
            var _ContextMenu = /** @class */ (function (_super) {
                __extends(_ContextMenu, _super);
                /*
                 * Initializes a new instance of the _ContextMenu class.
                 *
                 * @param element The DOM element that will host the control, or a jQuery selector (e.g. '#theCtrl').
                 * @param owner The @see: FlexSheet control what the ContextMenu works with.
                 */
                function _ContextMenu(element, owner) {
                    var _this = _super.call(this, element) || this;
                    _this._idx = -1;
                    _this._isDisableDelRow = false;
                    _this._owner = owner;
                    _this.applyTemplate('', _this.getTemplate(), {
                        _insRows: 'insert-rows',
                        _delRows: 'delete-rows',
                        _insCols: 'insert-columns',
                        _delCols: 'delete-columns',
                        _convertTable: 'convert-table'
                    });
                    _this._init();
                    return _this;
                }
                Object.defineProperty(_ContextMenu.prototype, "visible", {
                    /*
                     * Gets the visible of the context menu.
                     */
                    get: function () {
                        return this.hostElement.style.display !== 'none';
                    },
                    enumerable: true,
                    configurable: true
                });
                /*
                 * Show the context menu.
                 *
                 * @param e The mouse event.
                 * @param point The point indicates the position for the context menu.
                 */
                _ContextMenu.prototype.show = function (e, point) {
                    var posX = (point ? point.x : e.clientX) + (e ? window.pageXOffset : 0), //Left Position of Mouse Pointer
                    posY = (point ? point.y : e.clientY) + (e ? window.pageYOffset : 0); //Top Position of Mouse Pointer
                    this.hostElement.style.position = 'absolute';
                    this.hostElement.style.display = 'inline';
                    if (this._owner._isDisableDeleteRow(this._owner.selection.topRow, this._owner.selection.bottomRow)) {
                        this._isDisableDelRow = true;
                        wijmo.addClass(this._delRows, 'wj-state-disabled');
                    }
                    this._showTableOperation();
                    if (posY + this.hostElement.clientHeight > window.innerHeight) {
                        posY -= this.hostElement.clientHeight;
                    }
                    if (posX + this.hostElement.clientWidth > window.innerWidth) {
                        posX -= this.hostElement.clientWidth;
                    }
                    this.hostElement.style.top = posY + 'px';
                    this.hostElement.style.left = posX + 'px';
                };
                /*
                 * Hide the context menu.
                 */
                _ContextMenu.prototype.hide = function () {
                    this._idx = -1;
                    var menuItems = this.hostElement.querySelectorAll('.wj-context-menu-item');
                    this._removeSelectedState(menuItems);
                    this.hostElement.style.display = 'none';
                    this._isDisableDelRow = false;
                    wijmo.removeClass(this._delRows, 'wj-state-disabled');
                };
                /*
                 * Move to next context menu item.
                 */
                _ContextMenu.prototype.moveToNext = function () {
                    var menuItems = this.hostElement.querySelectorAll('.wj-context-menu-item');
                    this._removeSelectedState(menuItems);
                    this._idx++;
                    if (this._idx === 1 && this._isDisableDelRow) {
                        this._idx++;
                    }
                    while (menuItems[this._idx] && menuItems[this._idx].style.display === 'none') {
                        this._idx++;
                    }
                    if (this._idx >= menuItems.length) {
                        this._idx = 0;
                    }
                    wijmo.addClass(menuItems[this._idx], 'wj-context-menu-item-selected');
                };
                /*
                 * Move to previous context menu item
                 */
                _ContextMenu.prototype.moveToPrev = function () {
                    var menuItems = this.hostElement.querySelectorAll('.wj-context-menu-item');
                    this._removeSelectedState(menuItems);
                    this._idx--;
                    if (this._idx === 1 && this._isDisableDelRow) {
                        this._idx--;
                    }
                    while (this._idx > 0 && menuItems[this._idx].style.display === 'none') {
                        this._idx--;
                    }
                    if (this._idx < 0) {
                        this._idx = menuItems.length - 1;
                    }
                    wijmo.addClass(menuItems[this._idx], 'wj-context-menu-item-selected');
                };
                /*
                 * Move to the first context menu item
                 */
                _ContextMenu.prototype.moveToFirst = function () {
                    var menuItems = this.hostElement.querySelectorAll('.wj-context-menu-item');
                    this._removeSelectedState(menuItems);
                    this._idx = 0;
                    wijmo.addClass(menuItems[this._idx], 'wj-context-menu-item-selected');
                };
                /*
                 * Move to the last context menu item
                 */
                _ContextMenu.prototype.moveToLast = function () {
                    var menuItems = this.hostElement.querySelectorAll('.wj-context-menu-item');
                    this._removeSelectedState(menuItems);
                    this._idx = menuItems.length - 1;
                    if (menuItems[this._idx] && menuItems[this._idx].style.display === 'none') {
                        this._idx--;
                    }
                    wijmo.addClass(menuItems[this._idx], 'wj-context-menu-item-selected');
                };
                /*
                 * Handle command for the selected context menu item.
                 */
                _ContextMenu.prototype.handleContextMenu = function () {
                    if (this._idx === -1) {
                        // If there is no selected context menu item, we will select the first context menu item.
                        this.moveToNext();
                    }
                    else {
                        var menuItems = this.hostElement.querySelectorAll('.wj-context-menu-item');
                        switch (menuItems[this._idx]) {
                            case this._insCols:
                                this._owner.insertColumns();
                                break;
                            case this._insRows:
                                this._owner.insertRows();
                                break;
                            case this._delCols:
                                this._owner.deleteColumns();
                                break;
                            case this._delRows:
                                if (!this._isDisableDelRow) {
                                    this._owner.deleteRows();
                                }
                                break;
                            case this._convertTable:
                                this._addTable();
                                break;
                        }
                        this.hide();
                        this._owner.hostElement.focus();
                    }
                };
                // Initialize the context menu.
                _ContextMenu.prototype._init = function () {
                    var self = this, menuItems = this.hostElement.querySelectorAll('.wj-context-menu-item');
                    self.hostElement.style.zIndex = '9999';
                    document.querySelector('body').appendChild(self.hostElement);
                    self.addEventListener(document.body, 'mousemove', function () {
                        self._removeSelectedState(menuItems);
                    });
                    self.addEventListener(self.hostElement, 'contextmenu', function (e) {
                        e.preventDefault();
                    });
                    self.addEventListener(self._insRows, 'click', function (e) {
                        self._owner.insertRows();
                        self.hide();
                        self._owner.hostElement.focus();
                    });
                    self.addEventListener(self._delRows, 'click', function (e) {
                        if (!self._isDisableDelRow) {
                            self._owner.deleteRows();
                        }
                        self.hide();
                        self._owner.hostElement.focus();
                    });
                    self.addEventListener(self._insCols, 'click', function (e) {
                        self._owner.insertColumns();
                        self.hide();
                        self._owner.hostElement.focus();
                    });
                    self.addEventListener(self._delCols, 'click', function (e) {
                        self._owner.deleteColumns();
                        self.hide();
                        self._owner.hostElement.focus();
                    });
                    self.addEventListener(self._convertTable, 'click', function (e) {
                        self._addTable();
                        self.hide();
                        self._owner.hostElement.focus();
                    });
                };
                // Remove the selected state for the context menu items.
                _ContextMenu.prototype._removeSelectedState = function (menuItems) {
                    for (var i = 0; i < menuItems.length; i++) {
                        wijmo.removeClass(menuItems[i], 'wj-context-menu-item-selected');
                    }
                };
                // Show the table operation in the context menu.
                _ContextMenu.prototype._showTableOperation = function () {
                    var r, c, table, selectionInTable = false, selection = this._owner.selection;
                    // Tables are disabled
                    var tempIsEnabled = false;
                    if (tempIsEnabled /*!selectionInTable && !selection.isSingleCell && !this._owner._containsMergedCells(selection)*/) {
                        this._convertTable.style.display = 'inline';
                        this._convertTable.parentElement.style.display = 'inline';
                    }
                    else {
                        this._convertTable.style.display = 'none';
                        this._convertTable.parentElement.style.display = 'none';
                    }
                };
                // Add table.
                _ContextMenu.prototype._addTable = function () {
                    var range = this._owner.selection, table = this._owner.addTable(range.topRow, range.leftCol, range.rowSpan, range.columnSpan), undoAction = new sheet._TableAction(this._owner, table);
                    this._owner.undoStack._addAction(undoAction);
                };
                _ContextMenu.controlTemplate = '<div class="wj-context-menu" width="150px">' +
                    '<div class="wj-context-menu-item" wj-part="insert-rows">Insert Row</div>' +
                    '<div class="wj-context-menu-item" wj-part="delete-rows">Delete Rows</div>' +
                    '<div class="wj-context-menu-item" wj-part="insert-columns">Insert Column</div>' +
                    '<div class="wj-context-menu-item" wj-part="delete-columns">Delete Columns</div>' +
                    '<div>' +
                    '<div class="wj-state-disabled" style="width:100%;height:1px;background-color:lightgray;"></div>' +
                    '<div class="wj-context-menu-item" wj-part="convert-table">Convert To Table</div>' +
                    '</div>' +
                    '</div>';
                return _ContextMenu;
            }(wijmo.Control));
            sheet._ContextMenu = _ContextMenu;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Defines the _TabHolder control.
             */
            var _TabHolder = /** @class */ (function (_super) {
                __extends(_TabHolder, _super);
                /*
                 * Initializes a new instance of the _TabHolder class.
                 *
                 * @param element The DOM element that will host the control, or a jQuery selector (e.g. '#theCtrl').
                 * @param owner The @see: FlexSheet control that the _TabHolder control is associated to.
                 */
                function _TabHolder(element, owner) {
                    var _this = _super.call(this, element) || this;
                    _this._splitterMousedownHdl = _this._splitterMousedownHandler.bind(_this);
                    _this._owner = owner;
                    if (_this.hostElement.attributes['tabindex']) {
                        _this.hostElement.attributes.removeNamedItem('tabindex');
                    }
                    // instantiate and apply template
                    _this.applyTemplate('', _this.getTemplate(), {
                        _divSheet: 'left',
                        _divSplitter: 'splitter',
                        _divRight: 'right'
                        //_divHScrollbar: 'hscrollbar'
                    });
                    _this._init();
                    return _this;
                }
                Object.defineProperty(_TabHolder.prototype, "sheetControl", {
                    /*
                     * Gets the SheetTabs control
                     */
                    get: function () {
                        return this._sheetControl;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(_TabHolder.prototype, "visible", {
                    //get scrollBar(): ScrollBar {
                    //	return this._hScrollbar;
                    //}
                    /*
                     * Gets or sets the visibility of the TabHolder control
                     */
                    get: function () {
                        return this.hostElement.style.display !== 'none';
                    },
                    set: function (value) {
                        this.hostElement.style.display = value ? 'block' : 'none';
                        this._divSheet.style.display = value ? 'block' : 'none';
                    },
                    enumerable: true,
                    configurable: true
                });
                /*
                 * Gets the Blanket size for the TabHolder control.
                 */
                _TabHolder.prototype.getSheetBlanketSize = function () {
                    //var scrollBarSize = ScrollBar.getSize();
                    //return (scrollBarSize === 0 ? 20 : scrollBarSize + 3);
                    return 20;
                };
                /*
                 * Adjust the size of the TabHolder control
                 */
                _TabHolder.prototype.adjustSize = function () {
                    var hScrollDis = this._owner.scrollSize.width - this._owner.clientSize.width, vScrollDis = this._owner.scrollSize.height - this._owner.clientSize.height, eParent = this._divSplitter.parentElement, 
                    //totalWidth: number,
                    leftWidth;
                    if (hScrollDis <= 0) {
                        eParent.style.minWidth = '100px';
                        this._divSplitter.style.display = 'none';
                        this._divRight.style.display = 'none';
                        this._divSheet.style.width = '100%';
                        this._divSplitter.removeEventListener('mousedown', this._splitterMousedownHdl, true);
                        //this._hScrollbar.scrolled.removeHandler(this._scrollbarScrolled, this);
                    }
                    else {
                        eParent.style.minWidth = '300px';
                        this._divSplitter.style.display = 'none';
                        this._divRight.style.display = 'none';
                        //totalWidth = eParent.clientWidth - this._divSplitter.offsetWidth;
                        this._divSheet.style.width = '100%';
                        //leftWidth = Math.ceil(totalWidth / 2);
                        //this._divSheet.style.width = leftWidth + 'px';
                        //this._divRight.style.width = (totalWidth - leftWidth) + 'px';
                        //if (vScrollDis <= 0) {
                        //	this._divHScrollbar.style.marginRight = '0px';
                        //} else {
                        //	this._divHScrollbar.style.marginRight = '20px';
                        //}
                        //this._hScrollbar.scrollDistance = hScrollDis;
                        //this._hScrollbar.scrollValue = -this._owner.scrollPosition.x;
                        this._divSplitter.removeEventListener('mousedown', this._splitterMousedownHdl, true);
                        this._divSplitter.addEventListener('mousedown', this._splitterMousedownHdl, true);
                        //this._hScrollbar.scrolled.removeHandler(this._scrollbarScrolled, this);
                        //this._hScrollbar.scrolled.addHandler(this._scrollbarScrolled, this);
                        //this._hScrollbar.refresh();
                    }
                    this._sheetControl._adjustSize();
                };
                // Init the size of the splitter.
                // And init the ScrollBar, SheetTabs control 
                _TabHolder.prototype._init = function () {
                    var self = this;
                    self._funSplitterMousedown = function (e) {
                        self._splitterMouseupHandler(e);
                    };
                    self._divSplitter.parentElement.style.height = self.getSheetBlanketSize() + 'px';
                    //init scrollbar
                    //self._hScrollbar = new ScrollBar(self._divHScrollbar);
                    //init sheet
                    self._sheetControl = new sheet._SheetTabs(self._divSheet, this._owner);
                    //self._owner.scrollPositionChanged.addHandler(() => {
                    //	self._hScrollbar.scrollValue = -self._owner.scrollPosition.x;
                    //});
                };
                // Mousedown event handler for the splitter
                _TabHolder.prototype._splitterMousedownHandler = function (e) {
                    this._startPos = e.pageX;
                    document.addEventListener('mousemove', this._splitterMousemoveHandler.bind(this), true);
                    document.addEventListener('mouseup', this._funSplitterMousedown, true);
                    e.preventDefault();
                };
                // Mousemove event handler for the splitter
                _TabHolder.prototype._splitterMousemoveHandler = function (e) {
                    if (this._startPos === null || typeof (this._startPos) === 'undefined') {
                        return;
                    }
                    this._adjustDis(e.pageX - this._startPos);
                };
                // Mouseup event handler for the splitter
                _TabHolder.prototype._splitterMouseupHandler = function (e) {
                    document.removeEventListener('mousemove', this._splitterMousemoveHandler, true);
                    document.removeEventListener('mouseup', this._funSplitterMousedown, true);
                    this._adjustDis(e.pageX - this._startPos);
                    this._startPos = null;
                };
                // Adjust the distance for the splitter
                _TabHolder.prototype._adjustDis = function (dis) {
                    var rightWidth = this._divRight.offsetWidth - dis, leftWidth = this._divSheet.offsetWidth + dis;
                    if (rightWidth <= 100) {
                        rightWidth = 100;
                        dis = this._divRight.offsetWidth - rightWidth;
                        leftWidth = this._divSheet.offsetWidth + dis;
                    }
                    else if (leftWidth <= 100) {
                        leftWidth = 100;
                        dis = leftWidth - this._divSheet.offsetWidth;
                        rightWidth = this._divRight.offsetWidth - dis;
                    }
                    if (dis == 0) {
                        return;
                    }
                    this._divRight.style.width = rightWidth + 'px';
                    this._divSheet.style.width = leftWidth + 'px';
                    this._startPos = this._startPos + dis;
                    //this._hScrollbar.invalidate(false);
                };
                _TabHolder.controlTemplate = '<div>' +
                    '<div wj-part="left" style ="float:left;height:100%;overflow:hidden"></div>' + // left sheet
                    '<div wj-part="splitter" style="float:left;height:100%;width:6px;background-color:#e9eaee;padding:2px;cursor:e-resize"><div style="background-color:#8a9eb2;height:100%"></div></div>' + // splitter
                    '<div wj-part="right" style="float:left;height:100%;background-color:#e9eaee">' +
                    // We will use the native scrollbar of the flexgrid instead of the custom scrollbar of flexsheet (TFS 121971)
                    //'<div wj-part="hscrollbar" style="float:none;height:100%;border-left:1px solid #8a9eb2; padding-top:1px; display: none;"></div>' + // right scrollbar
                    '</div>' +
                    '</div>';
                return _TabHolder;
            }(wijmo.Control));
            sheet._TabHolder = _TabHolder;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Defines the _FlexSheetCellFactory class.
             *
             * This class extends the CellFactory of FlexGrid control.
             * It updates the content of the row/column header for the FlexSheet control.
             */
            var _FlexSheetCellFactory = /** @class */ (function (_super) {
                __extends(_FlexSheetCellFactory, _super);
                function _FlexSheetCellFactory() {
                    return _super !== null && _super.apply(this, arguments) || this;
                }
                /*
                 * Overrides the updateCell function of the CellFactory class.
                 *
                 * @param panel Part of the grid that owns this cell.
                 * @param r Index of this cell's row.
                 * @param c Index of this cell's column.
                 * @param cell Element that represents the cell.
                 * @param rng @see:CellRange that contains the cell's merged range, or null if the cell is not merged.
                 */
                _FlexSheetCellFactory.prototype.updateCell = function (panel, r, c, cell, rng) {
                    var g = panel.grid, r2 = r, c2 = c, content, cellIndex, flex, fc, val, data, isFormula, styleInfo, checkBox, input, bcol, format, firstVisibleCell, isGroupRow, dateVal;
                    // We shall reset the styles of current cell before updating current cell.
                    if (panel.cellType === grid.CellType.Cell) {
                        this._resetCellStyle(panel.columns[c], cell);
                    }
                    _super.prototype.updateCell.call(this, panel, r, c, cell, rng);
                    // adjust for merged ranges
                    if (rng && !rng.isSingleCell) {
                        r = rng.row;
                        c = rng.col;
                        r2 = rng.row2;
                        c2 = rng.col2;
                    }
                    bcol = g._getBindingColumn(panel, r, panel.columns[c]);
                    switch (panel.cellType) {
                        case grid.CellType.RowHeader:
                            cell.textContent = (r + 1) + '';
                            break;
                        case grid.CellType.ColumnHeader:
                            content = sheet.FlexSheet.convertNumberToAlpha(c);
                            if (cell.textContent) {
                                cell.innerHTML = cell.innerHTML.replace(wijmo.escapeHtml(cell.textContent.trim()), content).replace(cell.textContent, content);
                            }
                            else {
                                cell.innerHTML += content;
                            }
                            cell.style.textAlign = 'center';
                            break;
                        case grid.CellType.Cell:
                            flex = panel.grid;
                            cellIndex = r * flex.columns.length + c;
                            styleInfo = flex.selectedSheet && flex.selectedSheet._styledCells ? flex.selectedSheet._styledCells[cellIndex] : null;
                            if (!!rng && !rng.isSingleCell) {
                                firstVisibleCell = this._getFirstVisibleCell(flex, rng);
                                r = firstVisibleCell.row;
                                c = firstVisibleCell.col;
                            }
                            //process the header row with binding
                            if (panel.rows[r] instanceof sheet.HeaderRow) {
                                if (panel.columns[c].dataType === wijmo.DataType.Boolean) {
                                    if (cell.childElementCount === 1 && cell.firstElementChild instanceof HTMLInputElement && cell.firstElementChild.type === 'checkbox') {
                                        cell.innerHTML = wijmo.escapeHtml(panel.columns[c].header);
                                    }
                                }
                                else if (!cell.innerHTML) {
                                    cell.innerHTML = wijmo.escapeHtml(panel.columns[c].header);
                                }
                                wijmo.addClass(cell, 'wj-header-row');
                            }
                            else {
                                val = flex.getCellValue(r, c, false);
                                data = flex.getCellData(r, c, false);
                                isFormula = data != null && typeof data === 'string' && data[0] === '=';
                                isGroupRow = panel.rows[r] instanceof grid.GroupRow;
                                format = (styleInfo ? styleInfo.format : null) || (isGroupRow ? null : bcol.format);
                                if (flex.editRange && flex.editRange.contains(r, c)) {
                                    if (wijmo.isNumber(val) && !bcol.dataMap && !isFormula) {
                                        if (format) {
                                            val = this._getFormattedValue(val, format);
                                        }
                                        input = cell.querySelector('input');
                                        if (input) {
                                            input.value = val;
                                        }
                                    }
                                }
                                else {
                                    if (panel.columns[c].dataType === wijmo.DataType.Boolean) {
                                        checkBox = cell.querySelector('[type="checkbox"]');
                                        if (checkBox) {
                                            checkBox.checked = flex.getCellValue(r, c);
                                            checkBox.disabled = checkBox.disabled || !flex.canEditCell(r, c);
                                        }
                                    }
                                    else if (bcol.dataMap && !isGroupRow) {
                                        val = flex.getCellValue(r, c, true);
                                        fc = cell.firstChild;
                                        if (fc && fc.nodeType === 3 && fc.nodeValue !== val) {
                                            fc.nodeValue = val;
                                        }
                                    }
                                    else {
                                        // Only when the cell is not customized by itemFormatter or formatItem, flexsheet will handle the cell content itself.
                                        // Otherwise the customized cell content will be lost.
                                        if (cell.childElementCount === 0 && cell.textContent === flex.getCellData(r, c, true)) {
                                            val = flex.getCellValue(r, c, true);
                                            if (val !== '' && wijmo.isNumber(+val) && !isNaN(+val) && /[hsmy\:]/i.test(format)) {
                                                dateVal = sheet._Expression._fromOADate(+val);
                                                if (!isNaN(dateVal.getTime())) {
                                                    val = wijmo.Globalize.formatDate(dateVal, format);
                                                }
                                            }
                                            if (format || !isGroupRow) {
                                                val = wijmo.isString(val) ? val.replace(/^(\')(\s*[\w|=])/, '$2') : val;
                                                if (wijmo.isString(val)) {
                                                    if (val && this._isURL(val)) {
                                                        cell.innerHTML = '<a href="' + val + '" target="_blank">' + wijmo.escapeHtml(val) + '</a>';
                                                    }
                                                    else {
                                                        cell.innerHTML = wijmo.escapeHtml(val);
                                                        ;
                                                    }
                                                }
                                                else {
                                                    cell.innerHTML = val;
                                                }
                                            }
                                        }
                                    }
                                }
                                if (styleInfo) {
                                    var st = cell.style, styleInfoVal;
                                    for (var styleProp in styleInfo) {
                                        if (styleProp === 'className') {
                                            if (styleInfo.className) {
                                                wijmo.addClass(cell, styleInfo.className);
                                            }
                                        }
                                        else if (styleProp !== 'format' && (styleInfoVal = styleInfo[styleProp])) {
                                            if ((wijmo.hasClass(cell, 'wj-state-selected') || wijmo.hasClass(cell, 'wj-state-multi-selected'))
                                                && (styleProp === 'color' || styleProp === 'backgroundColor')) {
                                                st[styleProp] = '';
                                            }
                                            else if (styleProp === 'whiteSpace' && styleInfoVal === 'normal') {
                                                // Remove the whiteSpace style if the value of whiteSpace is normal. TFS 247165.
                                                // Because the whiteSpace style will cause the cell measure the width incorrectly.
                                                st[styleProp] = '';
                                            }
                                            else {
                                                if (styleProp.toLowerCase().indexOf('color') > -1 && !wijmo.isString(styleInfoVal)) {
                                                    if (styleInfoVal != null) {
                                                        st[styleProp] = flex._getThemeColor(styleInfoVal.theme, styleInfoVal.tint);
                                                    }
                                                    else {
                                                        st[styleProp] = '';
                                                    }
                                                }
                                                else {
                                                    st[styleProp] = styleInfoVal;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if (!!cell.style.backgroundColor || !!cell.style.color) {
                                if (!styleInfo) {
                                    flex.selectedSheet._styledCells[cellIndex] = styleInfo = {};
                                }
                                if (!!cell.style.backgroundColor) {
                                    styleInfo.backgroundColor = cell.style.backgroundColor;
                                }
                                if (!!cell.style.color) {
                                    styleInfo.color = cell.style.color;
                                }
                            }
                            break;
                    }
                    if (panel.cellType === grid.CellType.Cell) {
                        if (r === g._lastVisibleFrozenRow && !wijmo.hasClass(cell, 'wj-frozen-row')) {
                            wijmo.addClass(cell, 'wj-frozen-row');
                        }
                        if (c === g._lastVisibleFrozenColumn && !wijmo.hasClass(cell, 'wj-frozen-col')) {
                            wijmo.addClass(cell, 'wj-frozen-col');
                        }
                    }
                };
                // Reset the styles of the cell.
                _FlexSheetCellFactory.prototype._resetCellStyle = function (column, cell) {
                    ['fontFamily', 'fontSize', 'fontStyle', 'fontWeight', 'textDecoration', 'textAlign', 'verticalAlign', 'backgroundColor', 'color', 'whiteSpace', 'borderLeftStyle', 'borderLeftColor', 'borderLeftWidth', 'borderRightStyle', 'borderRightColor', 'borderRightWidth', 'borderTopStyle', 'borderTopColor', 'borderTopWidth', 'borderBottomStyle', 'borderBottomColor', 'borderBottomWidth'].forEach(function (val) {
                        if (val === 'textAlign') {
                            cell.style.textAlign = column.getAlignment();
                        }
                        else {
                            cell.style[val] = '';
                        }
                    });
                };
                // Get the formatted value.
                _FlexSheetCellFactory.prototype._getFormattedValue = function (value, format) {
                    var val;
                    if (value !== Math.round(value)) {
                        format = format.replace(/([a-z])(\d*)(.*)/ig, '$0112$3');
                    }
                    val = wijmo.Globalize.formatNumber(value, format, true);
                    return val;
                };
                // Get the first visible cell of the merged range.
                _FlexSheetCellFactory.prototype._getFirstVisibleCell = function (g, rng) {
                    var firstVisibleRow, firstVisibleColumn;
                    for (firstVisibleRow = rng.topRow; firstVisibleRow <= rng.bottomRow; firstVisibleRow++) {
                        if (g.rows[firstVisibleRow].isVisible) {
                            break;
                        }
                    }
                    for (firstVisibleColumn = rng.leftCol; firstVisibleColumn <= rng.rightCol; firstVisibleColumn++) {
                        if (g.columns[firstVisibleColumn].isVisible) {
                            break;
                        }
                    }
                    return new grid.CellRange(firstVisibleRow, firstVisibleColumn);
                };
                // Check whether the content of the cell is valid url
                _FlexSheetCellFactory.prototype._isURL = function (strUrl) {
                    var strRegex = '^(https|http|ftp|rtsp|mms)://'
                        + '(([0-9a-z_!~*\'().&=+$%-]+: )?[0-9a-z_!~*\'().&=+$%-]+@)?' //ftp's user@ 
                        + '(([0-9]{1,3}.){3}[0-9]{1,3}' // IP
                        + '|'
                        + '([0-9a-z_!~*\'()-]+.)*' // domain- www. 
                        + '([0-9a-z][0-9a-z-]{0,61})?[0-9a-z].' // second domain 
                        + '[a-z]{2,6})' // first level domain- .com or .museum 
                        + '(:[0-9]{1,4})?' // port - :80 
                        + '((/?)|' // a slash isn't required if there is no file name 
                        + '(/[0-9a-z_!~*\'().;?:@&=+$,%#-]+)+/?)$';
                    var re = new RegExp(strRegex);
                    return re.test(strUrl);
                };
                return _FlexSheetCellFactory;
            }(grid.CellFactory));
            sheet._FlexSheetCellFactory = _FlexSheetCellFactory;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
/**
 * Defines the @see:FlexSheet control and associated classes.
 *
 * The @see:FlexSheet control extends the @see:FlexGrid control to provide
 * Excel-like features.
 *
 * @fiddle:t8tp9tnx
 */
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid_1) {
        var sheet;
        (function (sheet_1) {
            'use strict';
            var FlexSheetFunctions = [
                { name: 'abs', description: 'Returns the absolute value of a number.' },
                { name: 'acos', description: 'Returns the arccosine of a number.' },
                { name: 'and', description: 'Returns TRUE if all of its arguments are TRUE.' },
                { name: 'asin', description: 'Returns the arcsine of a number.' },
                { name: 'atan', description: 'Returns the arctangent of a number.' },
                { name: 'atan2', description: 'Returns the arctangent from x- and y-coordinates.' },
                { name: 'average', description: 'Returns the average of its arguments.' },
                { name: 'ceiling', description: 'Rounds a number to the nearest integer or to the nearest multiple of significance.' },
                { name: 'char', description: 'Returns the character specified by the code number.' },
                { name: 'choose', description: 'Chooses a value from a list of values.' },
                { name: 'code', description: 'Returns a numeric code for the first character in a text string.' },
                { name: 'column', description: 'Returns the column number of a reference.' },
                { name: 'columns', description: 'Returns the number of columns in a reference.' },
                { name: 'concatenate', description: 'Joins several text items into one text item.' },
                { name: 'cos', description: 'Returns the cosine of a number.' },
                { name: 'count', description: 'Counts how many numbers are in the list of arguments.' },
                { name: 'counta', description: 'Counts how many values are in the list of arguments.' },
                { name: 'countblank', description: 'Counts the number of blank cells within a range.' },
                { name: 'countif', description: 'Counts the number of cells within a range that meet the given criteria.' },
                { name: 'countifs', description: 'Counts the number of cells within a range that meet multiple criteria.' },
                { name: 'date', description: 'Returns the serial number of a particular date.' },
                { name: 'datedif', description: 'Calculates the number of days, months, or years between two dates.' },
                { name: 'day', description: 'Converts a serial number to a day of the month.' },
                { name: 'dcount', description: 'Counts the cells that contain numbers in a database.' },
                { name: 'exp', description: 'Returns e raised to the power of a given number.' },
                { name: 'false', description: 'Returns the logical value FALSE.' },
                { name: 'find', description: 'Finds one text value within another (case-sensitive).' },
                { name: 'floor', description: 'Rounds a number down, toward zero.' },
                { name: 'hlookup', description: 'Looks in the top row of an array and returns the value of the indicated cell.' },
                { name: 'hour', description: 'Converts a serial number to an hour.' },
                { name: 'if', description: 'Specifies a logical test to perform.' },
                { name: 'index', description: 'Uses an index to choose a value from a reference.' },
                { name: 'left', description: 'Returns the leftmost characters from a text value.' },
                { name: 'len', description: 'Returns the number of characters in a text string.' },
                { name: 'ln', description: 'Returns the natural logarithm of a number.' },
                { name: 'lower', description: 'Converts text to lowercase.' },
                { name: 'max', description: 'Returns the maximum value in a list of arguments.' },
                { name: 'mid', description: 'Returns a specific number of characters from a text string starting at the position you specify.' },
                { name: 'min', description: 'Returns the minimum value in a list of arguments.' },
                { name: 'mod', description: 'Returns the remainder from division.' },
                { name: 'month', description: 'Converts a serial number to a month.' },
                { name: 'not', description: 'Reverses the logic of its argument.' },
                { name: 'now', description: 'Returns the serial number of the current date and time.' },
                { name: 'or', description: 'Returns TRUE if any argument is TRUE.' },
                { name: 'pi', description: 'Returns the value of pi.' },
                { name: 'power', description: 'Returns the result of a number raised to a power.' },
                { name: 'product', description: 'Multiplies its arguments.' },
                { name: 'proper', description: 'Capitalizes the first letter in each word of a text value.' },
                { name: 'rand', description: 'Returns a random number between 0 and 1.' },
                { name: 'rank', description: 'Returns the rank of a number in a list of numbers.' },
                { name: 'rate', description: 'Returns the interest rate per period of an annuity.' },
                { name: 'replace', description: 'Replaces characters within text.' },
                { name: 'rept', description: 'Repeats text a given number of times.' },
                { name: 'right', description: 'Returns the rightmost characters from a text value.' },
                { name: 'round', description: 'Rounds a number to a specified number of digits.' },
                { name: 'rounddown', description: 'Rounds a number down, toward zero.' },
                { name: 'roundup', description: 'Rounds a number up, away from zero.' },
                { name: 'row', description: 'Returns the row number of a reference.' },
                { name: 'rows', description: 'Returns the number of rows in a reference.' },
                { name: 'search', description: 'Finds one text value within another (not case-sensitive).' },
                { name: 'sin', description: 'Returns the sine of the given angle.' },
                { name: 'sqrt', description: 'Returns a positive square root.' },
                { name: 'stdev', description: 'Estimates standard deviation based on a sample.' },
                { name: 'stdevp', description: 'Calculates standard deviation based on the entire population.' },
                { name: 'substitute', description: 'Substitutes new text for old text in a text string.' },
                { name: 'subtotal', description: 'Returns a subtotal in a list or database.' },
                { name: 'sum', description: 'Adds its arguments.' },
                { name: 'sumif', description: 'Adds the cells specified by a given criteria.' },
                { name: 'sumifs', description: 'Adds the cells in a range that meet multiple criteria.' },
                { name: 'sumproduct', description: 'Multiplies corresponding components in the given arrays, and returns the sum of those products.' },
                { name: 'tan', description: 'Returns the tangent of a number.' },
                { name: 'text', description: 'Formats a number and converts it to text.' },
                { name: 'time', description: 'Returns the serial number of a particular time.' },
                { name: 'today', description: 'Returns the serial number of today\'s date.' },
                { name: 'trim', description: 'Removes spaces from text.' },
                { name: 'true', description: 'Returns the logical value TRUE.' },
                { name: 'trunc', description: 'Truncates a number to an integer.' },
                { name: 'upper', description: 'Converts text to uppercase.' },
                { name: 'value', description: 'Converts a text argument to a number.' },
                { name: 'var', description: 'Estimates variance based on a sample.' },
                { name: 'varp', description: 'Calculates variance based on the entire population.' },
                { name: 'year', description: 'Converts a serial number to a year.' },
            ];
            /**
             * Defines the @see:FlexSheet control.
             *
             * The @see:FlexSheet control extends the @see:FlexGrid control to provide Excel-like
             * features such as a calculation engine, multiple sheets, undo/redo, and
             * XLSX import/export.
             *
             * A complete list of the functions supported by the @see:FlexSheet's calculation
             * engine can be found here:
             * <a href="static/FlexSheetFunctions.html">FlexSheet Functions</a>.
             *
             * @fiddle:t8tp9tnx
             */
            var FlexSheet = /** @class */ (function (_super) {
                __extends(FlexSheet, _super);
                /**
                 * Initializes a new instance of the @see:FlexSheet class.
                 *
                 * @param element The DOM element that will host the control, or a jQuery selector (e.g. '#theCtrl').
                 * @param options JavaScript object containing initialization data for the control.
                 */
                function FlexSheet(element, options) {
                    var _this = _super.call(this, element, options) || this;
                    _this._selectedSheetIndex = -1;
                    _this._columnHeaderClicked = false;
                    _this._addingSheet = false;
                    _this._mouseMoveHdl = _this._mouseMove.bind(_this);
                    _this._clickHdl = _this._click.bind(_this);
                    _this._touchStartHdl = _this._touchStart.bind(_this);
                    _this._touchEndHdl = _this._touchEnd.bind(_this);
                    _this._isContextMenuKeyDown = false;
                    _this._isClicking = false;
                    _this._resettingFilter = false;
                    _this._definedNames = new wijmo.collections.ObservableArray();
                    _this._builtInTableStylesCache = {};
                    _this._needCopyToSheet = true;
                    /**
                     * Occurs when current sheet index changed.
                     */
                    _this.selectedSheetChanged = new wijmo.Event();
                    /**
                     * Occurs when dragging the rows or the columns of the <b>FlexSheet</b>.
                     */
                    _this.draggingRowColumn = new wijmo.Event();
                    /**
                     * Occurs when dropping the rows or the columns of the <b>FlexSheet</b>.
                     */
                    _this.droppingRowColumn = new wijmo.Event();
                    /**
                     * Occurs after the @see:FlexSheet loads the @see:Workbook instance
                     */
                    _this.loaded = new wijmo.Event();
                    /**
                     * Occurs when the @see:FlexSheet meets the unknown formula.
                     */
                    _this.unknownFunction = new wijmo.Event();
                    /**
                     * Occurs when the @see:FlexSheet is cleared.
                     */
                    _this.sheetCleared = new wijmo.Event();
                    /**
                     * Occurs before the @see:FlexSheet insert\delete rows.
                     */
                    _this.prepareChangingRow = new wijmo.Event();
                    /**
                     * Occurs before the @see:FlexSheet insert\delete columns.
                     */
                    _this.prepareChangingColumn = new wijmo.Event();
                    /**
                     * Occurs after the @see:FlexSheet insert\delete rows.
                     */
                    _this.rowChanged = new wijmo.Event();
                    /**
                     * Occurs after the @see:FlexSheet insert\delete columns.
                     */
                    _this.columnChanged = new wijmo.Event();
                    _this._needCopyToSheet = false;
                    // TBD: should take it from _xlsx._defaultColorThemes?
                    //this._colorThemes = wijmo.xlsx._xlsx._defaultColorThemes.slice();
                    _this._colorThemes = ['FFFFFF', '000000', 'EEECE1', '1F497D', '4F818D', 'C0504D', '9BBB59', '8064A2', '4BACC6', 'F79646'];
                    _this['_eCt'].style.backgroundColor = 'white';
                    // We will use the native scrollbar of the flexgrid instead of the custom scrollbar of flexsheet (TFS 121971)
                    //this['_root'].style.overflowX = 'hidden';
                    wijmo.addClass(_this.hostElement, 'wj-flexsheet');
                    // Set the default font to Arial of the FlexSheet control (TFS 127769) 
                    wijmo.setCss(_this.hostElement, {
                        fontFamily: 'Arial'
                    });
                    _this['_cf'] = new sheet_1._FlexSheetCellFactory();
                    _this['_bndSortConverter'] = _this._sheetSortConverter.bind(_this);
                    _this.quickAutoSize = false;
                    // initialize the splitter, the sheet tab and the hscrollbar.
                    _this._init();
                    _this.showSort = false;
                    _this.allowSorting = false;
                    _this.showGroups = false;
                    _this.showMarquee = true;
                    _this.showSelectedHeaders = grid_1.HeadersVisibility.All;
                    _this.allowResizing = grid_1.AllowResizing.Both;
                    _this.allowDragging = grid_1.AllowDragging.None;
                    _this._needCopyToSheet = true;
                    return _this;
                }
                Object.defineProperty(FlexSheet.prototype, "sheets", {
                    /**
                     * Gets the collection of @see:Sheet objects representing workbook sheets.
                     */
                    get: function () {
                        if (!this._sheets) {
                            this._sheets = new sheet_1.SheetCollection();
                            this._sheets.selectedSheetChanged.addHandler(this._selectedSheetChange, this);
                            this._sheets.collectionChanged.addHandler(this._sourceChange, this);
                            this._sheets.sheetVisibleChanged.addHandler(this._sheetVisibleChange, this);
                            this._sheets.sheetCleared.addHandler(this.onSheetCleared, this);
                        }
                        return this._sheets;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "selectedSheetIndex", {
                    /**
                     * Gets or sets the index of the current sheet in the @see:FlexSheet.
                     */
                    get: function () {
                        return this._selectedSheetIndex;
                    },
                    set: function (value) {
                        if (value !== this._selectedSheetIndex) {
                            this._showSheet(value);
                            this._sheets.selectedIndex = value;
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "selectedSheet", {
                    /**
                     * Gets the current @see:Sheet in the <b>FlexSheet</b>.
                     */
                    get: function () {
                        return this._sheets[this._selectedSheetIndex];
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "isFunctionListOpen", {
                    /**
                     * Gets a value indicating whether the function list is opened.
                     */
                    get: function () {
                        return this._functionListHost && this._functionListHost.style.display !== 'none';
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "isTabHolderVisible", {
                    /**
                     * Gets or sets a value indicating whether the TabHolder is visible.
                     */
                    get: function () {
                        return this._tabHolder.visible;
                    },
                    set: function (value) {
                        if (value !== this._tabHolder.visible) {
                            if (value) {
                                this._divContainer.style.height = (this._divContainer.parentElement.clientHeight - this._tabHolder.getSheetBlanketSize()) + 'px';
                            }
                            else {
                                this._divContainer.style.height = this._divContainer.parentElement.clientHeight + 'px';
                            }
                            this._tabHolder.visible = value;
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "undoStack", {
                    /**
                     * Gets the @see:UndoStack instance that controls undo and redo operations of the <b>FlexSheet</b>.
                     */
                    get: function () {
                        return this._undoStack;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "sortManager", {
                    /**
                     * Gets the @see:SortManager instance that controls <b>FlexSheet</b> sorting.
                     */
                    get: function () {
                        return this._sortManager;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "showFilterIcons", {
                    /**
                     * Gets or sets the visiblity of the filter icon.
                     */
                    get: function () {
                        if (!!this._filter) {
                            return this._filter.showFilterIcons;
                        }
                        return false;
                    },
                    set: function (value) {
                        if (!!this._filter && this._filter.showFilterIcons !== value) {
                            this._filter.showFilterIcons = value;
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "definedNames", {
                    /**
                     * Gets an array the @see:IDefinedName objects representing named ranges/expressions
                     * defined in the <b>FlexSheet</b>.
                     */
                    get: function () {
                        return this._definedNames;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(FlexSheet.prototype, "tables", {
                    /*
                     * Gets the tables define in FlexSheet.
                     */
                    get: function () {
                        return this._tables;
                    },
                    enumerable: true,
                    configurable: true
                });
                /**
                 * Raises the currentSheetChanged event.
                 *
                 * @param e @see:PropertyChangedEventArgs that contains the event data.
                 */
                FlexSheet.prototype.onSelectedSheetChanged = function (e) {
                    this._sortManager._refresh();
                    this.selectedSheetChanged.raise(this, e);
                };
                /**
                 * Raises the draggingRowColumn event.
                 */
                FlexSheet.prototype.onDraggingRowColumn = function (e) {
                    this.draggingRowColumn.raise(this, e);
                };
                /**
                 * Raises the droppingRowColumn event.
                 */
                FlexSheet.prototype.onDroppingRowColumn = function (e) {
                    this.droppingRowColumn.raise(this, new wijmo.EventArgs());
                };
                /**
                 * Raises the loaded event.
                 */
                FlexSheet.prototype.onLoaded = function (e) {
                    var self = this;
                    if (self._toRefresh) {
                        clearTimeout(self._toRefresh);
                        self._toRefresh = null;
                    }
                    self._toRefresh = setTimeout(function () {
                        self._setFlexSheetToDirty();
                        self.invalidate();
                    }, 10);
                    self.loaded.raise(this, new wijmo.EventArgs());
                };
                /**
                 * Raises the unknownFunction event.
                 */
                FlexSheet.prototype.onUnknownFunction = function (e) {
                    this.unknownFunction.raise(this, e);
                };
                /**
                 * Raises the sheetCleared event.
                 */
                FlexSheet.prototype.onSheetCleared = function (e) {
                    this.sheetCleared.raise(this, new wijmo.EventArgs());
                };
                /**
                 * Raises the prepareChangingRow event.
                 */
                FlexSheet.prototype.onPrepareChangingRow = function () {
                    this.prepareChangingRow.raise(this, new wijmo.EventArgs());
                };
                /**
                 * Raises the prepareChangingColumn event.
                 */
                FlexSheet.prototype.onPrepareChangingColumn = function () {
                    this.prepareChangingColumn.raise(this, new wijmo.EventArgs());
                };
                /**
                 * Raises the rowChanged event.
                 */
                FlexSheet.prototype.onRowChanged = function (e) {
                    this.rowChanged.raise(this, e);
                };
                /**
                 * Raises the columnChanged event.
                 */
                FlexSheet.prototype.onColumnChanged = function (e) {
                    this.columnChanged.raise(this, e);
                };
                /**
                 * Overridden to refresh the sheet and the TabHolder.
                 *
                 * @param fullUpdate Whether to update the control layout as well as the content.
                 */
                FlexSheet.prototype.refresh = function (fullUpdate) {
                    if (fullUpdate === void 0) { fullUpdate = true; }
                    var rowIndex, row, colIndex, col;
                    this._divContainer.style.height = (this._divContainer.parentElement.clientHeight - (this.isTabHolderVisible ? this._tabHolder.getSheetBlanketSize() : 0)) + 'px';
                    if (!this.preserveSelectedState && !!this.selectedSheet) {
                        this.selectedSheet.selectionRanges.clear();
                        this.selectedSheet.selectionRanges.push(this.selection);
                    }
                    if (fullUpdate) {
                        this._clearCalcEngine();
                    }
                    this._lastVisibleFrozenRow = -1;
                    if (this.frozenRows > 0) {
                        for (var ri = this.frozenRows - 1; ri >= 0; ri--) {
                            if (this.rows[ri] && this.rows[ri].isVisible) {
                                this._lastVisibleFrozenRow = ri;
                                break;
                            }
                        }
                    }
                    this._lastVisibleFrozenColumn = -1;
                    if (this.frozenColumns > 0) {
                        for (var ci = this.frozenColumns - 1; ci >= 0; ci--) {
                            if (this.columns[ci] && this.columns[ci].isVisible) {
                                this._lastVisibleFrozenColumn = ci;
                                break;
                            }
                        }
                    }
                    if (this.selectedSheet) {
                        if (this.selectedSheet._freezeHiddenRowCnt > 0) {
                            for (rowIndex = 0; rowIndex < this.selectedSheet._freezeHiddenRowCnt; rowIndex++) {
                                row = this.rows[rowIndex];
                                if (!(row instanceof HeaderRow)) {
                                    row.visible = false;
                                }
                            }
                        }
                        if (this.selectedSheet._freezeHiddenColumnCnt > 0) {
                            for (colIndex = 0; colIndex < this.selectedSheet._freezeHiddenColumnCnt; colIndex++) {
                                this.columns[colIndex].visible = false;
                            }
                        }
                    }
                    _super.prototype.refresh.call(this, fullUpdate);
                    this._tabHolder.adjustSize();
                };
                /**
                 * Overrides the setCellData function of the base class.
                 *
                 * @param r Index of the row that contains the cell.
                 * @param c Index, name, or binding of the column that contains the cell.
                 * @param value Value to store in the cell.
                 * @param coerce Whether to change the value automatically to match the column's data type.
                 * @param invalidate Whether to invalidate the FlexSheet to show the change.
                 * @return True if the value was stored successfully, false otherwise.
                 */
                FlexSheet.prototype.setCellData = function (r, c, value, coerce, invalidate) {
                    if (coerce === void 0) { coerce = false; }
                    if (invalidate === void 0) { invalidate = true; }
                    var isFormula = wijmo.isString(value) && value.length > 1 && value[0] === '=';
                    this._clearCalcEngine();
                    return this.cells.setCellData(r, c, value, coerce && !isFormula, invalidate);
                };
                /**
                 * Overrides the base class method to take into account the function list.
                 */
                FlexSheet.prototype.containsFocus = function () {
                    return this.isFunctionListOpen || _super.prototype.containsFocus.call(this);
                };
                /**
                 * Add an unbound @see:Sheet to the <b>FlexSheet</b>.
                 *
                 * @param sheetName The name of the Sheet.
                 * @param rows The row count of the Sheet.
                 * @param cols The column count of the Sheet.
                 * @param pos The position in the <b>sheets</b> collection.
                 * @param grid The @see:FlexGrid instance associated with the @see:Sheet. If not specified then new @see:FlexGrid instance
                 * will be created.
                 */
                FlexSheet.prototype.addUnboundSheet = function (sheetName, rows, cols, pos, grid) {
                    var sheet = this._addSheet(sheetName, rows, cols, pos, grid);
                    if (sheet.selectionRanges.length === 0) {
                        // Store current selection in the selection array for multiple selection.
                        sheet.selectionRanges.push(this.selection);
                    }
                    return sheet;
                };
                /**
                 * Add a bound @see:Sheet to the <b>FlexSheet</b>.
                 *
                 * @param sheetName The name of the @see:Sheet.
                 * @param source The items source for the @see:Sheet.
                 * @param pos The position in the <b>sheets</b> collection.
                 * @param grid The @see:FlexGrid instance associated with the @see:Sheet. If not specified then new @see:FlexGrid instance
                 * will be created.
                 */
                FlexSheet.prototype.addBoundSheet = function (sheetName, source, pos, grid) {
                    var sheet = this._addSheet(sheetName, 0, 0, pos, grid);
                    if (source) {
                        sheet.itemsSource = source;
                        if (this.childItemsPath) {
                            sheet.grid.childItemsPath = this.childItemsPath;
                        }
                    }
                    if (sheet.selectionRanges.length === 0) {
                        // Store current selection in the selection array for multiple selection.
                        sheet.selectionRanges.push(this.selection);
                    }
                    return sheet;
                };
                /**
                 * Apply the style to a range of cells.
                 *
                 * @param cellStyle The @see:ICellStyle object to apply.
                 * @param cells An array of @see:CellRange objects to apply the style to. If not specified then
                 * style is applied to the currently selected cells.
                 * @param isPreview Indicates whether the applied style is just for preview.
                 */
                FlexSheet.prototype.applyCellsStyle = function (cellStyle, cells, isPreview) {
                    if (isPreview === void 0) { isPreview = false; }
                    var rowIndex, colIndex, ranges = cells || [this.selection], range, index, cellStyleAction;
                    if (!this.selectedSheet) {
                        return;
                    }
                    // Cancel current applied style.
                    if (!cellStyle && this._cloneStyle) {
                        this.selectedSheet._styledCells = JSON.parse(JSON.stringify(this._cloneStyle));
                        this._cloneStyle = null;
                        this.refresh(false);
                        return;
                    }
                    // Apply cells style for the cell range of the FlexSheet control.
                    if (ranges) {
                        if (!cells && !isPreview) {
                            cellStyleAction = new sheet_1._CellStyleAction(this, this._cloneStyle);
                            this._cloneStyle = null;
                        }
                        else if (isPreview && !this._cloneStyle) {
                            this._cloneStyle = JSON.parse(JSON.stringify(this.selectedSheet._styledCells));
                        }
                        for (index = 0; index < ranges.length; index++) {
                            range = ranges[index];
                            for (rowIndex = range.topRow; rowIndex <= range.bottomRow; rowIndex++) {
                                for (colIndex = range.leftCol; colIndex <= range.rightCol; colIndex++) {
                                    this._applyStyleForCell(rowIndex, colIndex, cellStyle);
                                }
                            }
                        }
                        if (!cells && !isPreview) {
                            cellStyleAction.saveNewState();
                            this._undoStack._addAction(cellStyleAction);
                        }
                    }
                    if (!cells) {
                        this.refresh(false);
                    }
                };
                /**
                 * Freeze or unfreeze the columns and rows of the <b>FlexSheet</b> control.
                 */
                FlexSheet.prototype.freezeAtCursor = function () {
                    var self = this, rowIndex, colIndex, frozenColumns, frozenRows, row, column;
                    if (!self.selectedSheet) {
                        return;
                    }
                    if (self.selection && self.frozenRows === 0 && self.frozenColumns === 0) {
                        // hide rows\cols scrolled above and scrolled left of the view range
                        // so the user can freeze arbitrary parts of the grid 
                        // (not necessarily starting with the first row/column)
                        if (self._ptScrl.y < 0) {
                            for (rowIndex = 0; rowIndex < self.selection.topRow - 1; rowIndex++) {
                                row = self.rows[rowIndex];
                                if (!(row instanceof HeaderRow)) {
                                    if (row._pos + self._ptScrl.y < 0) {
                                        row.visible = false;
                                    }
                                    else {
                                        self.selectedSheet._freezeHiddenRowCnt = rowIndex;
                                        break;
                                    }
                                }
                            }
                        }
                        if (self._ptScrl.x < 0) {
                            for (colIndex = 0; colIndex < self.selection.leftCol - 1; colIndex++) {
                                column = self.columns[colIndex];
                                if (column._pos + self._ptScrl.x < 0) {
                                    self.columns[colIndex].visible = false;
                                }
                                else {
                                    self.selectedSheet._freezeHiddenColumnCnt = colIndex;
                                    break;
                                }
                            }
                        }
                        // freeze
                        frozenColumns = self.selection.leftCol > 0 ? self.selection.leftCol : 0;
                        frozenRows = self.selection.topRow > 0 ? self.selection.topRow : 0;
                    }
                    else {
                        // unhide
                        for (rowIndex = 0; rowIndex < self.frozenRows - 1; rowIndex++) {
                            self.rows[rowIndex].visible = true;
                        }
                        for (colIndex = 0; colIndex < self.frozenColumns - 1; colIndex++) {
                            self.columns[colIndex].visible = true;
                        }
                        // Apply the filter of the FlexSheet again after resetting the visible of the rows. (TFS 204887)
                        self._filter.apply();
                        // unfreeze
                        frozenColumns = 0;
                        frozenRows = 0;
                        self.selectedSheet._freezeHiddenRowCnt = 0;
                        self.selectedSheet._freezeHiddenColumnCnt = 0;
                    }
                    // Synch to the grid of current sheet.
                    self.frozenRows = self.selectedSheet.grid.frozenRows = frozenRows;
                    self.frozenColumns = self.selectedSheet.grid.frozenColumns = frozenColumns;
                    setTimeout(function () {
                        self._setFlexSheetToDirty();
                        self.invalidate();
                        self.scrollIntoView(self.selection.topRow, self.selection.leftCol);
                    }, 10);
                };
                /**
                 * Show the filter editor.
                 */
                FlexSheet.prototype.showColumnFilter = function () {
                    var selectedCol = this.selection.col > 0 ? this.selection.col : 0;
                    if (this.columns.length > 0) {
                        this._filter.editColumnFilter(this.columns[selectedCol]);
                    }
                };
                /**
                 * Clears the content of the <b>FlexSheet</b> control.
                 */
                FlexSheet.prototype.clear = function () {
                    this.beginUpdate();
                    this.selection = new grid_1.CellRange();
                    this.sheets.clear();
                    this._selectedSheetIndex = -1;
                    this.columns.clear();
                    this.rows.clear();
                    this.columnHeaders.columns.clear();
                    this.rowHeaders.rows.clear();
                    this._undoStack.clear();
                    this._ptScrl = new wijmo.Point();
                    this._clearCalcEngine();
                    this._definedNames.clear();
                    if (this._tables) {
                        this._tables.clear();
                    }
                    this.addUnboundSheet();
                    this.endUpdate();
                };
                /**
                 * Gets the @see:IFormatState object describing formatting of the selected cells.
                 *
                 * @return The @see:IFormatState object containing formatting properties.
                 */
                FlexSheet.prototype.getSelectionFormatState = function () {
                    var rowIndex, colIndex, rowCount = this.rows.length, columnCount = this.columns.length, formatState = {
                        isBold: false,
                        isItalic: false,
                        isUnderline: false,
                        textAlign: 'left',
                        isMergedCell: false
                    };
                    // If there is no rows or columns in the flexsheet, we should return the default format state (TFS 122628)
                    if (rowCount === 0 || columnCount === 0) {
                        return formatState;
                    }
                    // Check the selected cells
                    if (this.selection) {
                        if (this.selection.row >= rowCount || this.selection.row2 >= rowCount
                            || this.selection.col >= columnCount || this.selection.col2 >= columnCount) {
                            return formatState;
                        }
                        for (rowIndex = this.selection.topRow; rowIndex <= this.selection.bottomRow; rowIndex++) {
                            for (colIndex = this.selection.leftCol; colIndex <= this.selection.rightCol; colIndex++) {
                                this._checkCellFormat(rowIndex, colIndex, formatState);
                            }
                        }
                    }
                    return formatState;
                };
                /**
                 * Inserts rows in the current @see:Sheet of the <b>FlexSheet</b> control.
                 *
                 * @param index The position where new rows should be added. If not specified then rows will be added
                 * before the first row of the current selection.
                 * @param count The numbers of rows to add. If not specified then one row will be added.
                 */
                FlexSheet.prototype.insertRows = function (index, count) {
                    var rowIndex = wijmo.isNumber(index) && index >= 0 ? index :
                        (this.selection && this.selection.topRow > -1) ? this.selection.topRow : 0, rowCount = wijmo.isNumber(count) ? count : 1, insRowAction = new sheet_1._RowsChangedAction(this), currentRow = this.rows[rowIndex], i;
                    if (!this.selectedSheet) {
                        return;
                    }
                    this._clearCalcEngine();
                    this.finishEditing();
                    // The header row of the bound sheet should always in the top of the flexsheet.
                    // The new should be added below the header row. (TFS #124391.)
                    if (rowIndex === 0 && currentRow && currentRow.constructor === HeaderRow) {
                        rowIndex = 1;
                    }
                    this.onPrepareChangingRow();
                    // We should update styled cells hash before adding rows.
                    this._updateCellsForUpdatingRow(this.rows.length, rowIndex, rowCount);
                    // Update the affected formulas.
                    insRowAction._affectedFormulas = this._updateAffectedFormula(rowIndex, rowCount, true, true);
                    insRowAction._affectedDefinedNameVals = this._updateAffectedNamedRanges(rowIndex, rowCount, true, true);
                    if (this.collectionView) {
                        this.collectionView.beginUpdate();
                        if (this.itemsSource instanceof wijmo.collections.CollectionView) {
                            this.itemsSource.items.splice(rowIndex - 1, 0, {});
                        }
                        else {
                            this.itemsSource.splice(rowIndex - 1, 0, {});
                        }
                        this.collectionView.endUpdate();
                    }
                    else {
                        this.rows.beginUpdate();
                        for (i = 0; i < rowCount; i++) {
                            this.rows.insert(rowIndex, new grid_1.Row());
                        }
                        this.rows.endUpdate();
                    }
                    this._updateTablesForUpdatingRow(rowIndex, rowCount);
                    if (!this.selection || this.selection.row === -1 || this.selection.col === -1) {
                        this.selection = new grid_1.CellRange(0, 0);
                    }
                    insRowAction.saveNewState();
                    this._undoStack._addAction(insRowAction);
                    this.onRowChanged(new RowColumnChangedEventArgs(rowIndex, rowCount, true));
                };
                /**
                 * Deletes rows from the current @see:Sheet of the <b>FlexSheet</b> control.
                 *
                 * @param index The starting index of the deleting rows. If not specified then rows will be deleted
                 * starting from the first row of the current selection.
                 * @param count The numbers of rows to delete. If not specified then one row will be deleted.
                 */
                FlexSheet.prototype.deleteRows = function (index, count) {
                    var rowCount = wijmo.isNumber(count) && count >= 0 ? count :
                        (this.selection && this.selection.topRow > -1) ? this.selection.bottomRow - this.selection.topRow + 1 : 1, firstRowIndex = wijmo.isNumber(index) && index >= 0 ? index :
                        (this.selection && this.selection.topRow > -1) ? this.selection.topRow : -1, lastRowIndex = wijmo.isNumber(index) && index >= 0 ? index + rowCount - 1 :
                        (this.selection && this.selection.topRow > -1) ? this.selection.bottomRow : -1, delRowAction = new sheet_1._RowsChangedAction(this), rowDeleted = false, deletingRow, deletingRowIndex, currentRowsLength;
                    if (!this.selectedSheet /*|| this.itemsSource*/) {
                        return;
                    }
                    this._clearCalcEngine();
                    this.finishEditing();
                    if (firstRowIndex > -1 && lastRowIndex > -1) {
                        this.onPrepareChangingRow();
                        // We should update styled cells hash before deleting rows.
                        this._updateCellsForUpdatingRow(this.rows.length, firstRowIndex, rowCount, true);
                        // Update the affected formulas.
                        delRowAction._affectedFormulas = this._updateAffectedFormula(lastRowIndex, lastRowIndex - firstRowIndex + 1, false, true);
                        delRowAction._affectedDefinedNameVals = this._updateAffectedNamedRanges(lastRowIndex, lastRowIndex - firstRowIndex + 1, false, true);
                        this.rows.beginUpdate();
                        for (; lastRowIndex >= firstRowIndex; lastRowIndex--) {
                            deletingRow = this.rows[lastRowIndex];
                            // The header row of the bound sheet is a specific row.
                            // So it hasn't to be deleted manually.
                            if (deletingRow && deletingRow.constructor === HeaderRow) {
                                continue;
                            }
                            // if we remove the rows in the bound sheet,
                            // we need remove the row related item in the itemsSource of the flexsheet. (TFS 121651)
                            if (deletingRow.dataItem && this.collectionView) {
                                this.collectionView.beginUpdate();
                                deletingRowIndex = this._getCvIndex(lastRowIndex);
                                if (deletingRowIndex > -1) {
                                    if (this.itemsSource instanceof wijmo.collections.CollectionView) {
                                        this.itemsSource.items.splice(lastRowIndex - 1, 1);
                                    }
                                    else {
                                        this.itemsSource.splice(lastRowIndex - 1, 1);
                                    }
                                }
                                this.collectionView.endUpdate();
                            }
                            else {
                                this.rows.removeAt(lastRowIndex);
                            }
                            rowDeleted = true;
                        }
                        this.rows.endUpdate();
                        delRowAction._deletedTables = this._updateTablesForUpdatingRow(firstRowIndex, rowCount, true);
                        currentRowsLength = this.rows.length;
                        this.selectedSheet.selectionRanges.clear();
                        if (currentRowsLength === 0) {
                            this.select(new grid_1.CellRange());
                            if (this.hostElement.style.cursor === 'move') {
                                this.hostElement.style.cursor = 'default';
                            }
                        }
                        else if (lastRowIndex === currentRowsLength - 1) {
                            this.select(new grid_1.CellRange(lastRowIndex, 0, lastRowIndex, this.columns.length - 1));
                        }
                        else {
                            this.select(new grid_1.CellRange(this.selection.topRow, this.selection.col, this.selection.topRow, this.selection.col2));
                        }
                        if (rowDeleted) {
                            delRowAction.saveNewState();
                            this._undoStack._addAction(delRowAction);
                            this.onRowChanged(new RowColumnChangedEventArgs(firstRowIndex, rowCount, false));
                        }
                    }
                };
                /**
                 * Inserts columns in the current @see:Sheet of the <b>FlexSheet</b> control.
                 *
                 * @param index The position where new columns should be added. If not specified then columns will be added
                 * before the left column of the current selection.
                 * @param count The numbers of columns to add. If not specified then one column will be added.
                 */
                FlexSheet.prototype.insertColumns = function (index, count) {
                    var columnIndex = wijmo.isNumber(index) && index >= 0 ? index :
                        this.selection && this.selection.leftCol > -1 ? this.selection.leftCol : 0, colCount = wijmo.isNumber(count) ? count : 1, insColumnAction = new sheet_1._ColumnsChangedAction(this), column, i;
                    if (!this.selectedSheet) {
                        return;
                    }
                    // We disable inserting columns manually for the bound sheet.
                    // Because it will cause the synch issue between the itemsSource and the sheet.
                    if (this.itemsSource) {
                        return;
                    }
                    this._clearCalcEngine();
                    this.finishEditing();
                    this.onPrepareChangingColumn();
                    // We should update styled cells hash before adding columns.
                    this._updateCellsForUpdatingColumn(this.columns.length, columnIndex, colCount);
                    // Update the affected formulas.
                    insColumnAction._affectedFormulas = this._updateAffectedFormula(columnIndex, colCount, true, false);
                    insColumnAction._affectedDefinedNameVals = this._updateAffectedNamedRanges(columnIndex, colCount, true, false);
                    this.columns.beginUpdate();
                    for (i = 0; i < colCount; i++) {
                        column = new grid_1.Column();
                        column.isRequired = false;
                        this.columns.insert(columnIndex, column);
                    }
                    this.columns.endUpdate();
                    this._updateTablesForUpdatingColumn(columnIndex, colCount);
                    if (!this.selection || this.selection.row === -1 || this.selection.col === -1) {
                        this.selection = new grid_1.CellRange(0, 0);
                    }
                    insColumnAction.saveNewState();
                    this._undoStack._addAction(insColumnAction);
                    this.onColumnChanged(new RowColumnChangedEventArgs(columnIndex, colCount, true));
                };
                /**
                 * Deletes columns from the current @see:Sheet of the <b>FlexSheet</b> control.
                 *
                 * @param index The starting index of the deleting columns. If not specified then columns will be deleted
                 * starting from the first column of the current selection.
                 * @param count The numbers of columns to delete. If not specified then one column will be deleted.
                 */
                FlexSheet.prototype.deleteColumns = function (index, count) {
                    var currentColumnLength, colCount = wijmo.isNumber(count) && count >= 0 ? count :
                        (this.selection && this.selection.leftCol > -1) ? this.selection.rightCol - this.selection.leftCol + 1 : 1, firstColIndex = wijmo.isNumber(index) && index >= 0 ? index :
                        (this.selection && this.selection.leftCol > -1) ? this.selection.leftCol : -1, lastColIndex = wijmo.isNumber(index) && index >= 0 ? index + colCount - 1 :
                        (this.selection && this.selection.leftCol > -1) ? this.selection.rightCol : -1, delColumnAction = new sheet_1._ColumnsChangedAction(this);
                    if (!this.selectedSheet) {
                        return;
                    }
                    // We disable deleting columns manually for the bound sheet.
                    // Because it will cause the synch issue between the itemsSource and the sheet.
                    if (this.itemsSource) {
                        return;
                    }
                    this._clearCalcEngine();
                    this.finishEditing();
                    if (firstColIndex > -1 && lastColIndex > -1) {
                        this.onPrepareChangingColumn();
                        // We should update styled cells hash before deleting columns.
                        this._updateCellsForUpdatingColumn(this.columns.length, firstColIndex, colCount, true);
                        // Update the affected formulas.
                        delColumnAction._affectedFormulas = this._updateAffectedFormula(lastColIndex, lastColIndex - firstColIndex + 1, false, false);
                        delColumnAction._affectedDefinedNameVals = this._updateAffectedNamedRanges(lastColIndex, lastColIndex - firstColIndex + 1, false, false);
                        delColumnAction._deletedTables = this._updateTablesForUpdatingColumn(firstColIndex, colCount, true);
                        this.columns.beginUpdate();
                        for (; lastColIndex >= firstColIndex; lastColIndex--) {
                            this.columns.removeAt(lastColIndex);
                            this._sortManager.deleteSortLevel(lastColIndex);
                        }
                        this.columns.endUpdate();
                        this._sortManager.commitSort(false);
                        currentColumnLength = this.columns.length;
                        this.selectedSheet.selectionRanges.clear();
                        if (currentColumnLength === 0) {
                            this.select(new grid_1.CellRange());
                            if (this.hostElement.style.cursor === 'move') {
                                this.hostElement.style.cursor = 'default';
                            }
                        }
                        else if (lastColIndex === currentColumnLength - 1) {
                            this.select(new grid_1.CellRange(0, lastColIndex, this.rows.length - 1, lastColIndex));
                        }
                        else {
                            this.select(new grid_1.CellRange(this.selection.row, this.selection.leftCol, this.selection.row2, this.selection.leftCol));
                        }
                        delColumnAction.saveNewState();
                        this._undoStack._addAction(delColumnAction);
                        this.onColumnChanged(new RowColumnChangedEventArgs(firstColIndex, colCount, false));
                    }
                };
                /**
                 * Merges the selected @see:CellRange into one cell.
                 *
                 * @param cells The @see:CellRange to merge.
                 * @param isCopyMergeCell This parameter indicates that merge operation is done by copy\paste merge cell or not.
                 */
                FlexSheet.prototype.mergeRange = function (cells, isCopyMergeCell) {
                    if (isCopyMergeCell === void 0) { isCopyMergeCell = false; }
                    var rowIndex, colIndex, cellIndex, mergedRange, range = cells || this.selection, mergedCellExists = false, cellMergeAction, firstVisibleRow = -1, table;
                    if (!this.selectedSheet) {
                        return;
                    }
                    if (range) {
                        if (range.rowSpan === 1 && range.columnSpan === 1) {
                            return;
                        }
                        // If the merge cell range intersects with table, it isn't allowed to merge.
                        for (rowIndex = range.topRow; rowIndex <= range.bottomRow; rowIndex++) {
                            for (colIndex = range.leftCol; colIndex <= range.rightCol; colIndex++) {
                                table = this.selectedSheet.findTable(rowIndex, colIndex);
                                if (table) {
                                    return;
                                }
                            }
                        }
                        if (!cells && !isCopyMergeCell) {
                            cellMergeAction = new sheet_1._CellMergeAction(this);
                            this.hostElement.focus();
                        }
                        if (!this._resetMergedRange(range)) {
                            for (rowIndex = range.topRow; rowIndex <= range.bottomRow; rowIndex++) {
                                if (firstVisibleRow < 0 && this.rows[rowIndex].visible) {
                                    firstVisibleRow = rowIndex;
                                }
                                if (firstVisibleRow < 0) {
                                    continue;
                                }
                                for (colIndex = range.leftCol; colIndex <= range.rightCol; colIndex++) {
                                    cellIndex = rowIndex * this.columns.length + colIndex;
                                    this.selectedSheet._mergedRanges[cellIndex] = new grid_1.CellRange(firstVisibleRow, range.leftCol, range.bottomRow, range.rightCol);
                                }
                            }
                            if (!cells && !isCopyMergeCell) {
                                cellMergeAction.saveNewState();
                                this._undoStack._addAction(cellMergeAction);
                            }
                        }
                    }
                    if (!cells) {
                        this.refresh();
                    }
                };
                /**
                 * Gets a @see:CellRange that specifies the merged extent of a cell
                 * in a @see:GridPanel.
                 * This method overrides the getMergedRange method of its parent class FlexGrid
                 *
                 * @param panel @see:GridPanel that contains the range.
                 * @param r Index of the row that contains the cell.
                 * @param c Index of the column that contains the cell.
                 * @param clip Whether to clip the merged range to the grid's current view range.
                 * @return A @see:CellRange that specifies the merged range, or null if the cell is not merged.
                 */
                FlexSheet.prototype.getMergedRange = function (panel, r, c, clip) {
                    if (clip === void 0) { clip = true; }
                    var cellIndex = r * this.columns.length + c, mergedRange = this.selectedSheet ? this.selectedSheet._mergedRanges[cellIndex] : null, topRow, bottonRow, leftCol, rightCol;
                    if (panel === this.cells && mergedRange) {
                        // Adjust the merged cell with the frozen pane.
                        if (!mergedRange.isSingleCell && (this.frozenRows > 0 || this.frozenColumns > 0)
                            && ((mergedRange.topRow < this.frozenRows && mergedRange.bottomRow >= this.frozenRows)
                                || (mergedRange.leftCol < this.frozenColumns && mergedRange.rightCol >= this.frozenColumns))) {
                            topRow = mergedRange.topRow;
                            bottonRow = mergedRange.bottomRow;
                            leftCol = mergedRange.leftCol;
                            rightCol = mergedRange.rightCol;
                            if (r >= this.frozenRows && mergedRange.topRow < this.frozenRows) {
                                topRow = this.frozenRows;
                            }
                            if (r < this.frozenRows && mergedRange.bottomRow >= this.frozenRows) {
                                bottonRow = this.frozenRows - 1;
                            }
                            if (bottonRow >= this.rows.length) {
                                bottonRow = this.rows.length - 1;
                            }
                            if (c >= this.frozenColumns && mergedRange.leftCol < this.frozenColumns) {
                                leftCol = this.frozenColumns;
                            }
                            if (c < this.frozenColumns && mergedRange.rightCol >= this.frozenColumns) {
                                rightCol = this.frozenColumns - 1;
                            }
                            if (rightCol >= this.columns.length) {
                                rightCol = this.columns.length - 1;
                            }
                            return new grid_1.CellRange(topRow, leftCol, bottonRow, rightCol);
                        }
                        if (mergedRange.bottomRow >= this.rows.length) {
                            return new grid_1.CellRange(mergedRange.topRow, mergedRange.leftCol, this.rows.length - 1, mergedRange.rightCol);
                        }
                        if (mergedRange.rightCol >= this.columns.length) {
                            return new grid_1.CellRange(mergedRange.topRow, mergedRange.leftCol, mergedRange.bottomRow, this.columns.length - 1);
                        }
                        return mergedRange.clone();
                    }
                    // Only when there are columns in current sheet, it will get the merge range from parent flexgrid. (TFS #142348, #143544)
                    if (c >= 0 && this.columns && this.columns.length > c && r >= 0 && this.rows && this.rows.length > r) {
                        return _super.prototype.getMergedRange.call(this, panel, r, c, clip);
                    }
                    return null;
                };
                /**
                 * Evaluates a formula.
                 *
                 * @see:FlexSheet formulas follow the Excel syntax, including a large subset of the
                 * functions supported by Excel. A complete list of the functions supported by
                 * @see:FlexSheet can be found here:
                 * <a href="static/FlexSheetFunctions.html">FlexSheet Functions</a>.
                 *
                 * @param formula The formula to evaluate. The formula may start with an optional equals sign ('=').
                 * @param format If specified, defines the .Net format that will be applied to the evaluated value.
                 * @param sheet The @see:Sheet whose data will be used for evaluation.
                 *              If not specified then the current sheet is used.
                 */
                FlexSheet.prototype.evaluate = function (formula, format, sheet) {
                    return this._evaluate(formula, format, sheet);
                };
                /**
                 * Gets the evaluated cell value.
                 *
                 * Unlike the <b>getCellData</b> method that returns a raw data that can be a value or a formula, the <b>getCellValue</b>
                 * method always returns an evaluated value, that is if the cell contains a formula then it will be evaluated first and the
                 * resulting value will be returned.
                 *
                 * @param rowIndex The row index of the cell.
                 * @param colIndex The column index of the cell.
                 * @param formatted Indicates whether to return an original or a formatted value of the cell.
                 * @param sheet The @see:Sheet whose value to evaluate. If not specified then the data from current sheet
                 * is used.
                 */
                FlexSheet.prototype.getCellValue = function (rowIndex, colIndex, formatted, sheet) {
                    if (formatted === void 0) { formatted = false; }
                    var col = sheet && sheet !== this.selectedSheet ? sheet.grid.columns[colIndex] : this.columns[colIndex], styleInfo = this._getCellStyle(rowIndex, colIndex, sheet), format, cellVal;
                    format = styleInfo && styleInfo.format ? styleInfo.format : '';
                    cellVal = sheet && sheet !== this.selectedSheet ? sheet.grid.getCellData(rowIndex, colIndex, false) : this.getCellData(rowIndex, colIndex, false);
                    if (wijmo.isString(cellVal) && cellVal[0] === '=') {
                        cellVal = this._evaluate(cellVal, formatted ? format : '', sheet, rowIndex, colIndex);
                    }
                    if (formatted) {
                        cellVal = this._formatEvaluatedResult(cellVal, col, format);
                    }
                    else if (cellVal != null && !wijmo.isPrimitive(cellVal)) {
                        cellVal = cellVal.value;
                    }
                    return cellVal == null ? '' : cellVal;
                };
                /**
                 * Open the function list.
                 *
                 * @param target The DOM element that toggle the function list.
                 */
                FlexSheet.prototype.showFunctionList = function (target) {
                    var self = this, functionOffset = self._cumulativeOffset(target), rootOffset = self._cumulativeOffset(self['_root']), offsetTop, offsetLeft;
                    self._functionTarget = wijmo.tryCast(target, HTMLInputElement);
                    if (self._functionTarget && self._functionTarget.value && self._functionTarget.value[0] === '=') {
                        self._functionList._cv.filter = function (item) {
                            var text = item['actualvalue'].toLowerCase(), searchIndex = self._getCurrentFormulaIndex(self._functionTarget.value), searchText;
                            if (searchIndex === -1) {
                                searchIndex = 0;
                            }
                            searchText = self._functionTarget.value.substr(searchIndex + 1).trim().toLowerCase();
                            if ((searchText.length > 0 && text.indexOf(searchText) === 0) || self._functionTarget.value === '=') {
                                return true;
                            }
                            return false;
                        };
                        self._functionList.selectedIndex = 0;
                        offsetTop = functionOffset.y + target.clientHeight + 2 + (wijmo.hasClass(target, 'wj-grid-editor') ? this._ptScrl.y : 0);
                        offsetLeft = functionOffset.x + (wijmo.hasClass(target, 'wj-grid-editor') ? this._ptScrl.x : 0);
                        wijmo.setCss(self._functionListHost, {
                            height: self._functionList._cv.items.length > 5 ? '218px' : 'auto',
                            display: self._functionList._cv.items.length > 0 ? 'block' : 'none',
                            top: '',
                            left: ''
                        });
                        self._functionListHost.scrollTop = 0;
                        if (self._functionListHost.offsetHeight + offsetTop > rootOffset.y + self['_root'].offsetHeight) {
                            offsetTop = offsetTop - target.clientHeight - self._functionListHost.offsetHeight - 5;
                        }
                        else {
                            offsetTop += 5;
                        }
                        if (self._functionListHost.offsetWidth + offsetLeft > rootOffset.x + self['_root'].offsetWidth) {
                            offsetLeft = rootOffset.x + self['_root'].offsetWidth - self._functionListHost.offsetWidth;
                        }
                        wijmo.setCss(self._functionListHost, {
                            top: offsetTop,
                            left: offsetLeft
                        });
                    }
                    else {
                        self.hideFunctionList();
                    }
                };
                /**
                 * Close the function list.
                 */
                FlexSheet.prototype.hideFunctionList = function () {
                    this._functionListHost.style.display = 'none';
                };
                /**
                 * Select previous function in the function list.
                 */
                FlexSheet.prototype.selectPreviousFunction = function () {
                    var index = this._functionList.selectedIndex;
                    if (index > 0) {
                        this._functionList.selectedIndex--;
                    }
                };
                /**
                 * Select next function in the function list.
                 */
                FlexSheet.prototype.selectNextFunction = function () {
                    var index = this._functionList.selectedIndex;
                    if (index < this._functionList.itemsSource.length) {
                        this._functionList.selectedIndex++;
                    }
                };
                /**
                 * Inserts the selected function from the function list to the cell value editor.
                 */
                FlexSheet.prototype.applyFunctionToCell = function () {
                    var self = this, currentFormulaIndex;
                    if (self._functionTarget) {
                        currentFormulaIndex = self._getCurrentFormulaIndex(self._functionTarget.value);
                        if (currentFormulaIndex === -1) {
                            currentFormulaIndex = self._functionTarget.value.indexOf('=');
                        }
                        else {
                            currentFormulaIndex += 1;
                        }
                        self._functionTarget.value = self._functionTarget.value.substring(0, currentFormulaIndex) + self._functionList.selectedValue + '(';
                        if (self._functionTarget.value[0] !== '=') {
                            self._functionTarget.value = '=' + self._functionTarget.value;
                        }
                        self._functionTarget.focus();
                        self.hideFunctionList();
                    }
                };
                /**
                 * Saves <b>FlexSheet</b> to xlsx file.
                 * This method works with JSZip 2.5.
                 *
                 * For example:
                 * <pre>// This sample exports FlexSheet content to an xlsx file.
                 * // click.
                 * &nbsp;
                 * // HTML
                 * &lt;button
                 *     onclick="saveXlsx('FlexSheet.xlsx')"&gt;
                 *     Save
                 * &lt;/button&gt;
                 * &nbsp;
                 * // JavaScript
                 * function saveXlsx(fileName) {
                 *     // Save the flexGrid to xlsx file.
                 *     flexsheet.save(fileName);
                 * }</pre>
                 *
                 * @param fileName Name of the file that is generated.
                 * @return A workbook instance containing the generated xlsx file content.
                 */
                FlexSheet.prototype.save = function (fileName) {
                    var workbook = this._saveToWorkbook();
                    if (fileName) {
                        workbook.save(fileName);
                    }
                    return workbook;
                };
                /**
                 * Saves the <b>FlexSheet</b> to xlsx file asynchronously.
                 * This method works with JSZip 3.0.
                 *
                 * @param fileName Name of the file that is generated.
                 * @param onSaved This callback provides an approach to get the base-64 string that
                 *  represents the content of the saved FlexSheet. Since this method is an asynchronous
                 * method, user is not able to get the base-64 string immediately. User has to get the
                 * base-64 string through this callback. This has a single parameter, the base64 string
                 * of the saved flexsheet. It is passed to user.
                 * @param onError This callback catches error information when saving.
                 * This has a single parameter, the failure reason. The return value is passed to user
                 * if he wants to catch the save failure reason.
                 *
                 * For example:
                 * <pre>
                 * flexsheet.saveAsync('', function (base64) {
                 *      // user can access the base64 string in this callback.
                 *      document.getElementByID('export').href = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' + 'base64,' + base64;
                 * }, function (reason) {
                 *      // User can catch the failure reason in this callback.
                 *      console.log('The reason of save failure is ' + reason);
                 * });
                 * </pre>
                 
                 * @return A workbook instance containing the generated xlsx file content.
                 */
                FlexSheet.prototype.saveAsync = function (fileName, onSaved, onError) {
                    var workbook = this._saveToWorkbook();
                    workbook.saveAsync(fileName, onSaved, onError);
                    return workbook;
                };
                /*
                 * Save the <b>FlexSheet</b> to Workbook Object Model represented by the @see:IWorkbook interface.
                 *
                 * @return The @see:IWorkbook instance that represents the export results.
                 */
                FlexSheet.prototype.saveToWorkbookOM = function () {
                    var workbook = this._saveToWorkbook();
                    return workbook._serialize();
                };
                /**
                 * Loads the workbook into <b>FlexSheet</b>.
                 * This method works with JSZip 2.5.
                 *
                 * For example:
                 * <pre>// This sample opens an xlsx file chosen through Open File
                 * // dialog and fills FlexSheet
                 * &nbsp;
                 * // HTML
                 * &lt;input type="file"
                 *     id="importFile"
                 *     accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                 * /&gt;
                 * &lt;div id="flexHost"&gt;&lt;/&gt;
                 * &nbsp;
                 * // JavaScript
                 * var flexSheet = new wijmo.grid.FlexSheet("#flexHost"),
                 *     importFile = document.getElementById('importFile');
                 * &nbsp;
                 * importFile.addEventListener('change', function () {
                 *     loadWorkbook();
                 * });
                 * &nbsp;
                 * function loadWorkbook() {
                 *     var reader,
                 *         file = importFile.files[0];
                 *     if (file) {
                 *         reader = new FileReader();
                 *         reader.onload = function (e) {
                 *             flexSheet.load(reader.result);
                 *         };
                 *         reader.readAsArrayBuffer(file);
                 *     }
                 * }</pre>
                 *
                 * @param workbook A workbook instance or a Blob instance or a base-64 string
                 * or an ArrayBuffer containing xlsx file content.
                 */
                FlexSheet.prototype.load = function (workbook) {
                    var workbookInstance, reader, self = this;
                    if (workbook instanceof Blob) {
                        reader = new FileReader();
                        reader.onload = function () {
                            var fileContent = reader.result;
                            fileContent = wijmo.xlsx.Workbook._base64EncArr(new Uint8Array(fileContent));
                            workbookInstance = new wijmo.xlsx.Workbook();
                            workbookInstance.load(fileContent);
                            self._loadFromWorkbook(workbookInstance);
                        };
                        reader.readAsArrayBuffer(workbook);
                    }
                    else if (workbook instanceof wijmo.xlsx.Workbook) {
                        self._loadFromWorkbook(workbook);
                    }
                    else {
                        if (workbook instanceof ArrayBuffer) {
                            workbook = wijmo.xlsx.Workbook._base64EncArr(new Uint8Array(workbook));
                        }
                        else if (!wijmo.isString(workbook)) {
                            throw 'Invalid workbook.';
                        }
                        workbookInstance = new wijmo.xlsx.Workbook();
                        workbookInstance.load(workbook);
                        self._loadFromWorkbook(workbookInstance);
                    }
                };
                /**
                 * Loads the workbook into <b>FlexSheet</b> asynchronously.
                 * This method works with JSZip 3.0.
                 *
                 * @param workbook A workbook instance or a Blob instance or a base-64
                 * string or an ArrayBuffer containing xlsx file content.
                 * @param onLoaded This callback provides an approach to get the loaded workbook instance.
                 * Since this method is an asynchronous method, user is not able to get the loaded workbook
                 * instance immediately. User has to get the loaded workbook instance through this callback.
                 * This has a single parameter, the loaded workbook instance. It is passed to user.
                 * @param onError This callback catches error information when loading.
                 * This has a single parameter, the failure reason. The return value is passed to user
                 * if he wants to catch the load failure reason.
                 *
                 * For example:
                 * <pre>
                 * flexsheet.loadAsync(blob, function (workbook) {
                 *      // user can access the loaded workbook instance in this callback.
                 *      var app = worksheet.application ;
                 *      ...
                 * }, function (reason) {
                 *      // User can catch the failure reason in this callback.
                 *      console.log('The reason of load failure is ' + reason);
                 * });
                 * </pre>
                 */
                FlexSheet.prototype.loadAsync = function (workbook, onLoaded, onError) {
                    var workbookInstance, reader, self = this;
                    if (workbook instanceof Blob) {
                        reader = new FileReader();
                        reader.onload = function () {
                            var fileContent = reader.result;
                            fileContent = wijmo.xlsx.Workbook._base64EncArr(new Uint8Array(fileContent));
                            workbookInstance = new wijmo.xlsx.Workbook();
                            workbookInstance.loadAsync(fileContent, function (loadedWork) {
                                self._loadFromWorkbook(loadedWork);
                                if (onLoaded) {
                                    onLoaded(loadedWork);
                                }
                            }, onError);
                        };
                        reader.readAsArrayBuffer(workbook);
                    }
                    else if (workbook instanceof wijmo.xlsx.Workbook) {
                        self._loadFromWorkbook(workbook);
                        if (onLoaded) {
                            onLoaded(workbook);
                        }
                    }
                    else {
                        if (workbook instanceof ArrayBuffer) {
                            workbook = wijmo.xlsx.Workbook._base64EncArr(new Uint8Array(workbook));
                        }
                        else if (!wijmo.isString(workbook)) {
                            throw 'Invalid workbook.';
                        }
                        workbookInstance = new wijmo.xlsx.Workbook();
                        workbookInstance.loadAsync(workbook, function (loadedWork) {
                            self._loadFromWorkbook(loadedWork);
                            if (onLoaded) {
                                onLoaded(loadedWork);
                            }
                        }, onError);
                    }
                };
                /*
                 * Load the Workbook Object Model instance into the <b>FlexSheet</b>.
                 *
                 * @param workbook The Workbook Object Model instance to load data from.
                 */
                FlexSheet.prototype.loadFromWorkbookOM = function (workbook) {
                    var grids = [], workbookInstance;
                    if (workbook instanceof wijmo.xlsx.Workbook) {
                        workbookInstance = workbook;
                    }
                    else {
                        workbookInstance = new wijmo.xlsx.Workbook();
                        workbookInstance._deserialize(workbook);
                    }
                    this._loadFromWorkbook(workbookInstance);
                };
                /**
                 * Undo the last user action.
                 */
                FlexSheet.prototype.undo = function () {
                    var self = this;
                    // The undo should wait until other operations have done. (TFS 189582) 
                    setTimeout(function () {
                        self._undoStack.undo();
                    }, 100);
                };
                /**
                 * Redo the last user action.
                 */
                FlexSheet.prototype.redo = function () {
                    var self = this;
                    // The redo should wait until other operations have done. (TFS 189582) 
                    setTimeout(function () {
                        self._undoStack.redo();
                    }, 100);
                };
                /**
                 * Selects a cell range and optionally scrolls it into view.
                 *
                 * @see:FlexSheet overrides this method to adjust the selection cell range for the merged cells in the @see:FlexSheet.
                 *
                 * @param rng The cell range to select.
                 * @param show Indicates whether to scroll the new selection into view.
                 */
                FlexSheet.prototype.select = function (rng, show) {
                    if (show === void 0) { show = true; }
                    var mergedRange, rowIndex, colIndex;
                    if (wijmo.isNumber(rng) && wijmo.isNumber(show)) {
                        rng = new grid_1.CellRange(rng, show);
                        show = true;
                    }
                    if (rng.rowSpan !== this.rows.length && rng.columnSpan !== this.columns.length) {
                        for (rowIndex = rng.topRow; rowIndex <= rng.bottomRow; rowIndex++) {
                            for (colIndex = rng.leftCol; colIndex <= rng.rightCol; colIndex++) {
                                mergedRange = this.getMergedRange(this.cells, rowIndex, colIndex);
                                if (mergedRange && !rng.equals(mergedRange)) {
                                    if (rng.row <= rng.row2) {
                                        rng.row = Math.min(rng.topRow, mergedRange.topRow);
                                        rng.row2 = Math.max(rng.bottomRow, mergedRange.bottomRow);
                                    }
                                    else {
                                        rng.row = Math.max(rng.bottomRow, mergedRange.bottomRow);
                                        rng.row2 = Math.min(rng.topRow, mergedRange.topRow);
                                    }
                                    if (rng.col <= rng.col2) {
                                        rng.col = Math.min(rng.leftCol, mergedRange.leftCol);
                                        rng.col2 = Math.max(rng.rightCol, mergedRange.rightCol);
                                    }
                                    else {
                                        rng.col = Math.max(rng.rightCol, mergedRange.rightCol);
                                        rng.col2 = Math.min(rng.leftCol, mergedRange.leftCol);
                                    }
                                }
                            }
                        }
                    }
                    if (this.collectionView) {
                        // When select all cells in the bound sheet, we should ignore the header row of the bound sheet.
                        // This updating is for TFS issue #128358
                        if (rng.topRow === 0 && rng.bottomRow === this.rows.length - 1
                            && rng.leftCol === 0 && rng.rightCol === this.columns.length - 1) {
                            rng.row = 1;
                            rng.row2 = this.rows.length - 1;
                        }
                    }
                    _super.prototype.select.call(this, rng, show);
                };
                /*
                 * Add custom function in @see:FlexSheet.
                 * @param name the name of the custom function.
                 * @param func the custom function.
                 * @param description the description of the custom function, it will be shown in the function autocompletion of the @see:FlexSheet.
                 * @param minParamsCount the minimum count of the parameter that the function need.
                 * @param maxParamsCount the maximum count of the parameter that the function need.
                 *        If the count of the parameters in the custom function is arbitrary, the minParamsCount and maxParamsCount should be set to null.
                 */
                FlexSheet.prototype.addCustomFunction = function (name, func, description, minParamsCount, maxParamsCount) {
                    wijmo._deprecated('addCustomFunction', 'addFunction');
                    this._calcEngine.addCustomFunction(name, func, minParamsCount, maxParamsCount);
                    this._addCustomFunctionDescription(name, description);
                };
                /**
                 * Add custom function in @see:FlexSheet.
                 * @param name the name of the custom function.
                 * @param func the custom function.
                 * <br/>
                 * The function signature looks as follows:
                 * <br/>
                 * <pre>function (...params: any[][][]): any;</pre>
                 * The function takes a variable number of parameters, each parameter corresponds to an expression
                 * passed as a function argument. Independently of whether the expression passed as a function argument
                 * resolves to a single value or to a cell range, each parameter value is always a two dimensional array
                 * of resolved values. The number of rows (first index) and columns (second index) in the array corresponds
                 * to the size of the specified cell range. In case where argument is an expression that resolves
                 * to a single value, it will be a one-to-one array where its value can be retrieved using the
                 * param[0][0] indexer.
                 * <br/>
                 * The sample below adds a custom Sum Product function ('customSumProduct') to the FlexSheet:
                 * <pre>flexSheet.addFunction('customSumProduct', (...params: any[][][]) =&gt; {
                 *    let result = 0,
                 *        range1 = params[0],
                 *        range2 = params[1];
                 *
                 *    if (range1.length &gt; 0 && range1.length === range2.length && range1[0].length === range2[0].length) {
                 *        for (let i = 0; i &lt; range1.length; i++) {
                 *            for (let j = 0; j &lt; range1[0].length; j++) {
                 *                result += range1[i][j] * range2[i][j];
                 *            }
                 *        }
                 *    }
                 *    return result;
                 * }, 'Custom SumProduct Function', 2, 2);</pre>
                 * After adding this function, it can be used it in sheet cell expressions, like here:
                 * <pre>=customSumProduct(A1:B5, B1:C5)</pre>
                 * @param description the description of the custom function, it will be shown in the function autocompletion of the @see:FlexSheet.
                 * @param minParamsCount the minimum count of the parameter that the function need.
                 * @param maxParamsCount the maximum count of the parameter that the function need.
                 *        If the count of the parameters in the custom function is arbitrary, the minParamsCount and maxParamsCount should be set to null.
                 */
                FlexSheet.prototype.addFunction = function (name, func, description, minParamsCount, maxParamsCount) {
                    this._calcEngine.addFunction(name, func, minParamsCount, maxParamsCount);
                    this._addCustomFunctionDescription(name, description);
                };
                /**
                 * Disposes of the control by removing its association with the host element.
                 */
                FlexSheet.prototype.dispose = function () {
                    var userAgent = window.navigator.userAgent;
                    this._needCopyToSheet = false;
                    document.removeEventListener('mousemove', this._mouseMoveHdl);
                    document.body.removeEventListener('click', this._clickHdl);
                    if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i)) {
                        document.body.removeEventListener('touchstart', this._touchStartHdl);
                        document.body.removeEventListener('touchend', this._touchEndHdl);
                    }
                    this.hideFunctionList();
                    _super.prototype.dispose.call(this);
                };
                /**
                 * Gets the content of a @see:CellRange as a string suitable for
                 * copying to the clipboard.
                 *
                 * @see:FlexSheet overrides this method to support multiple rows or columns selection in @see:FlexSheet.
                 *
                 * Hidden rows and columns are not included in the clip string.
                 *
                 * @param rng @see:CellRange to copy. If omitted, the current selection is used.
                 */
                FlexSheet.prototype.getClipString = function (rng) {
                    var clipString = '', selections, rowIndex, selIndex, firstRow = true, firstCell, sel, cell;
                    this._isCutting = false;
                    if (!rng) {
                        if (this._isMultipleRowsSelected()) {
                            clipString = '';
                            selections = this.selectedSheet.selectionRanges.slice(0);
                            if (selections.length === 0) {
                                selections = [this.selection];
                            }
                            selections.sort(this._sortByRow);
                            for (selIndex = 0; selIndex < selections.length; selIndex++) {
                                if (clipString) {
                                    clipString += '\n';
                                }
                                clipString += this.getClipString(selections[selIndex]);
                            }
                            return clipString;
                        }
                        else if (this._isMultipleColumnsSelected()) {
                            clipString = '';
                            selections = this.selectedSheet.selectionRanges.slice(0);
                            if (selections.length === 0) {
                                selections = [this.selection];
                            }
                            selections.sort(this._sortByColumn);
                            for (rowIndex = 0, firstRow = true; rowIndex < this.rows.length; rowIndex++) {
                                if (!firstRow) {
                                    clipString += '\n';
                                }
                                firstRow = false;
                                for (selIndex = 0, firstCell = true; selIndex < selections.length; selIndex++) {
                                    if (!firstCell) {
                                        clipString += '\t';
                                    }
                                    firstCell = false;
                                    clipString += this.getClipString(selections[selIndex]);
                                }
                                return clipString;
                            }
                        }
                        else {
                            rng = this.selection;
                            switch (this.selectionMode) {
                                // row modes: expand range to cover all columns
                                case grid_1.SelectionMode.Row:
                                case grid_1.SelectionMode.RowRange:
                                    rng.col = 0;
                                    rng.col2 = this.columns.length - 1;
                                    break;
                                // ListBox mode: scan rows and copy selected ones
                                case grid_1.SelectionMode.ListBox:
                                    rng.col = 0;
                                    rng.col2 = this.columns.length - 1;
                                    for (var i = 0; i < this.rows.length; i++) {
                                        if (this.rows[i].isSelected && this.rows[i].isVisible) {
                                            rng.row = rng.row2 = i;
                                            if (clipString)
                                                clipString += '\n';
                                            clipString += this.getClipString(rng);
                                        }
                                    }
                                    return clipString;
                            }
                        }
                    }
                    // scan rows
                    rng = wijmo.asType(rng, grid_1.CellRange);
                    if (!rng.isValid) {
                        return '';
                    }
                    for (var r = rng.topRow; r <= rng.bottomRow; r++) {
                        // skip invisible, add separator
                        if (!this.rows[r].isVisible)
                            continue;
                        if (!firstRow)
                            clipString += '\n';
                        firstRow = false;
                        // scan cells
                        for (var c = rng.leftCol, firstCell = true; c <= rng.rightCol; c++) {
                            // skip invisible, add separator
                            if (!this.columns[c].isVisible)
                                continue;
                            if (!firstCell)
                                clipString += '\t';
                            firstCell = false;
                            // append cell
                            cell = this.getCellValue(r, c, true).toString();
                            cell = cell.replace(/\t/g, ' '); // handle tabs
                            if (cell.indexOf('\n') > -1) {
                                cell = '"' + cell.replace(/"/g, '""') + '"';
                            }
                            clipString += cell;
                        }
                    }
                    return clipString;
                };
                /**
                 * Parses a string into rows and columns and applies the content to a given range.
                 *
                 * Override the <b>setClipString</b> method of @see:FlexGrid.
                 *
                 * @param text Tab and newline delimited text to parse into the grid.
                 * @param rng @see:CellRange to copy. If omitted, the current selection is used.
                 */
                FlexSheet.prototype.setClipString = function (text, rng) {
                    var autoRange = rng == null, pasted = false, rngPaste, row, col, copiedRow, copiedCol, rows, cells, cellData, matches, i, j, cellRefIndex, cellRef, index, cellAddress, updatedCellRef, rowDiff, colDiff, copiedRange, isMultiLine = false, copiedRowIndex, copiedColIndex, rowSpan, colSpan, orgText, copiedText;
                    rng = rng ? wijmo.asType(rng, grid_1.CellRange) : this.selection;
                    // normalize text
                    text = wijmo.asString(text).replace(/\r\n/g, '\n').replace(/\r/g, '\n');
                    if (text && text[text.length - 1] == '\n') {
                        text = text.substring(0, text.length - 1);
                    }
                    orgText = text;
                    rows = this._edtHdl._parseClipString(wijmo.asString(text));
                    if (autoRange && !rng.isSingleCell && rows.length) {
                        this._edtHdl._expandClipRows(rows, rng);
                    }
                    isMultiLine = this._containsMultiLineText(rows);
                    if ((!this._copiedRanges || this._copiedRanges.length === 0 || (orgText.trim() !== this._getRangeString(this._copiedRanges, this._copiedSheet).trim() && !this._containsRandFormula(this._copiedRanges, this._copiedSheet)) || !!this._cutValue) && !isMultiLine) {
                        if (orgText !== this._cutValue) {
                            this._cutValue = null;
                            _super.prototype.setClipString.call(this, text);
                        }
                        this._copiedRanges = null;
                        this._copiedSheet = null;
                        return;
                    }
                    // keep track of paste range to select later
                    rngPaste = new grid_1.CellRange(rng.topRow, rng.leftCol);
                    // copy lines to rows
                    this.beginUpdate();
                    if (isMultiLine || !this._copiedRanges || this._copiedRanges.length > 1 || this._copiedRanges.length === 0) {
                        row = rng.topRow;
                        copiedRange = this._copiedRanges && this._copiedRanges.length > 1 ? this._copiedRanges[0] : new grid_1.CellRange();
                        copiedRow = copiedRange.topRow;
                        for (i = 0; i < rows.length && row < this.rows.length; i++, row++) {
                            // skip invisible row, keep clip line
                            if (!this.rows[row].isVisible) {
                                i--;
                                continue;
                            }
                            // copy cells to columns
                            cells = rows[i];
                            copiedCol = copiedRange.leftCol;
                            col = rng.leftCol;
                            colDiff = col - copiedCol;
                            for (j = 0; j < cells.length && col < this.columns.length; j++, col++) {
                                // skip invisible column, keep clip cell
                                if (!this.columns[col].isVisible) {
                                    j--;
                                    continue;
                                }
                                // assign cell
                                cellData = cells[j];
                                if (!this.columns[col].isReadOnly && !this.rows[row].isReadOnly) {
                                    pasted = this._postSetClipStringProcess(cellData, row, col, copiedRow, copiedCol);
                                    // update paste range
                                    rngPaste.row2 = Math.max(rngPaste.row2, row);
                                    rngPaste.col2 = Math.max(rngPaste.col2, col);
                                }
                                if (copiedCol >= 0) {
                                    copiedCol++;
                                }
                            }
                            if (copiedRow >= 0) {
                                copiedRow++;
                            }
                        }
                    }
                    else if (this._copiedRanges && this._copiedRanges.length === 1) {
                        copiedRowIndex = 0;
                        copiedRange = this._copiedRanges[0];
                        copiedText = this._getRangeString(this._copiedRanges, this._copiedSheet, false);
                        rows = this._edtHdl._parseClipString(copiedText);
                        if (autoRange && !rng.isSingleCell && rows.length) {
                            this._edtHdl._expandClipRows(rows, rng);
                        }
                        rowSpan = copiedRange.rowSpan > rng.rowSpan ? copiedRange.rowSpan : rng.rowSpan;
                        colSpan = copiedRange.columnSpan > rng.columnSpan ? copiedRange.columnSpan : rng.columnSpan;
                        row = rng.topRow;
                        for (i = 0; i < rows.length && row < this.rows.length; i++, row++) {
                            copiedColIndex = 0;
                            // skip invisible row
                            if (!this.rows[row].isVisible) {
                                i--;
                                continue;
                            }
                            while (this._copiedSheet.grid.rows[copiedRange.topRow + copiedRowIndex] && !this._copiedSheet.grid.rows[copiedRange.topRow + copiedRowIndex].isVisible) {
                                copiedRowIndex++;
                            }
                            if (copiedRowIndex >= copiedRange.rowSpan) {
                                if (rowSpan % copiedRange.rowSpan === 0 && colSpan % copiedRange.columnSpan === 0) {
                                    copiedRowIndex = copiedRowIndex % copiedRange.rowSpan;
                                }
                                else {
                                    break;
                                }
                            }
                            if (!this._copiedSheet.grid.rows[copiedRange.topRow + copiedRowIndex]) {
                                break;
                            }
                            rowDiff = row - copiedRange.topRow - copiedRowIndex;
                            cells = rows[i];
                            col = rng.leftCol;
                            for (j = 0; j < cells.length && col < this.columns.length; j++, col++) {
                                // skip invisible column
                                if (!this.columns[col] || !this.columns[col].isVisible) {
                                    j--;
                                    continue;
                                }
                                if (copiedColIndex >= copiedRange.columnSpan) {
                                    if (rowSpan % copiedRange.rowSpan === 0 && colSpan % copiedRange.columnSpan === 0) {
                                        copiedColIndex = copiedColIndex % copiedRange.columnSpan;
                                    }
                                    else {
                                        break;
                                    }
                                }
                                colDiff = col - copiedRange.leftCol - copiedColIndex;
                                if (!this.columns[col].isReadOnly && !this.rows[row].isReadOnly) {
                                    cellData = cells[j];
                                    if (!!cellData && typeof cellData === 'string' && cellData[0] === '=' && (rowDiff !== 0 || colDiff !== 0)) {
                                        matches = cellData.match(/((\w+)\!)?\$?[A-Za-z]{1,2}\$?\d+/g);
                                        if (!!matches && matches.length > 0) {
                                            cellRefLoop: for (cellRefIndex = 0; cellRefIndex < matches.length; cellRefIndex++) {
                                                cellRef = matches[cellRefIndex];
                                                index = cellData.indexOf(cellRef);
                                                if (index > 0 && (cellData[index - 1] === '\"' || /[\d\w]/.test(cellData[index - 1]))) {
                                                    continue cellRefLoop;
                                                }
                                                cellAddress = wijmo.xlsx.Workbook.tableAddress(cellRef);
                                                cellAddress.row += cellAddress.absRow ? 0 : rowDiff;
                                                cellAddress.col += cellAddress.absCol ? 0 : colDiff;
                                                updatedCellRef = wijmo.xlsx.Workbook.xlsxAddress(cellAddress.row, cellAddress.col, cellAddress.absRow, cellAddress.absCol);
                                                cellData = cellData.replace(cellRef, updatedCellRef);
                                            }
                                        }
                                    }
                                    pasted = this._postSetClipStringProcess(cellData, row, col, copiedRange.topRow + copiedRowIndex, copiedRange.leftCol + copiedColIndex);
                                    // update paste range
                                    rngPaste.row2 = Math.max(rngPaste.row2, row);
                                    rngPaste.col2 = Math.max(rngPaste.col2, col);
                                }
                                copiedColIndex++;
                            }
                            copiedRowIndex++;
                        }
                    }
                    if (this._isCutting) {
                        this._delCutData();
                        this._isCutting = false;
                        this._cutValue = orgText;
                        this._copiedRanges = null;
                        this._copiedSheet = null;
                    }
                    this.endUpdate();
                    // done, refresh view to update sorting/filtering 
                    if (this.collectionView && pasted) {
                        this.collectionView.refresh();
                    }
                    // select pasted range
                    this.select(rngPaste);
                };
                /*
                 * Get the built-in table style via its name.
                 *
                 * @param styleName The name of the built-in table style.
                 */
                FlexSheet.prototype.getBuiltInTableStyle = function (styleName) {
                    var styleIndex, tableStyle;
                    tableStyle = this._builtInTableStylesCache[styleName.toLowerCase()];
                    if (tableStyle == null) {
                        tableStyle = this._createBuiltInTableStyle(styleName);
                        Object.freeze(tableStyle);
                        this._builtInTableStylesCache[styleName.toLowerCase()] = tableStyle;
                    }
                    return tableStyle;
                };
                /*
                 * Add empty table to FlexSheet.
                 *
                 * @param rowIndex The top row position of the table.
                 * @param colIndex The left column position of the table.
                 * @param rowSpan The number of the rows in the table.
                 * @param colSpan The number of the columns in the table.
                 * @param tableName The name of the table.
                 * @param tableStyle The table style is applied to the table.
                 * @param options The options of the table.
                 * @param sheet Indicates the table will be added in which sheet.  If the sheet is omitted, it will be added in current sheet.
                 */
                FlexSheet.prototype.addTable = function (rowIndex, colIndex, rowSpan, colSpan, tableName, tableStyle, options, sheet) {
                    var table, range = new grid_1.CellRange(rowIndex, colIndex, rowIndex + rowSpan - 1, colIndex + colSpan - 1), flex = sheet == null ? this : sheet.grid;
                    if (!range.isValid || range.bottomRow >= flex.rows.length || range.rightCol >= flex.columns.length) {
                        throw 'The range of the table is invalid.';
                    }
                    return this._addTable(range, tableName, tableStyle, null, options, sheet);
                };
                /*
                 * Add the table from the data source in FlexSheet.
                 *
                 * @param rowIndex The top row position of the table.
                 * @param colIndex The left column position of the table.
                 * @param dataSource The dataSource load to the table.
                 * @param tableName The name of the table.
                 * @param tableStyle The table style is applied to the table.
                 * @param options The options of the table.
                 * @param sheet Indicates the table will be added in which sheet.  If the sheet is omitted, it will be added in current sheet.
                 */
                FlexSheet.prototype.addTableFromDataSource = function (rowIndex, colIndex, dataSource, tableName, tableStyle, options, sheet) {
                    var table, keys, columns, column, r, c, key, tableRange, flex = sheet == null ? this : sheet.grid;
                    if (dataSource == null || dataSource.length === 0) {
                        throw 'Invalid dataSource.';
                    }
                    keys = Object.keys(dataSource[0]);
                    if (keys == null || keys.length === 0) {
                        throw 'Invalid dataSource.';
                    }
                    var showHeader = (options && options.showHeaderRow) == null || options.showHeaderRow, // default is true
                    showTotal = !!(options && options.showTotalRow), dataRowFirst = rowIndex + (showHeader ? 1 : 0), dataRowLast = dataRowFirst + dataSource.length - 1, tableRowLast = dataRowLast + (showTotal ? 1 : 0);
                    if (colIndex + keys.length > flex.columns.length || tableRowLast >= flex.rows.length) {
                        throw 'The range of the table is out of the range of the sheet.';
                    }
                    flex.beginUpdate();
                    for (r = 0; r < dataSource.length; r++) {
                        for (c = 0; c < keys.length; c++) {
                            key = keys[c];
                            flex.setCellData(dataRowFirst + r, colIndex + c, dataSource[r][key]);
                        }
                    }
                    columns = [];
                    for (c = 0; c < keys.length; c++) {
                        key = keys[c];
                        if (showHeader) {
                            flex.setCellData(rowIndex, colIndex + c, key);
                        }
                        column = new sheet_1.TableColumn(key);
                        if (c === 0) {
                            column.totalRowLabel = 'Total';
                        }
                        else if (c === keys.length - 1) {
                            column.totalRowFunction = 'Sum';
                        }
                        columns.push(column);
                    }
                    flex.endUpdate();
                    tableRange = new grid_1.CellRange(rowIndex, colIndex, tableRowLast, colIndex + keys.length - 1);
                    return this._addTable(tableRange, tableName, tableStyle, columns, options, sheet);
                };
                // Override the getCvIndex method of its parent class FlexGrid
                FlexSheet.prototype._getCvIndex = function (index) {
                    var row;
                    if (index > -1 && this.collectionView) {
                        row = this.rows[index];
                        if (row instanceof HeaderRow) {
                            return index;
                        }
                        else {
                            return _super.prototype._getCvIndex.call(this, index);
                        }
                    }
                    return -1;
                };
                // Initialize the FlexSheet control
                FlexSheet.prototype._init = function () {
                    var _this = this;
                    var self = this, userAgent = window.navigator.userAgent, mouseUp = function (e) {
                        document.removeEventListener('mouseup', mouseUp);
                        self._mouseUp(e);
                    };
                    self.hostElement.setAttribute('tabindex', '-1');
                    self._divContainer = self.hostElement.querySelector('[wj-part="container"]');
                    self._tabHolder = new sheet_1._TabHolder(self.hostElement.querySelector('[wj-part="tab-holder"]'), self);
                    self._contextMenu = new sheet_1._ContextMenu(self.hostElement.querySelector('[wj-part="context-menu"]'), self);
                    self['_gpCells'] = new FlexSheetPanel(self, grid_1.CellType.Cell, self.rows, self.columns, self['_eCt']);
                    self['_gpCHdr'] = new FlexSheetPanel(self, grid_1.CellType.ColumnHeader, self['_hdrRows'], self.columns, self['_eCHdrCt']);
                    self['_gpRHdr'] = new FlexSheetPanel(self, grid_1.CellType.RowHeader, self.rows, self['_hdrCols'], self['_eRHdrCt']);
                    self['_gpTL'] = new FlexSheetPanel(self, grid_1.CellType.TopLeft, self['_hdrRows'], self['_hdrCols'], self['_eTLCt']);
                    self._sortManager = new sheet_1.SortManager(self);
                    self._filter = new sheet_1._FlexSheetFilter(self);
                    self._filter.filterApplied.addHandler(function () {
                        if (self.selectedSheet) {
                            self.selectedSheet._filterDefinition = self._filter.filterDefinition;
                            if (self.selectedSheet.itemsSource) {
                                self.selectedSheet._storeRowSettings();
                                self.selectedSheet._setRowSettings();
                            }
                        }
                    });
                    self._calcEngine = new sheet_1._CalcEngine(self);
                    self._calcEngine.unknownFunction.addHandler(function (sender, e) {
                        self.onUnknownFunction(e);
                    }, self);
                    self._initFuncsList();
                    self._undoStack = new sheet_1.UndoStack(self);
                    // Add header row for the bind sheet.
                    self.loadedRows.addHandler(function () {
                        if (self.itemsSource && !(self.rows[0] instanceof HeaderRow)) {
                            var row = new HeaderRow(), col;
                            for (var i = 0; i < self.columns.length; i++) {
                                col = self.columns[i];
                                if (!row._ubv) {
                                    row._ubv = {};
                                }
                                row._ubv[col._hash] = col.header;
                            }
                            if (self.rows[0] instanceof grid_1._NewRowTemplate) {
                                self.rows.insert(1, row);
                            }
                            else {
                                self.rows.insert(0, row);
                            }
                        }
                        if (self._filter) {
                            self._filter.apply();
                        }
                    });
                    // Setting the required property of the column to false for the bound sheet.
                    // TFS #126125
                    self.itemsSourceChanged.addHandler(function () {
                        var colIndex;
                        for (colIndex = 0; colIndex < self.columns.length; colIndex++) {
                            self.columns[colIndex].isRequired = false;
                        }
                    });
                    // Store the copied range for updating cell reference of the formula when copying. (TFS 190785)
                    self.copied.addHandler(function (sender, args) {
                        var selections;
                        self._copiedSheet = self.selectedSheet;
                        self._needCopyToSheet = true;
                        if (self._isMultipleRowsSelected()) {
                            selections = self.selectedSheet.selectionRanges.slice(0);
                            selections.sort(self._sortByRow);
                            self._copiedRanges = selections;
                        }
                        else if (self._isMultipleColumnsSelected()) {
                            selections = self.selectedSheet.selectionRanges.slice(0);
                            selections.sort(self._sortByColumn);
                            self._copiedRanges = selections;
                        }
                        else {
                            self._copiedRanges = [args.range];
                        }
                    });
                    // If the rows\columns of FlexSheet were cleared, we should reset merged cells, styled cells and selection of current sheet to null. (TFS 140344)
                    self.rows.collectionChanged.addHandler(function (sender, e) {
                        self._clearForEmptySheet('rows');
                        if (!self.itemsSource && self.selectedSheet && self._needCopyToSheet && !self._isCopying && !self._isUndoing && !(e.item instanceof grid_1._NewRowTemplate)) {
                            // Synch the change of rows with current sheet.
                            self._copyRowsToSelectedSheet();
                        }
                    }, self);
                    self.columns.collectionChanged.addHandler(function (sender, e) {
                        self._clearForEmptySheet('columns');
                        if (self.selectedSheet && self._needCopyToSheet && !self._isCopying && !self._isUndoing) {
                            // Synch the change of columns with current sheet.
                            self._copyColumnsToSelectedSheet();
                        }
                    }, self);
                    // Validate the inserted and updated defined name item.
                    self.definedNames.collectionChanged.addHandler(function (sender, e) {
                        if (e.action === wijmo.collections.NotifyCollectionChangedAction.Add || e.action === wijmo.collections.NotifyCollectionChangedAction.Change) {
                            var action = e.action === wijmo.collections.NotifyCollectionChangedAction.Add ? 'inserted' : 'updated';
                            if (!(e.item instanceof DefinedName)) {
                                self.definedNames.remove(e.item);
                                throw 'Invalid defined name item object was ' + action + '.  The DefinedName instance should be ' + action + ' in the definedNames array.';
                            }
                            if (!(e.item && e.item.name && e.item.value != null)) {
                                self.definedNames.remove(e.item);
                                throw 'Invalid defined name was ' + action + '.';
                            }
                            if (e.item.sheetName != null && !self._validateSheetName(e.item.sheetName)) {
                                self.definedNames.remove(e.item);
                                throw 'The sheet name (' + e.item.sheetName + ') does not exist in FlexSheet.';
                            }
                            if (self._checkExistDefinedName(e.item.name, e.item.sheetName, e.index)) {
                                self.definedNames.remove(e.item);
                                throw 'The ' + e.item.name + ' already existed in definedNames.';
                            }
                        }
                    });
                    self.addEventListener(self.hostElement, 'mousedown', function (e) {
                        document.addEventListener('mouseup', mouseUp);
                        // Only when the target is the child of the root container of the FlexSheet control, 
                        // it will deal with the mouse down event handler of the FlexSheet control. (TFS 152995)
                        if (self._isDescendant(self._divContainer, e.target)) {
                            self._mouseDown(e);
                        }
                    }, true);
                    self.addEventListener(self.hostElement, 'drop', function () {
                        self._columnHeaderClicked = false;
                    });
                    self.addEventListener(self.hostElement, 'contextmenu', function (e) {
                        var ht, selectedRow, selectedCol, colPos, rowPos, point, hostOffset, hostScrollOffset, newSelection;
                        if (e.defaultPrevented) {
                            return;
                        }
                        if (!self.activeEditor) {
                            // Handle the hitTest for the keyboard context menu event in IE
                            // Since it can't get the correct position for the keyboard context menu event in IE (TFS 122943)
                            if (self._isContextMenuKeyDown
                                && self.selection.row > -1 && self.selection.col > -1
                                && self.rows.length > 0 && self.columns.length > 0) {
                                selectedCol = self.columns[self.selection.col];
                                selectedRow = self.rows[self.selection.row];
                                hostOffset = self._cumulativeOffset(self.hostElement);
                                hostScrollOffset = self._cumulativeScrollOffset(self.hostElement);
                                colPos = selectedCol.pos + self['_eCt'].offsetLeft + hostOffset.x + selectedCol.renderSize / 2 + self._ptScrl.x;
                                rowPos = selectedRow.pos + self['_eCt'].offsetTop + hostOffset.y + selectedRow.renderSize / 2 + self._ptScrl.y;
                                point = new wijmo.Point(colPos - hostScrollOffset.x, rowPos - hostScrollOffset.y);
                                ht = self.hitTest(colPos, rowPos);
                                self._isContextMenuKeyDown = false;
                            }
                            else {
                                ht = self.hitTest(e);
                            }
                            e.preventDefault();
                            if (ht && ht.cellType !== grid_1.CellType.None) {
                                newSelection = new grid_1.CellRange(ht.row, ht.col);
                                if (ht.cellType === grid_1.CellType.Cell && !newSelection.intersects(self.selection)) {
                                    if (self.selectedSheet) {
                                        self.selectedSheet.selectionRanges.clear();
                                    }
                                    self.selection = newSelection;
                                    self.selectedSheet.selectionRanges.push(newSelection);
                                }
                                // Disable add\remove rows\columns for bound sheet.
                                if (!_this.itemsSource) {
                                    self._contextMenu.show(e, point);
                                }
                            }
                        }
                    });
                    self.prepareCellForEdit.addHandler(self._prepareCellForEditHandler, self);
                    self.cellEditEnded.addHandler(function (sender, args) {
                        if (args.data && (args.data.keyCode === 46 || args.data.keyCode === 8)) {
                            return;
                        }
                        setTimeout(function () {
                            self.hideFunctionList();
                        }, 200);
                    });
                    self.cellEditEnding.addHandler(function (sender, args) {
                        if (args.data && (args.data.keyCode === 46 || args.data.keyCode === 8)) {
                            return;
                        }
                        self._clearCalcEngine();
                    });
                    self.pasting.addHandler(function () {
                        self._needCopyToSheet = false;
                        self._isPasting = true;
                    });
                    self.pasted.addHandler(function () {
                        var sel = self.selection;
                        self._needCopyToSheet = true;
                        self._isPasting = false;
                        self._clearCalcEngine();
                        if (self.collectionView) {
                            self.deferUpdate(function (_) {
                                var row = self.rows[sel.row];
                                if (row && row.dataItem) {
                                    self.collectionView.moveCurrentTo(row.dataItem);
                                    self.refresh(true);
                                }
                            });
                        }
                    });
                    self.selectionChanged.addHandler(function () {
                        if (!self._enableMulSel && !self._isCopying && self.selectedSheet) {
                            self.selectedSheet.selectionRanges.clear();
                        }
                    });
                    self.resizingColumn.addHandler(function () {
                        self._resizing = true;
                    });
                    self.resizingRow.addHandler(function () {
                        self._resizing = true;
                    });
                    self.resizedColumn.addHandler(function () {
                        self._resizing = false;
                    });
                    self.resizedRow.addHandler(function () {
                        self._resizing = false;
                    });
                    self.addEventListener(self.hostElement, 'keydown', function (e) {
                        var args, text, selectionCnt;
                        if (e.ctrlKey) {
                            if (e.keyCode === 89) {
                                self.finishEditing();
                                self.redo();
                                e.preventDefault();
                            }
                            if (e.keyCode === 90) {
                                self.finishEditing();
                                self.undo();
                                e.preventDefault();
                            }
                            if (!!self.selectedSheet && e.keyCode === 65) {
                                self.selectedSheet.selectionRanges.clear();
                                self.selectedSheet.selectionRanges.push(self.selection);
                            }
                            if (e.keyCode === 67 || e.keyCode == 45) {
                                if (!!self.activeEditor) {
                                    self._copiedRanges = null;
                                    self._copiedSheet = null;
                                }
                                self._cutValue = null;
                            }
                            // Processing for 'Cut' operation. (TFS 191694)
                            if (e.keyCode === 88) {
                                if (!self.activeEditor) {
                                    self.finishEditing();
                                    args = new grid_1.CellRangeEventArgs(self.cells, self.selection);
                                    if (self.onCopying(args)) {
                                        self._cutValue = null;
                                        text = self.getClipString();
                                        self._isCutting = true;
                                        wijmo.Clipboard.copy(text);
                                        self.onCopied(args);
                                    }
                                    e.stopPropagation();
                                }
                            }
                            if (e.keyCode === wijmo.Key.Space && self.selection.isValid && self.selectionMode === grid_1.SelectionMode.CellRange) {
                                self.select(new grid_1.CellRange(_this.itemsSource ? 1 : 0, self.selection.col, self.rows.length - 1, self.selection.col));
                            }
                        }
                        // When press 'Esc' key, we should hide the context menu (TFS 122527)
                        if (e.keyCode === wijmo.Key.Escape) {
                            self._contextMenu.hide();
                        }
                        // Mark the context menu shortcut key pressed.
                        if (e.keyCode === 93 || (e.shiftKey && e.keyCode === 121)) {
                            self._isContextMenuKeyDown = true;
                        }
                        if (!!self.selectedSheet && !self._edtHdl.activeEditor) {
                            switch (e.keyCode) {
                                case wijmo.Key.Left:
                                case wijmo.Key.Right:
                                case wijmo.Key.Up:
                                case wijmo.Key.Down:
                                case wijmo.Key.PageUp:
                                case wijmo.Key.PageDown:
                                case wijmo.Key.Home:
                                case wijmo.Key.End:
                                case wijmo.Key.Tab:
                                case wijmo.Key.Enter:
                                    self.scrollIntoView(self.selection.row, self.selection.col);
                                    selectionCnt = self.selectedSheet.selectionRanges.length;
                                    if (selectionCnt > 0) {
                                        self.selectedSheet.selectionRanges.splice(selectionCnt - 1, 1, self.selection);
                                    }
                                    break;
                            }
                        }
                    });
                    self.addEventListener(document.body, 'keydown', function (e) {
                        if ((self._isDescendant(self.hostElement, e.target) || self.hostElement === e.target) && !self._edtHdl.activeEditor) {
                            // Delete cell content when user presses Delete or Back keys
                            // (Mac keyboards don't have a Delete key, so honor Back here as well)
                            if (e.keyCode === wijmo.Key.Delete || e.keyCode === wijmo.Key.Back) {
                                self._delSeletionContent(e);
                                e.preventDefault();
                            }
                        }
                        // If the context menu of the FlexSheet is visible, we'll handle the 'keydown' event for the context menu. 
                        if (self._contextMenu.visible) {
                            if (e.keyCode === wijmo.Key.Down) {
                                self._contextMenu.moveToNext();
                            }
                            if (e.keyCode === wijmo.Key.Up) {
                                self._contextMenu.moveToPrev();
                            }
                            if (e.keyCode === wijmo.Key.Home) {
                                self._contextMenu.moveToFirst();
                            }
                            if (e.keyCode === wijmo.Key.End) {
                                self._contextMenu.moveToLast();
                            }
                            if (e.keyCode === wijmo.Key.Enter) {
                                self._contextMenu.handleContextMenu();
                            }
                            e.preventDefault();
                        }
                    }, true);
                    document.body.addEventListener('click', self._clickHdl);
                    document.addEventListener('mousemove', self._mouseMoveHdl);
                    // Show/hide the customize context menu for iPad or iPhone 
                    if (userAgent.match(/iPad/i) || userAgent.match(/iPhone/i)) {
                        document.body.addEventListener('touchstart', self._touchStartHdl);
                        document.body.addEventListener('touchend', self._touchEndHdl);
                    }
                    // After dropping in flexsheet, the flexsheet._htDown should be reset to null. (TFS #142369)
                    self.addEventListener(self.hostElement, 'drop', function () {
                        self._htDown = null;
                    });
                };
                // initialize the function autocomplete list
                FlexSheet.prototype._initFuncsList = function () {
                    var self = this;
                    self._functionListHost = document.createElement('div');
                    wijmo.addClass(self._functionListHost, 'wj-flexsheet-formula-list');
                    document.querySelector('body').appendChild(self._functionListHost);
                    self._functionListHost.style.display = 'none';
                    self._functionListHost.style.position = 'absolute';
                    self._functionList = new wijmo.input.ListBox(self._functionListHost);
                    self._functionList.isContentHtml = true;
                    self._functionList.itemsSource = self._getFunctions();
                    self._functionList.displayMemberPath = 'displayValue';
                    self._functionList.selectedValuePath = 'actualvalue';
                    self.addEventListener(self._functionListHost, 'click', self.applyFunctionToCell.bind(self));
                    self.addEventListener(self._functionListHost, 'keydown', function (e) {
                        // When press 'Esc' key in the host element of the function list,
                        // the function list should be hidden and make the host element of the flexsheet get focus. (TFS 142370)
                        if (e.keyCode === wijmo.Key.Escape) {
                            self.hideFunctionList();
                            self.hostElement.focus();
                            e.preventDefault();
                        }
                        // When press 'Enter' key in the host element of the function list,
                        // the selected function of the function should be applied to the selected cell
                        // and make the host element of the flexsheet get focus.
                        if (e.keyCode === wijmo.Key.Enter) {
                            self.applyFunctionToCell();
                            self.hostElement.focus();
                            e.preventDefault();
                            e.stopPropagation();
                        }
                    });
                };
                // Organize the functions data the function list box
                FlexSheet.prototype._getFunctions = function () {
                    var functions = [], i = 0, func;
                    for (; i < FlexSheetFunctions.length; i++) {
                        func = FlexSheetFunctions[i];
                        functions.push({
                            displayValue: '<div class="wj-flexsheet-formula-name">' + func.name + '</div><div class="wj-flexsheet-formula-description">' + func.description + '</div>',
                            actualvalue: func.name
                        });
                    }
                    return functions;
                };
                // Add the description of the custom function in flexsheet.
                FlexSheet.prototype._addCustomFunctionDescription = function (name, description) {
                    var customFuncDesc = {
                        displayValue: '<div class="wj-flexsheet-formula-name">' + name + '</div>' + (description ? '<div class="wj-flexsheet-formula-description">' + description + '</div>' : ''),
                        actualvalue: name
                    }, funcList = this._functionList.itemsSource, funcIndex = -1, i = 0, funcDesc;
                    for (; i < funcList.length; i++) {
                        funcDesc = funcList[i];
                        if (funcDesc.actualvalue === name) {
                            funcIndex = i;
                            break;
                        }
                    }
                    if (funcIndex > -1) {
                        funcList.splice(funcIndex, 1, customFuncDesc);
                    }
                    else {
                        funcList.push(customFuncDesc);
                    }
                };
                // Get current processing formula index.
                FlexSheet.prototype._getCurrentFormulaIndex = function (searchText) {
                    var searchIndex = -1;
                    ['+', '-', '*', '/', '^', '(', '&'].forEach(function (val) {
                        var index = searchText.lastIndexOf(val);
                        if (index > searchIndex) {
                            searchIndex = index;
                        }
                    });
                    return searchIndex;
                };
                // Prepare cell for edit event handler.
                // This event handler will attach keydown, keyup and blur event handler for the edit cell.
                FlexSheet.prototype._prepareCellForEditHandler = function () {
                    var self = this, edt = self._edtHdl._edt;
                    if (!edt) {
                        return;
                    }
                    // bind keydown event handler for the edit cell.
                    self.addEventListener(edt, 'keydown', function (e) {
                        if (self.isFunctionListOpen) {
                            switch (e.keyCode) {
                                case wijmo.Key.Up:
                                    self.selectPreviousFunction();
                                    e.preventDefault();
                                    e.stopPropagation();
                                    break;
                                case wijmo.Key.Down:
                                    self.selectNextFunction();
                                    e.preventDefault();
                                    e.stopPropagation();
                                    break;
                                case wijmo.Key.Tab:
                                case wijmo.Key.Enter:
                                    self.applyFunctionToCell();
                                    e.preventDefault();
                                    e.stopPropagation();
                                    break;
                                case wijmo.Key.Escape:
                                    self.hideFunctionList();
                                    e.preventDefault();
                                    e.stopPropagation();
                                    break;
                            }
                        }
                    });
                    // bind the keyup event handler for the edit cell.
                    self.addEventListener(edt, 'keyup', function (e) {
                        if ((e.keyCode > 40 || e.keyCode < 32) && e.keyCode !== wijmo.Key.Tab && e.keyCode !== wijmo.Key.Escape) {
                            setTimeout(function () {
                                self.showFunctionList(edt);
                            }, 0);
                        }
                    });
                };
                // Add new sheet into the flexsheet.
                FlexSheet.prototype._addSheet = function (sheetName, rows, cols, pos, grid) {
                    var self = this, sheet = new sheet_1.Sheet(self, grid, sheetName, rows, cols);
                    if (!self.sheets.isValidSheetName(sheet)) {
                        sheet._setValidName(self.sheets.getValidSheetName(sheet));
                    }
                    sheet.nameChanged.addHandler(function (sender, e) {
                        self._updateDefinedNameWithSheetRefUpdating(e.oldValue, e.newValue);
                    });
                    if (typeof (pos) === 'number') {
                        if (pos < 0) {
                            pos = 0;
                        }
                        if (pos >= self.sheets.length) {
                            pos = self.sheets.length;
                        }
                    }
                    else {
                        pos = self.sheets.length;
                    }
                    self.sheets.insert(pos, sheet);
                    return sheet;
                };
                // Show specific sheet in the FlexSheet.
                FlexSheet.prototype._showSheet = function (index) {
                    var oldSheet, newSheet;
                    if (!this.sheets || !this.sheets.length || index >= this.sheets.length
                        || index < 0 || index === this.selectedSheetIndex
                        || (this.sheets[index] && !this.sheets[index].visible)) {
                        return;
                    }
                    // finish any pending edits in the old sheet data.
                    this.finishEditing();
                    this._clearCalcEngine();
                    // save the old sheet data
                    if (this.selectedSheetIndex > -1 && this.selectedSheetIndex < this.sheets.length) {
                        this._copyTo(this.sheets[this.selectedSheetIndex]);
                        this._resetFilterDefinition();
                    }
                    // show the new sheet data
                    if (this.sheets[index]) {
                        this._selectedSheetIndex = index;
                        this._copyFrom(this.sheets[index]);
                    }
                    this._filter.closeEditor();
                };
                // Current sheet changed event handler.
                FlexSheet.prototype._selectedSheetChange = function (sender, e) {
                    this._showSheet(e.newValue);
                    this.invalidate(true);
                    this.onSelectedSheetChanged(e);
                };
                // SheetCollection changed event handler.
                FlexSheet.prototype._sourceChange = function (sender, e) {
                    var item;
                    if (e.action === wijmo.collections.NotifyCollectionChangedAction.Add || e.action === wijmo.collections.NotifyCollectionChangedAction.Change) {
                        item = e.item;
                        item._attachOwner(this);
                        if (e.action === wijmo.collections.NotifyCollectionChangedAction.Add) {
                            this._addingSheet = true;
                            if (e.index <= this.selectedSheetIndex) {
                                this._selectedSheetIndex += 1;
                            }
                        }
                        else {
                            if (e.index === this.selectedSheetIndex) {
                                this._copyFrom(e.item, true);
                            }
                        }
                        this.selectedSheetIndex = e.index;
                    }
                    else if (e.action === wijmo.collections.NotifyCollectionChangedAction.Reset) {
                        for (var i = 0; i < this.sheets.length; i++) {
                            item = this.sheets[i];
                            item._attachOwner(this);
                        }
                        if (this.sheets.length > 0) {
                            if (this.selectedSheetIndex === 0) {
                                this._copyFrom(this.selectedSheet, true);
                            }
                            this.selectedSheetIndex = 0;
                        }
                        else {
                            this.rows.clear();
                            this.columns.clear();
                            this._selectedSheetIndex = -1;
                        }
                    }
                    else {
                        if (this.sheets.length > 0) {
                            if (this.selectedSheetIndex >= this.sheets.length) {
                                this.selectedSheetIndex = 0;
                            }
                            else if (this.selectedSheetIndex > e.index) {
                                this._selectedSheetIndex -= 1;
                            }
                        }
                        else {
                            this.rows.clear();
                            this.columns.clear();
                            this._selectedSheetIndex = -1;
                        }
                    }
                    this.invalidate(true);
                };
                // Sheet visible changed event handler.
                FlexSheet.prototype._sheetVisibleChange = function (sender, e) {
                    if (!e.item.visible) {
                        if (e.index === this.selectedSheetIndex) {
                            if (this.selectedSheetIndex === this.sheets.length - 1) {
                                this.selectedSheetIndex = e.index - 1;
                            }
                            else {
                                this.selectedSheetIndex = e.index + 1;
                            }
                        }
                    }
                };
                // apply the styles for the selected cells.
                FlexSheet.prototype._applyStyleForCell = function (rowIndex, colIndex, cellStyle) {
                    var self = this, row = self.rows[rowIndex], currentCellStyle, mergeRange, cellIndex;
                    // Will ignore the cells in the HeaderRow. 
                    if (row == null || row instanceof HeaderRow || !row.isVisible) {
                        return;
                    }
                    cellIndex = rowIndex * self.columns.length + colIndex;
                    // Handle the merged range style.
                    mergeRange = self.selectedSheet._mergedRanges[cellIndex];
                    if (mergeRange) {
                        cellIndex = mergeRange.topRow * self.columns.length + mergeRange.leftCol;
                    }
                    currentCellStyle = self.selectedSheet._styledCells[cellIndex];
                    // Add new cell style for the cell.
                    if (!currentCellStyle) {
                        self.selectedSheet._styledCells[cellIndex] = {
                            className: cellStyle.className,
                            textAlign: cellStyle.textAlign,
                            verticalAlign: cellStyle.verticalAlign,
                            fontStyle: cellStyle.fontStyle,
                            fontWeight: cellStyle.fontWeight,
                            fontFamily: cellStyle.fontFamily,
                            fontSize: cellStyle.fontSize,
                            textDecoration: cellStyle.textDecoration,
                            backgroundColor: cellStyle.backgroundColor,
                            color: cellStyle.color,
                            format: cellStyle.format,
                            whiteSpace: cellStyle.whiteSpace
                        };
                    }
                    else {
                        // Update the cell style.
                        currentCellStyle.className = cellStyle.className === 'normal' ? '' : cellStyle.className || currentCellStyle.className;
                        currentCellStyle.textAlign = cellStyle.textAlign || currentCellStyle.textAlign;
                        currentCellStyle.verticalAlign = cellStyle.verticalAlign || currentCellStyle.verticalAlign;
                        currentCellStyle.fontFamily = cellStyle.fontFamily || currentCellStyle.fontFamily;
                        currentCellStyle.fontSize = cellStyle.fontSize || currentCellStyle.fontSize;
                        currentCellStyle.backgroundColor = cellStyle.backgroundColor || currentCellStyle.backgroundColor;
                        currentCellStyle.color = cellStyle.color || currentCellStyle.color;
                        currentCellStyle.fontStyle = cellStyle.fontStyle === 'none' ? '' : cellStyle.fontStyle || currentCellStyle.fontStyle;
                        currentCellStyle.fontWeight = cellStyle.fontWeight === 'none' ? '' : cellStyle.fontWeight || currentCellStyle.fontWeight;
                        currentCellStyle.textDecoration = cellStyle.textDecoration === 'none' ? '' : cellStyle.textDecoration || currentCellStyle.textDecoration;
                        currentCellStyle.format = cellStyle.format || currentCellStyle.format;
                        currentCellStyle.whiteSpace = cellStyle.whiteSpace || currentCellStyle.whiteSpace;
                    }
                };
                // Check the format states for the cells of the selection.
                FlexSheet.prototype._checkCellFormat = function (rowIndex, colIndex, formatState) {
                    //return;
                    var cellIndex = rowIndex * this.columns.length + colIndex, mergeRange, cellStyle;
                    if (!this.selectedSheet) {
                        return;
                    }
                    mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                    if (mergeRange) {
                        formatState.isMergedCell = true;
                        cellIndex = mergeRange.topRow * this.columns.length + mergeRange.leftCol;
                    }
                    cellStyle = this.selectedSheet._styledCells[cellIndex];
                    // get the format states for the cells of the selection.
                    if (cellStyle) {
                        formatState.isBold = formatState.isBold || cellStyle.fontWeight === 'bold';
                        formatState.isItalic = formatState.isItalic || cellStyle.fontStyle === 'italic';
                        formatState.isUnderline = formatState.isUnderline || cellStyle.textDecoration === 'underline';
                    }
                    // get text align state for the selected cells.
                    if (rowIndex === this.selection.row && colIndex === this.selection.col) {
                        if (cellStyle && cellStyle.textAlign) {
                            formatState.textAlign = cellStyle.textAlign;
                        }
                        else if (colIndex > -1) {
                            formatState.textAlign = this.columns[colIndex].getAlignment() || formatState.textAlign;
                        }
                    }
                };
                // Reset the merged range.
                FlexSheet.prototype._resetMergedRange = function (range) {
                    var rowIndex, colIndex, cellIndex, mergeRowIndex, mergeColIndex, mergeCellIndex, mergedCell, mergedCellExists = false;
                    for (rowIndex = range.topRow; rowIndex <= range.bottomRow; rowIndex++) {
                        for (colIndex = range.leftCol; colIndex <= range.rightCol; colIndex++) {
                            cellIndex = rowIndex * this.columns.length + colIndex;
                            mergedCell = this.selectedSheet._mergedRanges[cellIndex];
                            // Reset the merged state of each cell inside current merged range.
                            if (mergedCell) {
                                mergedCellExists = true;
                                for (mergeRowIndex = mergedCell.topRow; mergeRowIndex <= mergedCell.bottomRow; mergeRowIndex++) {
                                    for (mergeColIndex = mergedCell.leftCol; mergeColIndex <= mergedCell.rightCol; mergeColIndex++) {
                                        mergeCellIndex = mergeRowIndex * this.columns.length + mergeColIndex;
                                        {
                                            delete this.selectedSheet._mergedRanges[mergeCellIndex];
                                        }
                                    }
                                }
                            }
                        }
                    }
                    return mergedCellExists;
                };
                // update the styledCells hash and mergedRange hash for add\delete rows.
                FlexSheet.prototype._updateCellsForUpdatingRow = function (originalRowCount, index, count, isDelete) {
                    var _this = this;
                    //return;
                    var startIndex, cellIndex, newCellIndex, cellStyle, mergeRange, updatedMergeCell = {}, originalCellCount = originalRowCount * this.columns.length;
                    // update for deleting rows.
                    if (isDelete) {
                        startIndex = index * this.columns.length;
                        for (cellIndex = startIndex; cellIndex < originalCellCount; cellIndex++) {
                            newCellIndex = cellIndex - count * this.columns.length;
                            // Update the styledCells hash
                            cellStyle = this.selectedSheet._styledCells[cellIndex];
                            if (cellStyle) {
                                // if the cell is behind the delete cell range, we should update the cell index for the cell to store the style.
                                // if the cell is inside the delete cell range, it need be deleted directly.
                                if (cellIndex >= (index + count) * this.columns.length) {
                                    this.selectedSheet._styledCells[newCellIndex] = cellStyle;
                                }
                                delete this.selectedSheet._styledCells[cellIndex];
                            }
                            // Update the mergedRange hash
                            mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                            if (mergeRange) {
                                if (index <= mergeRange.topRow && index + count > mergeRange.bottomRow) {
                                    // if the delete rows contain the merge cell range
                                    // we will delete the merge cell range directly.
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                                else if (mergeRange.bottomRow < index || mergeRange.topRow >= index + count) {
                                    // Update the merge range when the deleted row is outside current merge cell range.
                                    if (mergeRange.topRow > index) {
                                        mergeRange.row -= count;
                                    }
                                    mergeRange.row2 -= count;
                                    this.selectedSheet._mergedRanges[newCellIndex] = mergeRange;
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                                else {
                                    // Update the merge range when the deleted rows intersect with current merge cell range.
                                    this._updateCellMergeRangeForRow(mergeRange, index, count, updatedMergeCell, true);
                                }
                            }
                        }
                    }
                    else {
                        // Update for adding rows.
                        startIndex = index * this.columns.length - 1;
                        for (cellIndex = originalCellCount - 1; cellIndex > startIndex; cellIndex--) {
                            newCellIndex = cellIndex + this.columns.length * count;
                            // Update the styledCells hash
                            cellStyle = this.selectedSheet._styledCells[cellIndex];
                            if (cellStyle) {
                                this.selectedSheet._styledCells[newCellIndex] = cellStyle;
                                delete this.selectedSheet._styledCells[cellIndex];
                            }
                            // Update the mergedRange hash
                            mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                            if (mergeRange) {
                                if (mergeRange.topRow < index && mergeRange.bottomRow >= index) {
                                    // Update the merge range when the added row is inside current merge cell range.
                                    this._updateCellMergeRangeForRow(mergeRange, index, count, updatedMergeCell);
                                }
                                else {
                                    // Update the merge range when the added row is outside current merge cell range.
                                    mergeRange.row += count;
                                    mergeRange.row2 += count;
                                    this.selectedSheet._mergedRanges[newCellIndex] = mergeRange;
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                            }
                        }
                    }
                    Object.keys(updatedMergeCell).forEach(function (key) {
                        _this.selectedSheet._mergedRanges[key] = updatedMergeCell[key];
                    });
                };
                // Update the merge cell range when the add\delete rows intersect with current merge cell range.
                FlexSheet.prototype._updateCellMergeRangeForRow = function (currentRange, index, count, updatedMergeCell, isDelete) {
                    //return;
                    var rowIndex, columnIndex, cellIndex, newCellIndex, i, mergeRange, cloneRange;
                    if (isDelete) {
                        // Update the merge cell range for deleting rows.
                        for (rowIndex = currentRange.topRow; rowIndex <= currentRange.bottomRow; rowIndex++) {
                            for (columnIndex = currentRange.leftCol; columnIndex <= currentRange.rightCol; columnIndex++) {
                                cellIndex = rowIndex * this.columns.length + columnIndex;
                                newCellIndex = cellIndex - count * this.columns.length;
                                mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                                if (mergeRange) {
                                    cloneRange = mergeRange.clone();
                                    // when the first delete row is above the merge cell range
                                    // we should adjust the topRow of the merge cell rang via the first delete row.
                                    if (cloneRange.row > index) {
                                        cloneRange.row -= cloneRange.row - index;
                                    }
                                    // when the last delete row is behind the merge cell range.
                                    // we should adjust the bottomRow of the merge cell rang via the first delete row.
                                    if (cloneRange.row2 < index + count - 1) {
                                        cloneRange.row2 -= cloneRange.row2 - index + 1;
                                    }
                                    else {
                                        cloneRange.row2 -= count;
                                    }
                                    if (rowIndex < index) {
                                        updatedMergeCell[cellIndex] = cloneRange;
                                    }
                                    else {
                                        if (rowIndex >= index + count) {
                                            updatedMergeCell[newCellIndex] = cloneRange;
                                        }
                                        delete this.selectedSheet._mergedRanges[cellIndex];
                                    }
                                }
                            }
                        }
                    }
                    else {
                        // Update the merge cell range for adding row.
                        for (rowIndex = currentRange.bottomRow; rowIndex >= currentRange.topRow; rowIndex--) {
                            for (columnIndex = currentRange.rightCol; columnIndex >= currentRange.leftCol; columnIndex--) {
                                cellIndex = rowIndex * this.columns.length + columnIndex;
                                mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                                if (mergeRange) {
                                    cloneRange = mergeRange.clone();
                                    cloneRange.row2 += count;
                                    if (rowIndex < index) {
                                        updatedMergeCell[cellIndex] = cloneRange.clone();
                                    }
                                    for (i = 1; i <= count; i++) {
                                        newCellIndex = cellIndex + this.columns.length * i;
                                        updatedMergeCell[newCellIndex] = cloneRange;
                                    }
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                            }
                        }
                    }
                };
                // update styledCells hash and mergedRange hash for add\delete columns.
                FlexSheet.prototype._updateCellsForUpdatingColumn = function (originalColumnCount, index, count, isDelete) {
                    var _this = this;
                    var cellIndex, newCellIndex, cellStyle, rowIndex, columnIndex, mergeRange, updatedMergeCell = {}, originalCellCount = this.rows.length * originalColumnCount;
                    // Update for deleting columns.
                    if (isDelete) {
                        for (cellIndex = index; cellIndex < originalCellCount; cellIndex++) {
                            rowIndex = Math.floor(cellIndex / originalColumnCount);
                            columnIndex = cellIndex % originalColumnCount;
                            newCellIndex = cellIndex - (count * (rowIndex + (columnIndex >= index ? 1 : 0)));
                            // Update the styledCells hash
                            cellStyle = this.selectedSheet._styledCells[cellIndex];
                            if (cellStyle) {
                                // if the cell is outside the delete cell range, we should update the cell index for the cell to store the style.
                                // otherwise it need be deleted directly.
                                if (columnIndex < index || columnIndex >= index + count) {
                                    this.selectedSheet._styledCells[newCellIndex] = cellStyle;
                                }
                                delete this.selectedSheet._styledCells[cellIndex];
                            }
                            // Update the mergedRange hash
                            mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                            if (mergeRange) {
                                if (index <= mergeRange.leftCol && index + count > mergeRange.rightCol) {
                                    // if the delete columns contain the merge cell range
                                    // we will delete the merge cell range directly.
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                                else if (mergeRange.rightCol < index || mergeRange.leftCol >= index + count) {
                                    // Update the merge range when the deleted column is outside current merge cell range.
                                    if (mergeRange.leftCol >= index) {
                                        mergeRange.col -= count;
                                        mergeRange.col2 -= count;
                                    }
                                    this.selectedSheet._mergedRanges[newCellIndex] = mergeRange;
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                                else {
                                    // Update the merge range when the deleted columns intersect with current merge cell range.
                                    this._updateCellMergeRangeForColumn(mergeRange, index, count, originalColumnCount, updatedMergeCell, true);
                                }
                            }
                        }
                    }
                    else {
                        // Update for adding columns.
                        for (cellIndex = originalCellCount - 1; cellIndex >= index; cellIndex--) {
                            rowIndex = Math.floor(cellIndex / originalColumnCount);
                            columnIndex = cellIndex % originalColumnCount;
                            newCellIndex = cellIndex + rowIndex * count + (columnIndex >= index ? 1 : 0);
                            // Update the styledCells hash
                            cellStyle = this.selectedSheet._styledCells[cellIndex];
                            if (cellStyle) {
                                this.selectedSheet._styledCells[newCellIndex] = cellStyle;
                                delete this.selectedSheet._styledCells[cellIndex];
                            }
                            // Update the mergedRange hash
                            mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                            if (mergeRange) {
                                if (mergeRange.leftCol < index && mergeRange.rightCol >= index) {
                                    // Update the merge range when the added column is inside current merge cell range.
                                    this._updateCellMergeRangeForColumn(mergeRange, index, count, originalColumnCount, updatedMergeCell);
                                }
                                else {
                                    // Update the merge range when the added column is outside current merge cell range.
                                    if (mergeRange.leftCol >= index) {
                                        mergeRange.col += count;
                                        mergeRange.col2 += count;
                                    }
                                    this.selectedSheet._mergedRanges[newCellIndex] = mergeRange;
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                            }
                        }
                    }
                    Object.keys(updatedMergeCell).forEach(function (key) {
                        _this.selectedSheet._mergedRanges[key] = updatedMergeCell[key];
                    });
                };
                // Update the merge cell range when the add\delete columns intersect with current merge cell range.
                FlexSheet.prototype._updateCellMergeRangeForColumn = function (currentRange, index, count, originalColumnCount, updatedMergeCell, isDelete) {
                    var rowIndex, columnIndex, cellIndex, newCellIndex, i, mergeRange, cloneRange;
                    if (isDelete) {
                        // Update the merge cell range for deleting columns.
                        for (rowIndex = currentRange.topRow; rowIndex <= currentRange.bottomRow; rowIndex++) {
                            for (columnIndex = currentRange.leftCol; columnIndex <= currentRange.rightCol; columnIndex++) {
                                cellIndex = rowIndex * originalColumnCount + columnIndex;
                                newCellIndex = cellIndex - (count * (rowIndex + (columnIndex >= index ? 1 : 0)));
                                mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                                if (mergeRange) {
                                    cloneRange = mergeRange.clone();
                                    // when the first delete column is before with merge cell range
                                    // we should adjust the leftCol of the merge cell rang via the first delete column.
                                    if (cloneRange.col > index) {
                                        cloneRange.col -= cloneRange.col - index;
                                    }
                                    // when the last delete row is behind the merge cell range.
                                    // we should adjust the bottomRow of the merge cell rang via the first delete row.
                                    if (cloneRange.col2 < index + count - 1) {
                                        cloneRange.col2 -= cloneRange.col2 - index + 1;
                                    }
                                    else {
                                        cloneRange.col2 -= count;
                                    }
                                    if (columnIndex < index || columnIndex >= index + count) {
                                        updatedMergeCell[newCellIndex] = cloneRange;
                                    }
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                            }
                        }
                    }
                    else {
                        // Update the merge cell range for adding column.
                        for (rowIndex = currentRange.bottomRow; rowIndex >= currentRange.topRow; rowIndex--) {
                            for (columnIndex = currentRange.rightCol; columnIndex >= currentRange.leftCol; columnIndex--) {
                                cellIndex = rowIndex * originalColumnCount + columnIndex;
                                newCellIndex = cellIndex + rowIndex * count + (columnIndex >= index ? 1 : 0);
                                mergeRange = this.selectedSheet._mergedRanges[cellIndex];
                                if (mergeRange) {
                                    cloneRange = mergeRange.clone();
                                    cloneRange.col2 += count;
                                    if (columnIndex === index) {
                                        updatedMergeCell[newCellIndex - 1] = cloneRange.clone();
                                    }
                                    if (columnIndex >= index) {
                                        for (i = 0; i < count; i++) {
                                            updatedMergeCell[newCellIndex + i] = cloneRange;
                                        }
                                    }
                                    else {
                                        updatedMergeCell[newCellIndex] = cloneRange;
                                    }
                                    delete this.selectedSheet._mergedRanges[cellIndex];
                                }
                            }
                        }
                    }
                };
                // Clone the mergedRange of the Flexsheet
                FlexSheet.prototype._cloneMergedCells = function () {
                    var copy, mergedRanges;
                    if (!this.selectedSheet) {
                        return null;
                    }
                    mergedRanges = this.selectedSheet._mergedRanges;
                    // Handle the 3 simple types, and null or undefined
                    if (null == mergedRanges || "object" !== typeof mergedRanges)
                        return mergedRanges;
                    // Handle Object
                    if (mergedRanges instanceof Object) {
                        copy = {};
                        for (var attr in mergedRanges) {
                            if (mergedRanges.hasOwnProperty(attr)) {
                                if (mergedRanges[attr] && mergedRanges[attr].clone) {
                                    copy[attr] = mergedRanges[attr].clone();
                                }
                            }
                        }
                        return copy;
                    }
                    throw new Error("Unable to copy obj! Its type isn't supported.");
                };
                // Evaluate specified formula for flexsheet.
                FlexSheet.prototype._evaluate = function (formula, format, sheet, rowIndex, columnIndex) {
                    if (formula && formula.length > 1) {
                        formula = formula[0] === '=' ? formula : '=' + formula;
                        return this._calcEngine.evaluate(formula, format, sheet, rowIndex, columnIndex);
                    }
                    return formula;
                };
                // Copy the current flex sheet to the flexgrid of current sheet.
                FlexSheet.prototype._copyTo = function (sheet) {
                    var self = this, originAutoGenerateColumns = sheet.grid.autoGenerateColumns, colIndex, rowIndex, i;
                    sheet._storeRowSettings();
                    sheet.grid.selection = new grid_1.CellRange();
                    sheet.grid.rows.clear();
                    sheet.grid.columns.clear();
                    sheet.grid.columnHeaders.columns.clear();
                    sheet.grid.rowHeaders.rows.clear();
                    if (self.itemsSource) {
                        sheet.grid.autoGenerateColumns = false;
                        sheet.itemsSource = self.itemsSource;
                        sheet.grid.collectionView.beginUpdate();
                        if (!(sheet.grid.itemsSource instanceof wijmo.collections.CollectionView)) {
                            sheet.grid.collectionView.sortDescriptions.clear();
                            for (i = 0; i < self.collectionView.sortDescriptions.length; i++) {
                                sheet.grid.collectionView.sortDescriptions.push(self.collectionView.sortDescriptions[i]);
                            }
                        }
                    }
                    else {
                        sheet.itemsSource = null;
                        for (rowIndex = 0; rowIndex < self.rows.length; rowIndex++) {
                            sheet.grid.rows.push(self.rows[rowIndex]);
                        }
                    }
                    sheet._filterDefinition = self._filter.filterDefinition;
                    for (colIndex = 0; colIndex < self.columns.length; colIndex++) {
                        sheet.grid.columns.push(self.columns[colIndex]);
                    }
                    if (sheet.grid.collectionView) {
                        self._resetMappedColumns(sheet.grid);
                        sheet.grid.collectionView.endUpdate();
                    }
                    sheet._setRowSettings();
                    sheet.grid.autoGenerateColumns = originAutoGenerateColumns;
                    sheet.grid.frozenRows = self.frozenRows;
                    sheet.grid.frozenColumns = self.frozenColumns;
                    sheet.grid.selection = self.selection;
                    sheet._scrollPosition = self.scrollPosition;
                    setTimeout(function () {
                        self._setFlexSheetToDirty();
                        self.refresh(true);
                    }, 10);
                };
                // Copy the flexgrid of current sheet to flexsheet.
                FlexSheet.prototype._copyFrom = function (sheet, needRefresh) {
                    if (needRefresh === void 0) { needRefresh = true; }
                    var self = this, originAutoGenerateColumns = self.autoGenerateColumns, colIndex, rowIndex, i, rowSetting, column, row;
                    self._isCopying = true;
                    self._dragable = false;
                    self.itemsSource = null;
                    self.rows.clear();
                    self.columns.clear();
                    self.columnHeaders.columns.clear();
                    self.rowHeaders.rows.clear();
                    self.selection = new grid_1.CellRange();
                    if (sheet.selectionRanges.length > 1 && self.selectionMode === grid_1.SelectionMode.CellRange) {
                        self._enableMulSel = true;
                    }
                    if (sheet.itemsSource) {
                        self.autoGenerateColumns = false;
                        self.itemsSource = sheet.itemsSource;
                        self.collectionView.beginUpdate();
                        if (!(self.itemsSource instanceof wijmo.collections.CollectionView)) {
                            self.collectionView.sortDescriptions.clear();
                            for (i = 0; i < sheet.grid.collectionView.sortDescriptions.length; i++) {
                                self.collectionView.sortDescriptions.push(sheet.grid.collectionView.sortDescriptions[i]);
                            }
                        }
                    }
                    else {
                        for (rowIndex = 0; rowIndex < sheet.grid.rows.length; rowIndex++) {
                            self.rows.push(sheet.grid.rows[rowIndex]);
                        }
                    }
                    for (colIndex = 0; colIndex < sheet.grid.columns.length; colIndex++) {
                        column = sheet.grid.columns[colIndex];
                        column.isRequired = false;
                        self.columns.push(column);
                    }
                    if (self.collectionView) {
                        if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
                            self.collectionView.useStableSort = true;
                        }
                        self._resetMappedColumns(self);
                        self.collectionView.endUpdate();
                        self.collectionView.collectionChanged.addHandler(function (sender, e) {
                            if (e.action === wijmo.collections.NotifyCollectionChangedAction.Reset) {
                                self.invalidate();
                            }
                        }, self);
                    }
                    if (self.rows.length && self.columns.length) {
                        self.selection = sheet.grid.selection;
                    }
                    if (sheet._filterDefinition) {
                        self._filter.filterDefinition = sheet._filterDefinition;
                    }
                    for (rowIndex = 0; rowIndex < self.rows.length; rowIndex++) {
                        rowSetting = sheet._rowSettings[rowIndex];
                        if (rowSetting) {
                            row = self.rows[rowIndex];
                            row.height = rowSetting.height;
                            row.allowMerging = rowSetting.allowMerging;
                            row.visible = rowSetting.visible;
                            if (row instanceof grid_1.GroupRow) {
                                row.isCollapsed = rowSetting.isCollapsed;
                            }
                        }
                    }
                    self.autoGenerateColumns = originAutoGenerateColumns;
                    self.frozenRows = sheet.grid.frozenRows;
                    self.frozenColumns = sheet.grid.frozenColumns;
                    self._isCopying = false;
                    if (self._addingSheet) {
                        if (self._toRefresh) {
                            clearTimeout(self._toRefresh);
                            self._toRefresh = null;
                        }
                        self._toRefresh = setTimeout(function () {
                            self._setFlexSheetToDirty();
                            self.invalidate();
                        }, 10);
                        self._addingSheet = false;
                    }
                    else if (needRefresh) {
                        self.refresh();
                    }
                    self.scrollPosition = sheet._scrollPosition;
                };
                // Reset the _mappedColumns hash for the flexgrid. 
                FlexSheet.prototype._resetMappedColumns = function (flex) {
                    var col, sds, i = 0;
                    flex._mappedColumns = null;
                    if (flex.collectionView) {
                        sds = flex.collectionView.sortDescriptions;
                        for (; i < sds.length; i++) {
                            col = flex.columns.getColumn(sds[i].property);
                            if (col && col.dataMap) {
                                if (!flex._mappedColumns) {
                                    flex._mappedColumns = {};
                                }
                                flex._mappedColumns[col.binding] = col.dataMap;
                            }
                        }
                    }
                };
                // reset the filter definition for the flexsheet.
                FlexSheet.prototype._resetFilterDefinition = function () {
                    this._resettingFilter = true;
                    this._filter.filterDefinition = JSON.stringify({
                        defaultFilterType: wijmo.grid.filter.FilterType.Both,
                        filters: []
                    });
                    this._resettingFilter = false;
                };
                // Load the workbook instance to the flexsheet
                FlexSheet.prototype._loadFromWorkbook = function (workbook) {
                    var sheetCount, defiendName, sheetIndex = 0, self = this, i;
                    if (workbook.sheets == null || workbook.sheets.length === 0) {
                        return;
                    }
                    self.beginUpdate();
                    self.clear();
                    self._reservedContent = workbook.reservedContent;
                    sheetCount = workbook.sheets.length;
                    for (; sheetIndex < sheetCount; sheetIndex++) {
                        if (sheetIndex > 0) {
                            self.addUnboundSheet();
                        }
                        self.selectedSheet.grid['wj_sheetInfo'] = {};
                        wijmo.grid.xlsx.FlexGridXlsxConverter.load(self.selectedSheet.grid, workbook, { sheetIndex: sheetIndex, includeColumnHeaders: false });
                        self.selectedSheet.name = self.selectedSheet.grid['wj_sheetInfo'].name;
                        self.selectedSheet.visible = self.selectedSheet.grid['wj_sheetInfo'].visible;
                        self.selectedSheet._styledCells = self.selectedSheet.grid['wj_sheetInfo'].styledCells;
                        self.selectedSheet._mergedRanges = self.selectedSheet.grid['wj_sheetInfo'].mergedRanges;
                        if (self.selectedSheet.grid['wj_sheetInfo'].tableNames != null && self.selectedSheet.grid['wj_sheetInfo'].tableNames.length > 0) {
                            for (i = 0; i < self.selectedSheet.grid['wj_sheetInfo'].tableNames.length; i++) {
                                self.selectedSheet.tableNames[i] = self.selectedSheet.grid['wj_sheetInfo'].tableNames[i];
                            }
                        }
                        self._copyFrom(self.selectedSheet, false);
                    }
                    if (workbook.activeWorksheet != null && workbook.activeWorksheet > -1 && workbook.activeWorksheet < self.sheets.length) {
                        self.selectedSheetIndex = workbook.activeWorksheet;
                    }
                    else {
                        self.selectedSheetIndex = 0;
                    }
                    if (workbook.definedNames && workbook.definedNames.length > 0) {
                        for (i = 0; i < workbook.definedNames.length; i++) {
                            defiendName = workbook.definedNames[i];
                            self.definedNames.push(new DefinedName(self, defiendName.name, defiendName.value, defiendName.sheetName));
                        }
                    }
                    if (workbook.tables && workbook.tables.length > 0) {
                        var selSheetIdx = self.selectedSheetIndex;
                        var tables = [];
                        for (i = 0; i < workbook.tables.length; i++) {
                            self.selectedSheetIndex = self._getTableSheetIndex(workbook.tables[i].name);
                            tables[i] = this._parseFromWorkbookTable(workbook.tables[i]);
                        }
                        this._tables = new wijmo.collections.ObservableArray(tables);
                        self.selectedSheetIndex = selSheetIdx;
                    }
                    if (workbook.colorThemes && workbook.colorThemes.length > 0) {
                        for (i = 0; i < this._colorThemes.length; i++) {
                            this._colorThemes[i] = workbook.colorThemes[i];
                        }
                    }
                    self.endUpdate();
                    self.onLoaded();
                };
                // Save the flexsheet to the workbook instance.
                FlexSheet.prototype._saveToWorkbook = function () {
                    var mainBook, tmpBook, definedName, item, currentSheet, sheetIndex, i;
                    if (this.sheets.length === 0) {
                        throw 'The flexsheet is empty.';
                    }
                    currentSheet = this.sheets[0];
                    if (this.selectedSheetIndex === 0) {
                        currentSheet._storeRowSettings();
                        if (currentSheet.tableNames.length > 0) {
                            currentSheet.grid['wj_sheetInfo'].tableNames = currentSheet.tableNames;
                        }
                    }
                    currentSheet._setRowSettings();
                    mainBook = wijmo.grid.xlsx.FlexGridXlsxConverter.save(currentSheet.grid, { sheetName: currentSheet.name, sheetVisible: currentSheet.visible, includeColumnHeaders: false });
                    mainBook.reservedContent = this._reservedContent;
                    for (sheetIndex = 1; sheetIndex < this.sheets.length; sheetIndex++) {
                        currentSheet = this.sheets[sheetIndex];
                        if (this.selectedSheetIndex === sheetIndex) {
                            currentSheet._storeRowSettings();
                        }
                        currentSheet._setRowSettings();
                        if (currentSheet.tableNames.length > 0) {
                            currentSheet.grid['wj_sheetInfo'].tableNames = currentSheet.tableNames;
                        }
                        currentSheet._setRowSettings();
                        tmpBook = wijmo.grid.xlsx.FlexGridXlsxConverter.save(currentSheet.grid, { sheetName: currentSheet.name, sheetVisible: currentSheet.visible, includeColumnHeaders: false });
                        mainBook._addWorkSheet(tmpBook.sheets[0], sheetIndex);
                    }
                    mainBook.activeWorksheet = this.selectedSheetIndex;
                    for (i = 0; i < this.definedNames.length; i++) {
                        var item = this.definedNames[i];
                        definedName = new wijmo.xlsx.DefinedName();
                        definedName.name = item.name;
                        definedName.value = item.value;
                        definedName.sheetName = item.sheetName;
                        mainBook.definedNames.push(definedName);
                    }
                    if (this._tables && this._tables.length > 0) {
                        for (i = 0; i < this._tables.length; i++) {
                            mainBook.tables.push(this._parseToWorkbookTable(this._tables[i]));
                        }
                    }
                    if (this._colorThemes && this._colorThemes.length > 0) {
                        for (i = 0; i < this._colorThemes.length; i++) {
                            mainBook.colorThemes[i] = this._colorThemes[i];
                        }
                    }
                    return mainBook;
                };
                // mouseDown event handler.
                // This event handler for handling selecting columns
                FlexSheet.prototype._mouseDown = function (e) {
                    var userAgent = window.navigator.userAgent, ht = this.hitTest(e), cols = this.columns, currentRange, colIndex, selected, newSelection, edt;
                    if (this.selectedSheet) {
                        this.selectedSheet._scrollPosition = this.scrollPosition;
                    }
                    this._wholeColumnsSelected = false;
                    if (this._dragable) {
                        this._isDragging = true;
                        this._draggingMarker = document.createElement('div');
                        wijmo.setCss(this._draggingMarker, {
                            position: 'absolute',
                            display: 'none',
                            borderStyle: 'dotted',
                            cursor: 'move'
                        });
                        document.body.appendChild(this._draggingMarker);
                        this._draggingTooltip = new wijmo.Tooltip();
                        this._draggingCells = this.selection;
                        if (this.selectedSheet) {
                            this.selectedSheet.selectionRanges.clear();
                        }
                        this.onDraggingRowColumn(new DraggingRowColumnEventArgs(this._draggingRow, e.shiftKey));
                        e.preventDefault();
                        return;
                    }
                    if (ht.cellType !== grid_1.CellType.None) {
                        this._isClicking = true;
                    }
                    if (this.selectionMode === grid_1.SelectionMode.CellRange) {
                        if (e.ctrlKey) {
                            if (!this._enableMulSel) {
                                this._enableMulSel = true;
                            }
                        }
                        else {
                            if (ht.cellType !== grid_1.CellType.None) {
                                if (this.selectedSheet) {
                                    this.selectedSheet.selectionRanges.clear();
                                }
                                if (this._enableMulSel) {
                                    this.refresh(false);
                                }
                                this._enableMulSel = false;
                            }
                        }
                    }
                    else {
                        this._enableMulSel = false;
                        if (this.selectedSheet) {
                            this.selectedSheet.selectionRanges.clear();
                        }
                    }
                    this._htDown = ht;
                    // If there is no rows or columns in the flexsheet, we don't need deal with anything in the mouse down event(TFS 122628)
                    if (this.rows.length === 0 || this.columns.length === 0) {
                        return;
                    }
                    if (!userAgent.match(/iPad/i) && !userAgent.match(/iPhone/i)) {
                        this._contextMenu.hide();
                    }
                    if (this.selectionMode !== grid_1.SelectionMode.CellRange) {
                        return;
                    }
                    // When right click the row header, we should select current row. (TFS 121167)
                    if (ht.cellType === grid_1.CellType.RowHeader && e.which === 3) {
                        newSelection = new grid_1.CellRange(ht.row, 0, ht.row, this.columns.length - 1);
                        if (!this.selection.contains(newSelection)) {
                            this.selection = newSelection;
                        }
                        return;
                    }
                    if (ht.cellType !== grid_1.CellType.ColumnHeader && ht.cellType !== grid_1.CellType.None) {
                        return;
                    }
                    if (ht.col > -1 && this.columns[ht.col].isSelected) {
                        return;
                    }
                    if (!wijmo.hasClass(e.target, 'wj-cell') || ht.edgeRight) {
                        return;
                    }
                    this._columnHeaderClicked = true;
                    this._wholeColumnsSelected = true;
                    if (e.shiftKey) {
                        this._multiSelectColumns(ht);
                    }
                    else {
                        currentRange = new grid_1.CellRange(this.itemsSource ? 1 : 0, ht.col, this.rows.length - 1, ht.col);
                        if (e.which === 3 && this.selection.contains(currentRange)) {
                            return;
                        }
                        this.select(currentRange);
                    }
                };
                // mouseMove event handler
                // This event handler for handling multiple selecting columns.
                FlexSheet.prototype._mouseMove = function (e) {
                    var ht = this.hitTest(e), selection = this.selection, rowCnt = this.rows.length, colCnt = this.columns.length, cursor = this.hostElement.style.cursor, isTopRow;
                    if (this.rows.length === 0 || this.columns.length === 0) {
                        this._dragable = false;
                        if (ht.cellType === grid_1.CellType.Cell) {
                            this.hostElement.style.cursor = 'default';
                        }
                        return;
                    }
                    if (this._isDragging) {
                        this.hostElement.style.cursor = 'move';
                        this._showDraggingMarker(e);
                        return;
                    }
                    if (this.itemsSource) {
                        isTopRow = selection.topRow === 0 || selection.topRow === 1;
                    }
                    else {
                        isTopRow = selection.topRow === 0;
                    }
                    if (selection && ht.cellType !== grid_1.CellType.None && !this.itemsSource) {
                        this._draggingColumn = isTopRow && selection.bottomRow === rowCnt - 1;
                        this._draggingRow = selection.leftCol === 0 && selection.rightCol === colCnt - 1;
                        if (ht.cellType === grid_1.CellType.Cell) {
                            if (this._draggingColumn && (((ht.col === selection.leftCol - 1 || ht.col === selection.rightCol) && ht.edgeRight)
                                || (ht.row === rowCnt - 1 && ht.edgeBottom))) {
                                cursor = 'move';
                            }
                            if (this._draggingRow && !this._containsGroupRows(selection) && ((ht.row === selection.topRow - 1 || ht.row === selection.bottomRow) && ht.edgeBottom
                                || (ht.col === colCnt - 1 && ht.edgeRight))) {
                                cursor = 'move';
                            }
                        }
                        else if (ht.cellType === grid_1.CellType.ColumnHeader) {
                            if (ht.edgeBottom) {
                                if (this._draggingColumn && (ht.col >= selection.leftCol && ht.col <= selection.rightCol)) {
                                    cursor = 'move';
                                }
                                else if (this._draggingRow && selection.topRow === 0) {
                                    cursor = 'move';
                                }
                            }
                        }
                        else if (ht.cellType === grid_1.CellType.RowHeader) {
                            if (ht.edgeRight) {
                                if (this._draggingColumn && selection.leftCol === 0) {
                                    cursor = 'move';
                                }
                                else if (this._draggingRow && (ht.row >= selection.topRow && ht.row <= selection.bottomRow) && !this._containsGroupRows(selection)) {
                                    cursor = 'move';
                                }
                            }
                        }
                        if (cursor === 'move') {
                            this._dragable = true;
                        }
                        else {
                            this._dragable = false;
                        }
                        this.hostElement.style.cursor = cursor;
                    }
                    if (!this._htDown || !this._htDown.panel) {
                        return;
                    }
                    ht = new grid_1.HitTestInfo(this._htDown.panel, e);
                    this._multiSelectColumns(ht);
                    if (ht.cellType === grid_1.CellType.Cell) {
                        this.scrollIntoView(ht.row, ht.col);
                    }
                };
                // mouseUp event handler.
                // This event handler for resetting the variable for handling multiple select columns
                FlexSheet.prototype._mouseUp = function (e) {
                    if (this._isDragging) {
                        if (!this._draggingCells.equals(this._dropRange)) {
                            this._handleDropping(e);
                            this.onDroppingRowColumn();
                        }
                        this._draggingCells = null;
                        this._dropRange = null;
                        document.body.removeChild(this._draggingMarker);
                        this._draggingMarker = null;
                        this._draggingTooltip.hide();
                        this._draggingTooltip = null;
                        this._isDragging = false;
                        this._draggingColumn = false;
                        this._draggingRow = false;
                    }
                    if (this._htDown && this._htDown.cellType !== grid_1.CellType.None && this.selectedSheet) {
                        if (this._htDown.cellType === grid_1.CellType.TopLeft && this.selectionMode === grid_1.SelectionMode.CellRange) {
                            this.selection = new grid_1.CellRange(this.selectedSheet.itemsSource ? 1 : 0, 0, this.rows.length - 1, this.columns.length - 1);
                            this.selectedSheet.selectionRanges.push(this.selection);
                        }
                        else if (this.selection.isValid) {
                            this.selectedSheet.selectionRanges.push(this.selection);
                        }
                        this._enableMulSel = false;
                    }
                    this._isClicking = false;
                    this._columnHeaderClicked = false;
                    this._htDown = null;
                };
                // Click event handler.
                FlexSheet.prototype._click = function () {
                    var self = this, userAgent = window.navigator.userAgent;
                    // When click in the body, we also need hide the context menu.
                    if (!userAgent.match(/iPad/i) && !userAgent.match(/iPhone/i)) {
                        self._contextMenu.hide();
                    }
                    setTimeout(function () {
                        self.hideFunctionList();
                    }, 200);
                };
                // touch start event handler for iOS device
                FlexSheet.prototype._touchStart = function (e) {
                    var self = this;
                    if (!wijmo.hasClass(e.target, 'wj-context-menu-item')) {
                        self._contextMenu.hide();
                    }
                    self._longClickTimer = setTimeout(function () {
                        var ht;
                        ht = self.hitTest(e);
                        if (ht && ht.cellType !== grid_1.CellType.None && !self.itemsSource && !self._resizing) {
                            self._contextMenu.show(null, new wijmo.Point(e.pageX + 10, e.pageY + 10));
                        }
                    }, 500);
                };
                // touch end event handler for iOS device
                FlexSheet.prototype._touchEnd = function () {
                    clearTimeout(this._longClickTimer);
                };
                // Show the dragging marker while the mouse moving.
                FlexSheet.prototype._showDraggingMarker = function (e) {
                    var hitInfo = new grid_1.HitTestInfo(this.cells, e), selection = this.selection, colCnt = this.columns.length, rowCnt = this.rows.length, scrollOffset = this._cumulativeScrollOffset(this.hostElement), rootBounds = this['_root'].getBoundingClientRect(), rootOffsetX = rootBounds.left + scrollOffset.x, rootOffsetY = rootBounds.top + scrollOffset.y, hitCellBounds, selectionCnt, hit, height, width, rootSize, i, content, css;
                    this.scrollIntoView(hitInfo.row, hitInfo.col);
                    if (this._draggingColumn) {
                        selectionCnt = selection.rightCol - selection.leftCol + 1;
                        hit = hitInfo.col;
                        width = 0;
                        if (hit < 0 || hit + selectionCnt > colCnt) {
                            hit = colCnt - selectionCnt;
                        }
                        hitCellBounds = this.cells.getCellBoundingRect(0, hit);
                        rootSize = this['_root'].offsetHeight - this['_eCHdr'].offsetHeight;
                        height = this.cells.height;
                        height = height > rootSize ? rootSize : height;
                        for (i = 0; i < selectionCnt; i++) {
                            width += this.columns[hit + i].renderSize;
                        }
                        content = FlexSheet.convertNumberToAlpha(hit) + ' : ' + FlexSheet.convertNumberToAlpha(hit + selectionCnt - 1);
                        if (this._dropRange) {
                            this._dropRange.col = hit;
                            this._dropRange.col2 = hit + selectionCnt - 1;
                        }
                        else {
                            this._dropRange = new grid_1.CellRange(0, hit, this.rows.length - 1, hit + selectionCnt - 1);
                        }
                    }
                    else if (this._draggingRow) {
                        selectionCnt = selection.bottomRow - selection.topRow + 1;
                        hit = hitInfo.row;
                        height = 0;
                        if (hit < 0 || hit + selectionCnt > rowCnt) {
                            hit = rowCnt - selectionCnt;
                        }
                        hitCellBounds = this.cells.getCellBoundingRect(hit, 0);
                        rootSize = this['_root'].offsetWidth - this['_eRHdr'].offsetWidth;
                        for (i = 0; i < selectionCnt; i++) {
                            height += this.rows[hit + i].renderSize;
                        }
                        width = this.cells.width;
                        width = width > rootSize ? rootSize : width;
                        content = (hit + 1) + ' : ' + (hit + selectionCnt);
                        if (this._dropRange) {
                            this._dropRange.row = hit;
                            this._dropRange.row2 = hit + selectionCnt - 1;
                        }
                        else {
                            this._dropRange = new grid_1.CellRange(hit, 0, hit + selectionCnt - 1, this.columns.length - 1);
                        }
                    }
                    if (!hitCellBounds) {
                        return;
                    }
                    css = {
                        display: 'inline',
                        zIndex: '9999',
                        opacity: 0.5,
                        top: hitCellBounds.top - (this._draggingColumn ? this._ptScrl.y : 0) + scrollOffset.y,
                        left: hitCellBounds.left - (this._draggingRow ? this._ptScrl.x : 0) + scrollOffset.x,
                        height: height,
                        width: width
                    };
                    hitCellBounds.top = hitCellBounds.top - (this._draggingColumn ? this._ptScrl.y : 0);
                    hitCellBounds.left = hitCellBounds.left - (this._draggingRow ? this._ptScrl.x : 0);
                    if (this.rightToLeft && this._draggingRow) {
                        css.left = css.left - width + hitCellBounds.width + 2 * this._ptScrl.x;
                        hitCellBounds.left = hitCellBounds.left + 2 * this._ptScrl.x;
                    }
                    if (this._draggingRow) {
                        if (rootOffsetX + this['_eRHdr'].offsetWidth !== css.left || rootOffsetY + this['_root'].offsetHeight + 1 < css.top + css.height) {
                            return;
                        }
                    }
                    else {
                        if (rootOffsetY + this['_eCHdr'].offsetHeight !== css.top || rootOffsetX + this['_root'].offsetWidth + 1 < css.left + css.width) {
                            return;
                        }
                    }
                    wijmo.setCss(this._draggingMarker, css);
                    this._draggingTooltip.show(this.hostElement, content, hitCellBounds);
                };
                // Handle dropping rows or columns.
                FlexSheet.prototype._handleDropping = function (e) {
                    var self = this, srcRowIndex, srcColIndex, desRowIndex, desColIndex, moveCellsAction, affectedFormulas, affectedDefinedNames;
                    if (!self.selectedSheet || !self._draggingCells || !self._dropRange || self._containsMergedCells(self._draggingCells) || self._containsMergedCells(self._dropRange)) {
                        return;
                    }
                    self._clearCalcEngine();
                    if ((self._draggingColumn && self._draggingCells.leftCol > self._dropRange.leftCol)
                        || (self._draggingRow && self._draggingCells.topRow > self._dropRange.topRow)) {
                        // Handle changing the columns or rows position.
                        if (e.shiftKey) {
                            if (self._draggingColumn) {
                                desColIndex = self._dropRange.leftCol;
                                for (srcColIndex = self._draggingCells.leftCol; srcColIndex <= self._draggingCells.rightCol; srcColIndex++) {
                                    self.columns.moveElement(srcColIndex, desColIndex);
                                    desColIndex++;
                                }
                            }
                            else if (self._draggingRow) {
                                desRowIndex = self._dropRange.topRow;
                                for (srcRowIndex = self._draggingCells.topRow; srcRowIndex <= self._draggingCells.bottomRow; srcRowIndex++) {
                                    self.rows.moveElement(srcRowIndex, desRowIndex);
                                    desRowIndex++;
                                }
                            }
                            self._exchangeCellStyle(true);
                        }
                        else {
                            // Handle moving or copying the cell content.
                            moveCellsAction = new sheet_1._MoveCellsAction(self, self._draggingCells, self._dropRange, e.ctrlKey);
                            desRowIndex = self._dropRange.topRow;
                            for (srcRowIndex = self._draggingCells.topRow; srcRowIndex <= self._draggingCells.bottomRow; srcRowIndex++) {
                                desColIndex = self._dropRange.leftCol;
                                for (srcColIndex = self._draggingCells.leftCol; srcColIndex <= self._draggingCells.rightCol; srcColIndex++) {
                                    self._moveCellContent(srcRowIndex, srcColIndex, desRowIndex, desColIndex, e.ctrlKey);
                                    if (self._draggingColumn && desRowIndex === self._dropRange.topRow) {
                                        self.columns[desColIndex].dataType = self.columns[srcColIndex].dataType ? self.columns[srcColIndex].dataType : wijmo.DataType.Object;
                                        self.columns[desColIndex].align = self.columns[srcColIndex].align;
                                        self.columns[desColIndex].format = self.columns[srcColIndex].format;
                                        if (!e.ctrlKey) {
                                            self.columns[srcColIndex].dataType = wijmo.DataType.Object;
                                            self.columns[srcColIndex].align = null;
                                            self.columns[srcColIndex].format = null;
                                        }
                                    }
                                    desColIndex++;
                                }
                                desRowIndex++;
                            }
                            if (self._draggingColumn && !e.ctrlKey) {
                                desColIndex = self._dropRange.leftCol;
                                for (srcColIndex = self._draggingCells.leftCol; srcColIndex <= self._draggingCells.rightCol; srcColIndex++) {
                                    self._updateColumnFiler(srcColIndex, desColIndex);
                                    desColIndex++;
                                }
                            }
                        }
                    }
                    else if ((self._draggingColumn && self._draggingCells.leftCol < self._dropRange.leftCol)
                        || (self._draggingRow && self._draggingCells.topRow < self._dropRange.topRow)) {
                        // Handle changing the columns or rows position.
                        if (e.shiftKey) {
                            if (self._draggingColumn) {
                                desColIndex = self._dropRange.rightCol;
                                for (srcColIndex = self._draggingCells.rightCol; srcColIndex >= self._draggingCells.leftCol; srcColIndex--) {
                                    self.columns.moveElement(srcColIndex, desColIndex);
                                    desColIndex--;
                                }
                            }
                            else if (self._draggingRow) {
                                desRowIndex = self._dropRange.bottomRow;
                                for (srcRowIndex = self._draggingCells.bottomRow; srcRowIndex >= self._draggingCells.topRow; srcRowIndex--) {
                                    self.rows.moveElement(srcRowIndex, desRowIndex);
                                    desRowIndex--;
                                }
                            }
                            self._exchangeCellStyle(false);
                        }
                        else {
                            // Handle moving or copying the cell content.
                            moveCellsAction = new sheet_1._MoveCellsAction(self, self._draggingCells, self._dropRange, e.ctrlKey);
                            desRowIndex = self._dropRange.bottomRow;
                            for (srcRowIndex = self._draggingCells.bottomRow; srcRowIndex >= self._draggingCells.topRow; srcRowIndex--) {
                                desColIndex = self._dropRange.rightCol;
                                for (srcColIndex = self._draggingCells.rightCol; srcColIndex >= self._draggingCells.leftCol; srcColIndex--) {
                                    self._moveCellContent(srcRowIndex, srcColIndex, desRowIndex, desColIndex, e.ctrlKey);
                                    if (self._draggingColumn && desRowIndex === self._dropRange.bottomRow) {
                                        self.columns[desColIndex].dataType = self.columns[srcColIndex].dataType ? self.columns[srcColIndex].dataType : wijmo.DataType.Object;
                                        self.columns[desColIndex].align = self.columns[srcColIndex].align;
                                        self.columns[desColIndex].format = self.columns[srcColIndex].format;
                                        if (!e.ctrlKey) {
                                            self.columns[srcColIndex].dataType = wijmo.DataType.Object;
                                            self.columns[srcColIndex].align = null;
                                            self.columns[srcColIndex].format = null;
                                        }
                                    }
                                    desColIndex--;
                                }
                                desRowIndex--;
                            }
                            if (self._draggingColumn && !e.ctrlKey) {
                                desColIndex = self._dropRange.rightCol;
                                for (srcColIndex = self._draggingCells.rightCol; srcColIndex >= self._draggingCells.leftCol; srcColIndex--) {
                                    self._updateColumnFiler(srcColIndex, desColIndex);
                                    desColIndex--;
                                }
                            }
                        }
                    }
                    if (!e.ctrlKey) {
                        affectedFormulas = self._updateFormulaForDropping(e.shiftKey);
                        affectedDefinedNames = self._updateNamedRangesForDropping();
                    }
                    if (moveCellsAction && moveCellsAction.saveNewState()) {
                        moveCellsAction._affectedFormulas = affectedFormulas;
                        moveCellsAction._affectedDefinedNameVals = affectedDefinedNames;
                        self._undoStack._addAction(moveCellsAction);
                    }
                    if (self._undoStack._pendingAction) {
                        self._undoStack._pendingAction['_affectedFormulas'] = affectedFormulas;
                        self._undoStack._pendingAction['_affectedDefinedNameVals'] = affectedDefinedNames;
                    }
                    self.select(self._dropRange);
                    self.selectedSheet.selectionRanges.push(self.selection);
                    // Ensure that the host element of FlexSheet get focus after dropping. (TFS 142888)
                    self.hostElement.focus();
                };
                // Move the content and style of the source cell to the destination cell.
                FlexSheet.prototype._moveCellContent = function (srcRowIndex, srcColIndex, desRowIndex, desColIndex, isCopyContent) {
                    var val = this.getCellData(srcRowIndex, srcColIndex, false), srcCellIndex = srcRowIndex * this.columns.length + srcColIndex, desCellIndex = desRowIndex * this.columns.length + desColIndex, srcCellStyle = this.selectedSheet._styledCells[srcCellIndex], updatedVal, srcTable, desTable, srcTableColIndex, desTableColIndex, srcColName, desColName;
                    if (isCopyContent && !!val && typeof val === 'string' && val[0] === '=') {
                        updatedVal = this._updateCellRefForDropping(val, this.selectedSheetIndex);
                    }
                    this.setCellData(desRowIndex, desColIndex, updatedVal || val);
                    desTable = this.selectedSheet.findTable(desRowIndex, desColIndex);
                    if (desTable && desTable.showHeaderRow && desRowIndex === desTable.range.topRow) {
                        desTableColIndex = desColIndex - desTable.range.leftCol;
                        desColName = desTable.columns[desTableColIndex].name;
                        desTable.columns[desTableColIndex].name = updatedVal || val;
                    }
                    // Copy the cell style of the source cell to the destination cell.
                    if (srcCellStyle) {
                        this.selectedSheet._styledCells[desCellIndex] = JSON.parse(JSON.stringify(srcCellStyle));
                    }
                    else {
                        delete this.selectedSheet._styledCells[desCellIndex];
                    }
                    // If we just move the columns or the rows, we need remove the content and styles of the cells in the columns or the rows.
                    if (!isCopyContent) {
                        delete this.selectedSheet._styledCells[srcCellIndex];
                        srcTable = this.selectedSheet.findTable(srcRowIndex, srcColIndex);
                        if (srcTable) {
                            if (srcTable === desTable && srcRowIndex === desRowIndex) {
                                if (srcTable.showHeaderRow && srcRowIndex === srcTable.range.topRow) {
                                    srcTableColIndex = srcColIndex - srcTable.range.leftCol;
                                    srcTable._updateColumnName(srcTableColIndex, desColName);
                                    return;
                                }
                            }
                            if (srcTable.showHeaderRow && srcRowIndex === srcTable.range.topRow) {
                                return;
                            }
                        }
                        this.setCellData(srcRowIndex, srcColIndex, null);
                    }
                    else {
                        srcTable = this.selectedSheet.findTable(srcRowIndex, srcColIndex);
                        if (srcTable) {
                            if (srcTable === desTable && srcRowIndex === desRowIndex) {
                                if (srcTable.showHeaderRow && srcRowIndex === srcTable.range.topRow) {
                                    srcTableColIndex = srcColIndex - srcTable.range.leftCol;
                                    srcTable._updateColumnName(srcTableColIndex, updatedVal || val);
                                }
                            }
                        }
                    }
                };
                // Exchange the cell style for changing the rows or columns position.
                FlexSheet.prototype._exchangeCellStyle = function (isReverse) {
                    var rowIndex, colIndex, cellIndex, newCellIndex, draggingRange, index = 0, srcCellStyles = [];
                    // Store the style of the source cells and delete the style of the source cells.
                    // Since the stored style will be moved to the destination cells.
                    for (rowIndex = this._draggingCells.topRow; rowIndex <= this._draggingCells.bottomRow; rowIndex++) {
                        for (colIndex = this._draggingCells.leftCol; colIndex <= this._draggingCells.rightCol; colIndex++) {
                            cellIndex = rowIndex * this.columns.length + colIndex;
                            if (this.selectedSheet._styledCells[cellIndex]) {
                                srcCellStyles.push(JSON.parse(JSON.stringify(this.selectedSheet._styledCells[cellIndex])));
                                delete this.selectedSheet._styledCells[cellIndex];
                            }
                            else {
                                srcCellStyles.push(undefined);
                            }
                        }
                    }
                    // Adjust the style of the cells that is between the dragging cells and the drop range.
                    if (isReverse) {
                        if (this._draggingColumn) {
                            draggingRange = this._draggingCells.rightCol - this._draggingCells.leftCol + 1;
                            for (colIndex = this._draggingCells.leftCol - 1; colIndex >= this._dropRange.leftCol; colIndex--) {
                                for (rowIndex = 0; rowIndex < this.rows.length; rowIndex++) {
                                    cellIndex = rowIndex * this.columns.length + colIndex;
                                    newCellIndex = rowIndex * this.columns.length + colIndex + draggingRange;
                                    if (this.selectedSheet._styledCells[cellIndex]) {
                                        this.selectedSheet._styledCells[newCellIndex] = JSON.parse(JSON.stringify(this.selectedSheet._styledCells[cellIndex]));
                                        delete this.selectedSheet._styledCells[cellIndex];
                                    }
                                    else {
                                        delete this.selectedSheet._styledCells[newCellIndex];
                                    }
                                }
                            }
                        }
                        else if (this._draggingRow) {
                            draggingRange = this._draggingCells.bottomRow - this._draggingCells.topRow + 1;
                            for (rowIndex = this._draggingCells.topRow - 1; rowIndex >= this._dropRange.topRow; rowIndex--) {
                                for (colIndex = 0; colIndex < this.columns.length; colIndex++) {
                                    cellIndex = rowIndex * this.columns.length + colIndex;
                                    newCellIndex = (rowIndex + draggingRange) * this.columns.length + colIndex;
                                    if (this.selectedSheet._styledCells[cellIndex]) {
                                        this.selectedSheet._styledCells[newCellIndex] = JSON.parse(JSON.stringify(this.selectedSheet._styledCells[cellIndex]));
                                        delete this.selectedSheet._styledCells[cellIndex];
                                    }
                                    else {
                                        delete this.selectedSheet._styledCells[newCellIndex];
                                    }
                                }
                            }
                        }
                    }
                    else {
                        if (this._draggingColumn) {
                            draggingRange = this._draggingCells.rightCol - this._draggingCells.leftCol + 1;
                            for (colIndex = this._draggingCells.rightCol + 1; colIndex <= this._dropRange.rightCol; colIndex++) {
                                for (rowIndex = 0; rowIndex < this.rows.length; rowIndex++) {
                                    cellIndex = rowIndex * this.columns.length + colIndex;
                                    newCellIndex = rowIndex * this.columns.length + colIndex - draggingRange;
                                    if (this.selectedSheet._styledCells[cellIndex]) {
                                        this.selectedSheet._styledCells[newCellIndex] = JSON.parse(JSON.stringify(this.selectedSheet._styledCells[cellIndex]));
                                        delete this.selectedSheet._styledCells[cellIndex];
                                    }
                                    else {
                                        delete this.selectedSheet._styledCells[newCellIndex];
                                    }
                                }
                            }
                        }
                        else if (this._draggingRow) {
                            draggingRange = this._draggingCells.bottomRow - this._draggingCells.topRow + 1;
                            for (rowIndex = this._draggingCells.bottomRow + 1; rowIndex <= this._dropRange.bottomRow; rowIndex++) {
                                for (colIndex = 0; colIndex < this.columns.length; colIndex++) {
                                    cellIndex = rowIndex * this.columns.length + colIndex;
                                    newCellIndex = (rowIndex - draggingRange) * this.columns.length + colIndex;
                                    if (this.selectedSheet._styledCells[cellIndex]) {
                                        this.selectedSheet._styledCells[newCellIndex] = JSON.parse(JSON.stringify(this.selectedSheet._styledCells[cellIndex]));
                                        delete this.selectedSheet._styledCells[cellIndex];
                                    }
                                    else {
                                        delete this.selectedSheet._styledCells[newCellIndex];
                                    }
                                }
                            }
                        }
                    }
                    // Set the stored the style of the source cells to the destination cells.
                    for (rowIndex = this._dropRange.topRow; rowIndex <= this._dropRange.bottomRow; rowIndex++) {
                        for (colIndex = this._dropRange.leftCol; colIndex <= this._dropRange.rightCol; colIndex++) {
                            cellIndex = rowIndex * this.columns.length + colIndex;
                            if (srcCellStyles[index]) {
                                this.selectedSheet._styledCells[cellIndex] = srcCellStyles[index];
                            }
                            else {
                                delete this.selectedSheet._styledCells[cellIndex];
                            }
                            index++;
                        }
                    }
                };
                // Check whether the specific cell range contains merged cells.
                FlexSheet.prototype._containsMergedCells = function (rng) {
                    var rowIndex, colIndex, cellIndex, mergedRange;
                    if (!this.selectedSheet) {
                        return false;
                    }
                    for (rowIndex = rng.topRow; rowIndex <= rng.bottomRow; rowIndex++) {
                        for (colIndex = rng.leftCol; colIndex <= rng.rightCol; colIndex++) {
                            cellIndex = rowIndex * this.columns.length + colIndex;
                            mergedRange = this.selectedSheet._mergedRanges[cellIndex];
                            if (mergedRange && mergedRange.isValid && !mergedRange.isSingleCell) {
                                return true;
                            }
                        }
                    }
                    return false;
                };
                // Multiple select columns processing.
                FlexSheet.prototype._multiSelectColumns = function (ht) {
                    var range;
                    if (ht && this._columnHeaderClicked) {
                        range = new grid_1.CellRange(ht.row, ht.col);
                        range.row = !!this.selectedSheet.itemsSource ? 1 : 0;
                        range.row2 = this.rows.length - 1;
                        range.col2 = this.selection.col2;
                        this.select(range);
                    }
                };
                // Gets the absolute offset for the element.
                FlexSheet.prototype._cumulativeOffset = function (element) {
                    var top = 0, left = 0;
                    do {
                        top += element.offsetTop || 0;
                        left += element.offsetLeft || 0;
                        element = element.offsetParent;
                    } while (element);
                    return new wijmo.Point(left, top);
                };
                // Gets the absolute scroll offset for the element.
                FlexSheet.prototype._cumulativeScrollOffset = function (element) {
                    var scrollTop = 0, scrollLeft = 0;
                    do {
                        scrollTop += element.scrollTop || 0;
                        scrollLeft += element.scrollLeft || 0;
                        element = element.offsetParent;
                    } while (element && !(element instanceof HTMLBodyElement));
                    // Chrome and Safari always use document.body.scrollTop, 
                    // while IE and Firefox use document.body.scrollTop for quirks mode and document.documentElement.scrollTop for standard mode. 
                    // So we need check both the document.body.scrollTop and document.documentElement.scrollTop (TFS 142679)
                    scrollTop += document.body.scrollTop || document.documentElement.scrollTop;
                    scrollLeft += document.body.scrollLeft || document.documentElement.scrollLeft;
                    return new wijmo.Point(scrollLeft, scrollTop);
                };
                // Check whether current hit is within current selection.
                FlexSheet.prototype._checkHitWithinSelection = function (ht) {
                    var cellIndex, mergedRange;
                    if (ht != null && ht.cellType === grid_1.CellType.Cell) {
                        mergedRange = this.getMergedRange(this.cells, ht.row, ht.col);
                        if (mergedRange && mergedRange.contains(this.selection)) {
                            return true;
                        }
                        if (this.selection.row === ht.row && this.selection.col === ht.col) {
                            return true;
                        }
                    }
                    return false;
                };
                // Clear the merged cells, styled cells and selection for the empty sheet.
                FlexSheet.prototype._clearForEmptySheet = function (rowsOrColumns) {
                    if (this.selectedSheet && this[rowsOrColumns].length === 0 && this._isCopying !== true && this._isUndoing !== true) {
                        this.selectedSheet._mergedRanges = null;
                        this.selectedSheet._styledCells = null;
                        this.select(new grid_1.CellRange());
                    }
                };
                // Check whether the specified cell range contains Group Row.
                FlexSheet.prototype._containsGroupRows = function (cellRange) {
                    var rowIndex, row;
                    for (rowIndex = cellRange.topRow; rowIndex <= cellRange.bottomRow; rowIndex++) {
                        row = this.rows[rowIndex];
                        if (row instanceof grid_1.GroupRow) {
                            return true;
                        }
                    }
                    return false;
                };
                // Delete the content of the selected cells.
                FlexSheet.prototype._delSeletionContent = function (evt) {
                    var selections = this.selectedSheet.selectionRanges.slice(), selection, evtRange, index, colIndex, rowIndex, tableIndex, tableNames, tableName, table, bcol, contentDeleted = false, e, delAction = new sheet_1._EditAction(this);
                    if (this.isReadOnly) {
                        return;
                    }
                    if (this.allowDelete) {
                        if (this.selection.isValid && this.selection.leftCol === 0 && this.selection.rightCol === this.columns.length - 1) {
                            this.deleteRows(this.selection.topRow, this.selection.rowSpan);
                            return;
                        }
                    }
                    this.beginUpdate();
                    if (this.selectedSheet.tableNames && this.selectedSheet.tableNames.length > 0) {
                        tableNames = this.selectedSheet.tableNames.slice();
                    }
                    if (selections == null || selections.length === 0) {
                        selections = [this.selection];
                    }
                    for (index = 0; index < selections.length; index++) {
                        selection = selections[index];
                        evtRange = new grid_1.CellRange();
                        e = new grid_1.CellEditEndingEventArgs(this.cells, evtRange, evt);
                        if (tableNames) {
                            for (tableIndex = 0; tableIndex < tableNames.length; tableIndex++) {
                                tableName = tableNames[tableIndex];
                                table = this._getTable(tableName);
                                if (table) {
                                    if (selection.contains(table.range)) {
                                        delAction._storeDeletedTables(table);
                                        this.tables.remove(table);
                                        this.selectedSheet.tableNames.splice(this.selectedSheet.tableNames.indexOf(tableName), 1);
                                    }
                                }
                            }
                        }
                        for (rowIndex = selection.topRow; rowIndex <= selection.bottomRow; rowIndex++) {
                            if (this.rows[rowIndex] && !this.rows[rowIndex].isReadOnly) {
                                for (colIndex = selection.leftCol; colIndex <= selection.rightCol; colIndex++) {
                                    bcol = this._getBindingColumn(this.cells, rowIndex, this.columns[colIndex]);
                                    if (!bcol.isReadOnly && bcol.isRequired === false || (bcol.isRequired == null && bcol.dataType == wijmo.DataType.String)) {
                                        if (this.getCellData(rowIndex, colIndex, true)) {
                                            evtRange.setRange(rowIndex, colIndex);
                                            e.cancel = false;
                                            if (this.onBeginningEdit(e)) {
                                                this.setCellData(rowIndex, colIndex, '', true);
                                                contentDeleted = true;
                                                this.onCellEditEnding(e);
                                                this.onCellEditEnded(e);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (contentDeleted) {
                        delAction.saveNewState();
                        this._undoStack._addAction(delAction);
                    }
                    this.endUpdate();
                };
                // Update the affected formulas for inserting/removing row/columns.
                FlexSheet.prototype._updateAffectedFormula = function (index, count, isAdding, isRow) {
                    var sheetIndex, sheet, grid, rowIndex, colIndex, newRowIndex, newColIndex, cellData, updatedCellData, oldFormulas = [], newFormulas = [], currentSel = this.selection.clone();
                    this.selectedSheet._storeRowSettings();
                    this.beginUpdate();
                    for (sheetIndex = 0; sheetIndex < this.sheets.length; sheetIndex++) {
                        sheet = this.sheets[sheetIndex];
                        grid = sheet.grid;
                        for (rowIndex = 0; rowIndex < grid.rows.length; rowIndex++) {
                            for (colIndex = 0; colIndex < grid.columns.length; colIndex++) {
                                cellData = grid.getCellData(rowIndex, colIndex, false);
                                if (!!cellData && wijmo.isString(cellData) && cellData[0] === '=') {
                                    updatedCellData = this._updateCellRef(cellData, sheetIndex, index, count, isAdding, isRow);
                                    if (updatedCellData) {
                                        oldFormulas.push({
                                            sheet: sheet,
                                            point: new wijmo.Point(rowIndex, colIndex),
                                            formula: cellData
                                        });
                                        newRowIndex = rowIndex;
                                        newColIndex = colIndex;
                                        if (sheetIndex === this.selectedSheetIndex) {
                                            if (isRow) {
                                                if (rowIndex >= index) {
                                                    if (isAdding) {
                                                        newRowIndex += count;
                                                    }
                                                    else {
                                                        newRowIndex -= count;
                                                    }
                                                }
                                            }
                                            else {
                                                if (colIndex >= index) {
                                                    if (isAdding) {
                                                        newColIndex += count;
                                                    }
                                                    else {
                                                        newColIndex -= count;
                                                    }
                                                }
                                            }
                                            if (!isAdding) {
                                                if ((isRow && rowIndex <= index && rowIndex >= index - count + 1) ||
                                                    (!isRow && colIndex <= index && colIndex >= index - count + 1)) {
                                                    continue;
                                                }
                                            }
                                        }
                                        grid.setCellData(rowIndex, colIndex, updatedCellData);
                                        newFormulas.push({
                                            sheet: sheet,
                                            point: new wijmo.Point(newRowIndex, newColIndex),
                                            formula: updatedCellData
                                        });
                                    }
                                }
                            }
                        }
                    }
                    this.selection = currentSel;
                    this.endUpdate();
                    return {
                        oldFormulas: oldFormulas,
                        newFormulas: newFormulas
                    };
                };
                // Update the affected NamedRanges for inserting/removing row/columns.
                FlexSheet.prototype._updateAffectedNamedRanges = function (index, count, isAdding, isRow) {
                    var nameIndex, definedName, definedNameVal, updatedDefinedNameVal, oldDefinedNameVals = [], newDefinedNameVals = [];
                    for (nameIndex = 0; nameIndex < this.definedNames.length; nameIndex++) {
                        definedName = this.definedNames[nameIndex];
                        definedNameVal = definedName.value;
                        if (!!definedNameVal && wijmo.isString(definedNameVal)) {
                            updatedDefinedNameVal = this._updateCellRef(definedNameVal, this.selectedSheetIndex, index, count, isAdding, isRow);
                            if (updatedDefinedNameVal) {
                                oldDefinedNameVals.push({
                                    name: definedName.name,
                                    value: definedNameVal
                                });
                                definedName.value = updatedDefinedNameVal;
                                newDefinedNameVals.push({
                                    name: definedName.name,
                                    value: updatedDefinedNameVal
                                });
                            }
                        }
                    }
                    return {
                        oldDefinedNameVals: oldDefinedNameVals,
                        newDefinedNameVals: newDefinedNameVals
                    };
                };
                // Update the column filter for moving the column. 
                FlexSheet.prototype._updateColumnFiler = function (srcColIndex, descColIndex) {
                    var filterDef = JSON.parse(this._filter.filterDefinition);
                    for (var i = 0; i < filterDef.filters.length; i++) {
                        var filter = filterDef.filters[i];
                        if (filter.columnIndex === srcColIndex) {
                            filter.columnIndex = descColIndex;
                            break;
                        }
                    }
                    this._filter.filterDefinition = JSON.stringify(filterDef);
                };
                // Chech the specific element is the child of other element.
                FlexSheet.prototype._isDescendant = function (paranet, child) {
                    var node = child.parentNode;
                    while (node != null) {
                        if (node === paranet) {
                            return true;
                        }
                        node = node.parentNode;
                    }
                    return false;
                };
                // Clear the expression cache of the CalcEngine.
                FlexSheet.prototype._clearCalcEngine = function () {
                    this._calcEngine._clearExpressionCache();
                };
                // Get string of the given cell ranges and sheet.
                FlexSheet.prototype._getRangeString = function (ranges, sheet, isGetCellValue) {
                    if (isGetCellValue === void 0) { isGetCellValue = true; }
                    var clipString = '', rowIndex, selIndex, firstRow = true, firstCell, sel, cell, rng, flex = sheet.grid;
                    if (wijmo.isArray(ranges) && ranges.length > 1) {
                        if (this._isMultipleRowsSelected(ranges, sheet)) {
                            clipString = '';
                            for (selIndex = 0; selIndex < ranges.length; selIndex++) {
                                if (clipString) {
                                    clipString += '\n';
                                }
                                clipString += this._getRangeString(ranges[selIndex], sheet);
                            }
                            return clipString;
                        }
                        else if (this._isMultipleColumnsSelected(ranges, sheet)) {
                            clipString = '';
                            for (rowIndex = 0, firstRow = true; rowIndex < flex.rows.length; rowIndex++) {
                                if (!firstRow) {
                                    clipString += '\n';
                                }
                                firstRow = false;
                                for (selIndex = 0, firstCell = true; selIndex < ranges.length; selIndex++) {
                                    sel = ranges[selIndex].clone();
                                    sel.row = sel.row2 = rowIndex;
                                    if (!firstCell) {
                                        clipString += '\t';
                                    }
                                    firstCell = false;
                                    clipString += this._getRangeString(ranges[selIndex], sheet);
                                }
                                return clipString;
                            }
                        }
                        else {
                            rng = ranges[0];
                            switch (this.selectionMode) {
                                // row modes: expand range to cover all columns
                                case grid_1.SelectionMode.Row:
                                case grid_1.SelectionMode.RowRange:
                                    rng.col = 0;
                                    rng.col2 = flex.columns.length - 1;
                                    return this._getRangeString(rng, sheet);
                                // ListBox mode: scan rows and copy selected ones
                                case grid_1.SelectionMode.ListBox:
                                    rng.col = 0;
                                    rng.col2 = flex.columns.length - 1;
                                    for (var i = 0; i < flex.rows.length; i++) {
                                        if (flex.rows[i].isSelected && flex.rows[i].isVisible) {
                                            rng.row = rng.row2 = i;
                                            if (clipString)
                                                clipString += '\n';
                                            clipString += this._getRangeString(rng, sheet);
                                        }
                                    }
                                    return clipString;
                            }
                        }
                    }
                    // scan rows
                    rng = wijmo.asType(wijmo.isArray(ranges) ? ranges[0] : ranges, grid_1.CellRange);
                    for (var r = rng.topRow; r <= rng.bottomRow; r++) {
                        // skip invisible, add separator
                        if (!(flex.rows[r] && flex.rows[r].isVisible))
                            continue;
                        if (!firstRow)
                            clipString += '\n';
                        firstRow = false;
                        // scan cells
                        for (var c = rng.leftCol, firstCell = true; c <= rng.rightCol; c++) {
                            // skip invisible, add separator
                            if (!(flex.columns[c] && flex.columns[c].isVisible))
                                continue;
                            if (!firstCell)
                                clipString += '\t';
                            firstCell = false;
                            // append cell
                            if (isGetCellValue) {
                                cell = flex.getCellData(r, c, true).toString();
                                if (cell && cell[0] === '=') {
                                    var cellIndex = r * flex.columns.length + c;
                                    var styleInfo = sheet._styledCells[cellIndex];
                                    var format = styleInfo ? styleInfo.format : '';
                                    var col = flex.columns[c];
                                    cell = this.evaluate(cell, format, sheet);
                                    cell = this._formatEvaluatedResult(cell, col, format);
                                    cell = cell == null ? '' : cell;
                                }
                            }
                            else {
                                cell = flex.getCellData(r, c, true).toString();
                            }
                            cell = cell.replace(/\t/g, ' '); // handle tabs
                            if (cell.indexOf('\n') > -1) {
                                cell = '"' + cell.replace(/"/g, '""') + '"';
                            }
                            clipString += cell;
                        }
                    }
                    // done
                    return clipString;
                };
                // Check whether the cell ranges contains formula cells.
                FlexSheet.prototype._containsRandFormula = function (ranges, sheet) {
                    for (var i = 0; i < ranges.length; i++) {
                        var rng = ranges[i];
                        for (var rowIndex = rng.topRow; rowIndex <= rng.bottomRow && rowIndex < sheet.grid.rows.length; rowIndex++) {
                            for (var colIndex = rng.leftCol; colIndex <= rng.rightCol && colIndex < sheet.grid.columns.length; colIndex++) {
                                var cellData = sheet.grid.getCellData(rowIndex, colIndex, false);
                                if (wijmo.isString(cellData) && cellData[0] === '=' && cellData.search(/rand/i) !== -1) {
                                    return true;
                                }
                            }
                        }
                    }
                    return false;
                };
                // Check current selections of the FlexSheet are multiple rows.
                FlexSheet.prototype._isMultipleRowsSelected = function (ranges, sheet) {
                    var sel, selections;
                    if (ranges && ranges.length > 0) {
                        selections = ranges;
                    }
                    else if (this.selectedSheet.selectionRanges.length > 0) {
                        selections = this.selectedSheet.selectionRanges;
                    }
                    else {
                        selections = [this.selection];
                    }
                    for (var i = 0; i < selections.length; i++) {
                        sel = selections[i];
                        if (sheet) {
                            if (sel.leftCol !== 0 || sel.rightCol !== sheet.grid.columns.length - 1) {
                                return false;
                            }
                        }
                        else {
                            if (sel.leftCol !== 0 || sel.rightCol !== this.columns.length - 1) {
                                return false;
                            }
                        }
                    }
                    return true;
                };
                // Check current selections of the FlexSheet are multiple columns.
                FlexSheet.prototype._isMultipleColumnsSelected = function (ranges, sheet) {
                    var sel, selections;
                    if (ranges && ranges.length > 0) {
                        selections = ranges;
                    }
                    else if (this.selectedSheet.selectionRanges.length > 0) {
                        selections = this.selectedSheet.selectionRanges;
                    }
                    else {
                        selections = [this.selection];
                    }
                    for (var i = 0; i < selections.length; i++) {
                        sel = selections[i];
                        if (sheet) {
                            if (sel.bottomRow !== sheet.grid.rows.length - 1) {
                                return false;
                            }
                            if (!sheet.grid.itemsSource && sel.topRow !== 0) {
                                return false;
                            }
                            if (!!sheet.grid.itemsSource && sel.topRow !== 1) {
                                return false;
                            }
                        }
                        else {
                            if (sel.bottomRow !== this.rows.length - 1) {
                                return false;
                            }
                            if (!this.selectedSheet.itemsSource && sel.topRow !== 0) {
                                return false;
                            }
                            if (!!this.selectedSheet.itemsSource && sel.topRow !== 1) {
                                return false;
                            }
                        }
                    }
                    return true;
                };
                // Post processing for setting clip string in FlexSheet.
                FlexSheet.prototype._postSetClipStringProcess = function (cellData, row, col, copiedRow, copiedCol) {
                    var megredCell, rowSpan, colSpan, e, pasted = false, match;
                    if (copiedRow >= 0 && copiedCol >= 0) {
                        megredCell = this.getMergedRange(this.cells, copiedRow, copiedCol);
                        if (!!megredCell && megredCell.topRow === copiedRow && megredCell.leftCol === copiedCol) {
                            rowSpan = row + megredCell.rowSpan - 1;
                            rowSpan = rowSpan < this.rows.length ? rowSpan : this.rows.length - 1;
                            colSpan = col + megredCell.columnSpan - 1;
                            colSpan = colSpan < this.columns.length ? colSpan : this.columns.length - 1;
                            this.mergeRange(new grid_1.CellRange(row, col, rowSpan, colSpan), true);
                        }
                    }
                    // raise events so user can cancel the paste
                    e = new grid_1.CellRangeEventArgs(this.cells, new grid_1.CellRange(row, col), cellData);
                    if (this.onPastingCell(e)) {
                        if (this.cells.setCellData(row, col, e.data)) {
                            match = cellData.match(/\n/g);
                            if (match && match.length > 0) {
                                this._applyStyleForCell(row, col, { whiteSpace: 'pre' });
                                this.rows[row].height = this.rows.defaultSize * (match.length + 1);
                            }
                            this.onPastedCell(e);
                            pasted = true;
                        }
                    }
                    return pasted;
                };
                // Delete the cut data.
                FlexSheet.prototype._delCutData = function () {
                    var row, col, bcol, copySel = this._copiedRanges[0], cutSource = this._copiedSheet === this.selectedSheet ? this : this._copiedSheet.grid;
                    for (row = copySel.topRow; row <= copySel.bottomRow; row++) {
                        if (cutSource.rows[row] == null) {
                            continue;
                        }
                        for (col = copySel.leftCol; col <= copySel.rightCol; col++) {
                            if (this._copiedSheet !== this.selectedSheet || row < this.selection.topRow || row > this.selection.bottomRow || col < this.selection.leftCol || col > this.selection.rightCol) {
                                bcol = cutSource._getBindingColumn(cutSource.cells, row, cutSource.columns[col]);
                                if (bcol.isRequired == false || (bcol.isRequired == null && bcol.dataType == wijmo.DataType.String)) {
                                    if (cutSource.getCellData(row, col, true)) {
                                        cutSource.setCellData(row, col, '', true);
                                    }
                                }
                            }
                        }
                    }
                };
                // Check whether the pasted texts contains multi-line text.
                FlexSheet.prototype._containsMultiLineText = function (rows) {
                    for (var i = 0; i < rows.length; i++) {
                        var row = rows[i];
                        for (var j = 0; j < row.length; j++) {
                            if (row[j].indexOf('\n') >= 0) {
                                return true;
                            }
                        }
                    }
                    return false;
                };
                // Sort the selections by row.
                FlexSheet.prototype._sortByRow = function (sel1, sel2) {
                    if (sel1.topRow > sel2.topRow) {
                        return 1;
                    }
                    else if (sel1.topRow < sel2.topRow) {
                        return -1;
                    }
                    else {
                        return 0;
                    }
                };
                // Sort the selections by column.
                FlexSheet.prototype._sortByColumn = function (sel1, sel2) {
                    if (sel1.leftCol > sel2.leftCol) {
                        return 1;
                    }
                    else if (sel1.leftCol < sel2.leftCol) {
                        return -1;
                    }
                    else {
                        return 0;
                    }
                };
                // Set all the rows and columns to dirty for updating
                FlexSheet.prototype._setFlexSheetToDirty = function () {
                    this.columns._dirty = true;
                    this.rows._dirty = true;
                    this.rowHeaders.columns._dirty = true;
                    this.rowHeaders.rows._dirty = true;
                    this.columnHeaders.columns._dirty = true;
                    this.columnHeaders.rows._dirty = true;
                };
                /**
                 * Converts the number value to its corresponding alpha value.
                 * For instance: 0, 1, 2...to a, b, c...
                 * @param c The number value need to be converted.
                 */
                FlexSheet.convertNumberToAlpha = function (c) {
                    var content = '', dCount, pos;
                    if (c >= 0) {
                        do {
                            dCount = Math.floor(c / 26);
                            pos = c % 26;
                            content = String.fromCharCode(pos + 65) + content;
                            c = dCount - 1;
                        } while (dCount);
                    }
                    return content;
                };
                // update the formula of the row after reordering the row.
                FlexSheet.prototype._updateFormulaForReorderingRows = function (srcRow, dstRow) {
                    var distance = dstRow - srcRow, cellData, matches, cellRef, updatedCellRef, cellAddress, updatedRow;
                    this.beginUpdate();
                    for (var i = 0; i < this.columns.length; i++) {
                        cellData = this.getCellData(dstRow, i, false);
                        if (!!cellData && typeof cellData === 'string' && cellData[0] === '=') {
                            matches = cellData.match(/(?=\b\D)\$?[A-Za-z]{1,2}\$?\d+/g);
                            if (!!matches && matches.length > 0) {
                                for (var cellRefIndex = 0; cellRefIndex < matches.length; cellRefIndex++) {
                                    cellRef = matches[cellRefIndex];
                                    cellAddress = wijmo.xlsx.Workbook.tableAddress(cellRef);
                                    updatedRow = cellAddress.row + distance;
                                    if (updatedRow < 0) {
                                        updatedRow = 0;
                                    }
                                    else if (updatedRow >= this.rows.length) {
                                        updatedRow = this.rows.length - 1;
                                    }
                                    cellAddress.row = updatedRow;
                                    updatedCellRef = wijmo.xlsx.Workbook.xlsxAddress(cellAddress.row, cellAddress.col, cellAddress.absRow, cellAddress.absCol);
                                    cellData = cellData.replace(cellRef, updatedCellRef);
                                }
                                this.setCellData(dstRow, i, cellData);
                            }
                        }
                    }
                    this.endUpdate();
                };
                // update the formulas for drag & drop rows or columns.
                FlexSheet.prototype._updateFormulaForDropping = function (isChangePos) {
                    var oldFormulas = [], newFormulas = [], sheet, grid, sheetIndex, rowIndex, row, colIndex, column, cellData, updatedCellData;
                    this.beginUpdate();
                    for (sheetIndex = 0; sheetIndex < this.sheets.length; sheetIndex++) {
                        sheet = this.sheets[sheetIndex];
                        grid = sheet.grid;
                        for (rowIndex = 0; rowIndex < grid.rows.length; rowIndex++) {
                            for (colIndex = 0; colIndex < grid.columns.length; colIndex++) {
                                cellData = grid.getCellData(rowIndex, colIndex, false);
                                if (!!cellData && typeof cellData === 'string' && cellData[0] === '=') {
                                    updatedCellData = this._updateCellRefForDropping(cellData, sheetIndex);
                                    if (updatedCellData) {
                                        grid.setCellData(rowIndex, colIndex, updatedCellData);
                                        if (isChangePos && sheetIndex === this.selectedSheetIndex) {
                                            row = grid.rows[rowIndex];
                                            column = grid.columns[colIndex];
                                            oldFormulas.push({
                                                sheet: sheet,
                                                row: row,
                                                column: column,
                                                formula: cellData
                                            });
                                            newFormulas.push({
                                                sheet: sheet,
                                                row: row,
                                                column: column,
                                                formula: updatedCellData
                                            });
                                        }
                                        else {
                                            oldFormulas.push({
                                                sheet: sheet,
                                                point: new wijmo.Point(rowIndex, colIndex),
                                                formula: cellData
                                            });
                                            newFormulas.push({
                                                sheet: sheet,
                                                point: new wijmo.Point(rowIndex, colIndex),
                                                formula: updatedCellData
                                            });
                                        }
                                    }
                                }
                            }
                        }
                    }
                    this.endUpdate();
                    return {
                        oldFormulas: oldFormulas,
                        newFormulas: newFormulas
                    };
                };
                // Update the affected NamedRanges for drag & drop rows or columns.
                FlexSheet.prototype._updateNamedRangesForDropping = function () {
                    var nameIndex, definedName, definedNameVal, updatedDefinedNameVal, oldDefinedNameVals = [], newDefinedNameVals = [];
                    for (nameIndex = 0; nameIndex < this.definedNames.length; nameIndex++) {
                        definedName = this.definedNames[nameIndex];
                        definedNameVal = definedName.value;
                        if (!!definedNameVal && wijmo.isString(definedNameVal)) {
                            updatedDefinedNameVal = this._updateCellRefForDropping(definedNameVal, this.selectedSheetIndex);
                            if (updatedDefinedNameVal) {
                                oldDefinedNameVals.push({
                                    name: definedName.name,
                                    value: definedNameVal
                                });
                                definedName.value = updatedDefinedNameVal;
                                newDefinedNameVals.push({
                                    name: definedName.name,
                                    value: updatedDefinedNameVal
                                });
                            }
                        }
                    }
                    return {
                        oldDefinedNameVals: oldDefinedNameVals,
                        newDefinedNameVals: newDefinedNameVals
                    };
                };
                // Update cell reference for drag & drop rows or columns.
                FlexSheet.prototype._updateCellRefForDropping = function (cellData, sheetIndex) {
                    var updatedCellData, distance, matches, cellRef, cellRefIndex, cellRefMatchIndex, cellRefs, cellRef1, cellRef2, sheetRefIndex, sheetRef1, sheetRef2, cellRange, updatedCellRef, cellAddress1, cellAddress2;
                    // Match the cell range paramter of the formula.  i.e. 'A1:B1'
                    matches = cellData.match(/((\w+)\!)?\$?[A-Za-z]{1,2}\$?\d+:((\w+)\!)?\$?[A-Za-z]{1,2}\$?\d+/g);
                    // If there is no cell range parameter, we will match the single cell paramter. i.e. 'A1'
                    if (!matches || matches.length === 0) {
                        matches = cellData.match(/((\w+)\!)?\$?[A-Za-z]{1,2}\$?\d+/g);
                    }
                    if (!!matches && matches.length > 0) {
                        for (cellRefIndex = 0; cellRefIndex < matches.length; cellRefIndex++) {
                            sheetRef1 = null;
                            cellRef1 = null;
                            cellRef2 = null;
                            cellRange = null;
                            cellAddress1 = null;
                            cellAddress2 = null;
                            cellRef = matches[cellRefIndex];
                            if (cellRef.indexOf(':') > 0) {
                                cellRefs = cellRef.split(':');
                                cellRef1 = cellRefs[0];
                                cellRef2 = cellRefs[1];
                                sheetRefIndex = cellRef1.indexOf('!');
                                if (sheetRefIndex >= 0) {
                                    sheetRef1 = cellRef1.substring(0, sheetRefIndex);
                                    cellRef1 = cellRef1.substring(sheetRefIndex + 1);
                                }
                                if (sheetIndex === this.selectedSheetIndex) {
                                    if (sheetRef1 && sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                else {
                                    if (!sheetRef1 || sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                sheetRefIndex = cellRef1.indexOf('!');
                                if (sheetRefIndex >= 0) {
                                    sheetRef2 = cellRef1.substring(0, sheetRefIndex);
                                    cellRef2 = cellRef1.substring(sheetRefIndex + 1);
                                }
                                cellAddress1 = wijmo.xlsx.Workbook.tableAddress(cellRef1);
                                cellRange = new grid_1.CellRange(cellAddress1.row, cellAddress1.col);
                                cellAddress2 = wijmo.xlsx.Workbook.tableAddress(cellRef2);
                                cellRange.row2 = cellAddress2.row;
                                cellRange.col2 = cellAddress2.col;
                            }
                            else {
                                sheetRefIndex = cellRef.indexOf('!');
                                if (sheetRefIndex >= 0) {
                                    sheetRef1 = cellRef.substring(0, sheetRefIndex);
                                    cellRef1 = cellRef.substring(sheetRefIndex + 1);
                                }
                                else {
                                    cellRefMatchIndex = cellData.indexOf(cellRef);
                                    if (cellRefMatchIndex > 0 && /[\d\w]/.test(cellData[cellRefMatchIndex - 1])) {
                                        continue;
                                    }
                                    cellRef1 = cellRef;
                                }
                                if (sheetIndex === this.selectedSheetIndex) {
                                    if (sheetRef1 && sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                else {
                                    if (!sheetRef1 || sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                cellAddress1 = wijmo.xlsx.Workbook.tableAddress(cellRef1);
                                cellRange = new grid_1.CellRange(cellAddress1.row, cellAddress1.col);
                            }
                            if (cellRange && this._draggingCells.contains(cellRange)) {
                                distance = this._dropRange.leftCol - this._draggingCells.leftCol;
                                if (distance !== 0) {
                                    cellRange.col += cellAddress1.absCol ? 0 : distance;
                                    cellRange.col2 += cellAddress2 ? (cellAddress2.absCol ? 0 : distance) : (cellAddress1.absCol ? 0 : distance);
                                }
                                distance = this._dropRange.topRow - this._draggingCells.topRow;
                                if (distance !== 0) {
                                    cellRange.row += cellAddress1.absRow ? 0 : distance;
                                    ;
                                    cellRange.row2 += cellAddress2 ? (cellAddress2.absRow ? 0 : distance) : (cellAddress1.absRow ? 0 : distance);
                                    ;
                                }
                                if (updatedCellData == null) {
                                    updatedCellData = cellData;
                                }
                                if (!cellAddress2) {
                                    updatedCellRef = sheetRef1 ? sheetRef1 + '!' : '';
                                    updatedCellRef += wijmo.xlsx.Workbook.xlsxAddress(cellRange.row, cellRange.col, cellAddress1.absRow, cellAddress1.absCol);
                                }
                                else {
                                    updatedCellRef = sheetRef1 ? sheetRef1 + '!' : '';
                                    updatedCellRef += wijmo.xlsx.Workbook.xlsxAddress(cellRange.row, cellRange.col, cellAddress1.absRow, cellAddress1.absCol) + ':';
                                    updatedCellRef += (sheetRef2 ? sheetRef2 + '!' : '') + wijmo.xlsx.Workbook.xlsxAddress(cellRange.row2, cellRange.col2, cellAddress2.absRow, cellAddress2.absCol);
                                }
                                updatedCellData = updatedCellData.replace(cellRef, updatedCellRef);
                            }
                        }
                    }
                    return updatedCellData;
                };
                // Scan the formulas of current sheet.
                FlexSheet.prototype._scanFormulas = function () {
                    var formulas = [];
                    for (var i = 0; i < this.rows.length; i++) {
                        for (var j = 0; j < this.columns.length; j++) {
                            var data = this.getCellData(i, j, false);
                            if (data && wijmo.isString(data) && data[0] === '=') {
                                formulas.push({
                                    row: i,
                                    column: j,
                                    formula: data
                                });
                            }
                        }
                    }
                    return formulas;
                };
                // Reset the formulas for current sheet.
                FlexSheet.prototype._resetFormulas = function (formulas) {
                    var self = this;
                    if (!formulas) {
                        return;
                    }
                    self.deferUpdate(function () {
                        for (var i = 0; i < formulas.length; i++) {
                            var item = formulas[i];
                            self.setCellData(item.row, item.column, item.formula);
                        }
                    });
                };
                // Get the cell style in selected sheet.
                FlexSheet.prototype._getCellStyle = function (rowIndex, colIndex, sheet) {
                    var sheet = sheet || this.selectedSheet, cellIndex;
                    if (!sheet) {
                        return null;
                    }
                    cellIndex = rowIndex * sheet.grid.columns.length + colIndex;
                    return sheet._styledCells[cellIndex];
                };
                // Validate the sheet name of the defined name item.
                FlexSheet.prototype._validateSheetName = function (sheetName) {
                    for (var i = 0; i < this.sheets.length; i++) {
                        if (this.sheets[i].name === sheetName) {
                            return true;
                        }
                    }
                    return false;
                };
                // Check whether the deined name already existed.
                FlexSheet.prototype._checkExistDefinedName = function (name, sheetName, ignoreIndex) {
                    if (ignoreIndex === void 0) { ignoreIndex = -1; }
                    for (var i = 0; i < this.definedNames.length; i++) {
                        if (this.definedNames[i].name === name && this.definedNames[i].sheetName === sheetName && i !== ignoreIndex) {
                            return true;
                        }
                    }
                    return false;
                };
                // Update the defiend name item with the sheet name changing.
                FlexSheet.prototype._updateDefinedNameWithSheetRefUpdating = function (oldSheetName, newSheetName) {
                    var definedName, match, cellRef, sheetRef;
                    for (var i = 0; i < this.definedNames.length; i++) {
                        definedName = this.definedNames[i];
                        // Update the sheet name of the defined name item.
                        if (definedName.sheetName === oldSheetName && definedName.sheetName != null) {
                            definedName._sheetName = newSheetName;
                        }
                        // Update the sheet reference of the value of the defined name item.
                        match = definedName.value.match(/(\w+)\!\$?[A-Za-z]+\$?\d+/g);
                        if (match && match.length > 0) {
                            for (var j = 0; j < match.length; j++) {
                                cellRef = match[j];
                                sheetRef = cellRef.substring(0, cellRef.indexOf('!'));
                                if (sheetRef === oldSheetName) {
                                    definedName.value = definedName.value.replace(cellRef, cellRef.replace(oldSheetName, newSheetName));
                                }
                            }
                        }
                    }
                };
                // Updated the formulas refer to the defined name or the table via the change of the name of defined name or table.
                FlexSheet.prototype._updateFormulasWithNameUpdating = function (oldName, newName, isTable) {
                    if (isTable === void 0) { isTable = false; }
                    var sheetIndex, rowIndex, colIndex, sheet, grid, cellData, nameIndex, prevChar, folChar, replaceRegEx, currentSel = this.selection.clone(), formulaChanged = false, folCharCheckReg;
                    if (isTable) {
                        folCharCheckReg = /\[/;
                    }
                    else {
                        folCharCheckReg = /\w/;
                    }
                    this.selectedSheet._storeRowSettings();
                    this.beginUpdate();
                    for (sheetIndex = 0; sheetIndex < this.sheets.length; sheetIndex++) {
                        sheet = this.sheets[sheetIndex];
                        grid = sheet.grid;
                        for (rowIndex = 0; rowIndex < grid.rows.length; rowIndex++) {
                            for (colIndex = 0; colIndex < grid.columns.length; colIndex++) {
                                cellData = grid.getCellData(rowIndex, colIndex, false);
                                if (!!cellData && typeof cellData === 'string' && cellData[0] === '=') {
                                    formulaChanged = false;
                                    nameIndex = cellData.indexOf(oldName);
                                    replaceRegEx = new RegExp(oldName, 'g');
                                    while (nameIndex > -1) {
                                        prevChar = '';
                                        folChar = '';
                                        if (nameIndex > 0) {
                                            prevChar = cellData[nameIndex - 1];
                                        }
                                        if (nameIndex + oldName.length < cellData.length) {
                                            folChar = cellData[nameIndex + oldName.length];
                                        }
                                        if (!(/\w/.test(prevChar)) && ((isTable && folCharCheckReg.test(folChar)) || (!isTable && !folCharCheckReg.test(folChar)))) {
                                            cellData = cellData.replace(replaceRegEx, function (match, offset) {
                                                if (offset === nameIndex) {
                                                    return newName;
                                                }
                                                else {
                                                    return oldName;
                                                }
                                            });
                                            formulaChanged = true;
                                        }
                                        nameIndex = cellData.indexOf(oldName, nameIndex + oldName.length);
                                    }
                                    if (formulaChanged) {
                                        grid.setCellData(rowIndex, colIndex, cellData);
                                    }
                                }
                            }
                        }
                    }
                    this.selection = currentSel;
                    this.endUpdate();
                };
                // Update the relate table name for each sheet via the change of the table name.
                FlexSheet.prototype._updateTableNameForSheet = function (oldName, newName) {
                    var sheetIndex, nameIndex, sheet;
                    for (sheetIndex = 0; sheetIndex < this.sheets.length; sheetIndex++) {
                        sheet = this.sheets[sheetIndex];
                        nameIndex = sheet.tableNames.indexOf(oldName);
                        if (nameIndex > -1) {
                            sheet.tableNames[nameIndex] = newName;
                        }
                    }
                };
                // Get the index of the defined name by its name.
                FlexSheet.prototype._getDefinedNameIndexByName = function (name) {
                    var index = 0;
                    for (; index < this.definedNames.length; index++) {
                        if (this.definedNames[index].name === name) {
                            return index;
                        }
                    }
                    return -1;
                };
                // update the table range of current sheet for add\delete rows.
                FlexSheet.prototype._updateTablesForUpdatingRow = function (index, count, isDelete) {
                    var tableIndex, tableName, table, effectIndex, tableNames, deletedTables;
                    tableNames = this.selectedSheet.tableNames.slice();
                    if (tableNames && tableNames.length > 0) {
                        for (tableIndex = 0; tableIndex < tableNames.length; tableIndex++) {
                            tableName = tableNames[tableIndex];
                            table = this._getTable(tableName);
                            if (table) {
                                if (isDelete) {
                                    effectIndex = index + count - 1;
                                    if (effectIndex < table.range.topRow) {
                                        table._updateTableRange(-count, -count, 0, 0);
                                    }
                                    else if (effectIndex >= table.range.topRow && effectIndex <= table.range.bottomRow) {
                                        if (index < table.range.topRow) {
                                            if (table.showHeaderRow) {
                                                table['_showHeaderRow'] = false;
                                            }
                                            table._updateTableRange(index - table.range.topRow, -count, 0, 0);
                                        }
                                        else if (index === table.range.topRow && count === table.range.rowSpan) {
                                            if (deletedTables == null) {
                                                deletedTables = [];
                                            }
                                            deletedTables.push(table);
                                            this.selectedSheet.tableNames.splice(this.selectedSheet.tableNames.indexOf(tableName), 1);
                                            this.tables.remove(table);
                                            continue;
                                        }
                                        else {
                                            if (index === table.range.topRow && table.showHeaderRow) {
                                                table['_showHeaderRow'] = false;
                                            }
                                            if (effectIndex === table.range.bottomRow && table.showTotalRow) {
                                                table['_showTotalRow'] = false;
                                            }
                                            table._updateTableRange(0, -count, 0, 0);
                                        }
                                    }
                                    else {
                                        if (index <= table.range.topRow) {
                                            if (deletedTables == null) {
                                                deletedTables = [];
                                            }
                                            deletedTables.push(table);
                                            this.selectedSheet.tableNames.splice(this.selectedSheet.tableNames.indexOf(tableName), 1);
                                            this.tables.remove(table);
                                        }
                                        else if (index <= table.range.bottomRow) {
                                            if (table.showTotalRow) {
                                                table['_showTotalRow'] = false;
                                            }
                                            table._updateTableRange(0, index - table.range.bottomRow - 1, 0, 0);
                                        }
                                    }
                                }
                                else {
                                    if (index <= table.range.topRow) {
                                        table._updateTableRange(count, count, 0, 0);
                                    }
                                    else if (index > table.range.topRow && index <= table.range.bottomRow) {
                                        table._updateTableRange(0, count, 0, 0);
                                    }
                                }
                            }
                        }
                    }
                    return deletedTables;
                };
                // update the table range of current sheet for add\delete columns.
                FlexSheet.prototype._updateTablesForUpdatingColumn = function (index, count, isDelete) {
                    var tableIndex, tableName, table, effectIndex, effectCount, startIndex, i, tableNames, deletedTables;
                    tableNames = this.selectedSheet.tableNames.slice();
                    if (tableNames && tableNames.length > 0) {
                        for (tableIndex = 0; tableIndex < tableNames.length; tableIndex++) {
                            tableName = tableNames[tableIndex];
                            table = this._getTable(tableName);
                            if (table) {
                                if (isDelete) {
                                    effectIndex = index + count - 1;
                                    if (effectIndex < table.range.leftCol) {
                                        table._updateTableRange(0, 0, -count, -count);
                                    }
                                    else if (effectIndex >= table.range.leftCol && effectIndex <= table.range.rightCol) {
                                        if (index < table.range.leftCol) {
                                            effectCount = count - table.range.leftCol + index;
                                            startIndex = table.range.leftCol;
                                            table._updateTableRange(0, 0, index - table.range.leftCol, -count);
                                        }
                                        else if (index === table.range.leftCol && count === table.range.columnSpan) {
                                            if (deletedTables == null) {
                                                deletedTables = [];
                                            }
                                            deletedTables.push(table);
                                            this.selectedSheet.tableNames.splice(this.selectedSheet.tableNames.indexOf(tableName), 1);
                                            this.tables.remove(table);
                                            continue;
                                        }
                                        else {
                                            effectCount = count;
                                            startIndex = index;
                                            table._updateTableRange(0, 0, 0, -effectCount);
                                        }
                                        table.columns.splice(startIndex - table.range.leftCol, effectCount);
                                    }
                                    else {
                                        if (index <= table.range.leftCol) {
                                            if (deletedTables == null) {
                                                deletedTables = [];
                                            }
                                            deletedTables.push(table);
                                            this.selectedSheet.tableNames.splice(this.selectedSheet.tableNames.indexOf(tableName), 1);
                                            this.tables.remove(table);
                                        }
                                        else if (index <= table.range.rightCol) {
                                            effectCount = table.range.rightCol - index + 1;
                                            table._updateTableRange(0, 0, 0, -effectCount);
                                            table.columns.splice(index, effectCount);
                                        }
                                    }
                                }
                                else {
                                    if (index <= table.range.leftCol) {
                                        table._updateTableRange(0, 0, count, count);
                                    }
                                    else if (index > table.range.leftCol && index <= table.range.rightCol) {
                                        table._updateTableRange(0, 0, 0, count);
                                        startIndex = index - table.range.leftCol;
                                        for (i = 0; i < count; i++) {
                                            table._addColumn(startIndex + i);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    return deletedTables;
                };
                // Check whether disable DeleteRow for flexsheet.
                FlexSheet.prototype._isDisableDeleteRow = function (topRow, bottomRow) {
                    var tableIndex, tableName, table;
                    if (this.selectedSheet.tableNames && this.selectedSheet.tableNames.length > 0) {
                        for (tableIndex = 0; tableIndex < this.selectedSheet.tableNames.length; tableIndex++) {
                            tableName = this.selectedSheet.tableNames[tableIndex];
                            table = this._getTable(tableName);
                            if (table && table.showHeaderRow) {
                                if (table.range.topRow >= topRow && table.range.topRow <= bottomRow) {
                                    return true;
                                }
                            }
                        }
                    }
                    return false;
                };
                // method used in JSON-style initialization
                FlexSheet.prototype._copy = function (key, value) {
                    var headerRow, column;
                    if (key == 'columns') {
                        _super.prototype._copy.call(this, key, value);
                        if (!!this.itemsSource) {
                            headerRow = this.rows[0];
                            if (headerRow instanceof HeaderRow) {
                                headerRow._ubv = null;
                                headerRow._ubv = {};
                                for (var i = 0; i < this.columns.length; i++) {
                                    column = this.columns[i];
                                    headerRow._ubv[column._hash] = column.header;
                                }
                            }
                        }
                        return true;
                    }
                    return false;
                };
                FlexSheet.prototype._getTableSheetIndex = function (tableName) {
                    var sheets = this.sheets;
                    for (var i = 0; i < sheets.length; i++) {
                        if (sheets[i].tableNames.indexOf(tableName) > -1) {
                            return i;
                        }
                    }
                    return -1;
                };
                // Sort converter for FlexSheet, this converter mainly handles to evaluate the formula value.
                FlexSheet.prototype._sheetSortConverter = function (sd, item, value, init) {
                    value = _super.prototype['_sortConverter'].call(this, sd, item, value, init);
                    if (wijmo.isString(value) && value.length > 0 && value[0] === '=') {
                        value = this.evaluate(value);
                        if (!wijmo.isPrimitive(value) && value) {
                            value = value.value;
                        }
                    }
                    return value;
                };
                // Format the evaluated result.
                FlexSheet.prototype._formatEvaluatedResult = function (result, col, format) {
                    if (wijmo.isPrimitive(result)) {
                        if (col.dataMap) {
                            result = col.dataMap.getDisplayValue(result);
                        }
                        if (wijmo.isInt(result) && !col.format && !col.dataMap && !format) {
                            result = result.toString();
                        }
                        else {
                            result = result != null ? wijmo.Globalize.format(result, format || col.format) : '';
                        }
                    }
                    else if (result) {
                        if (wijmo.isInt(result.value) && !col.format && !col.dataMap && !format && !result.format) {
                            result = result.value.toString();
                        }
                        else {
                            result = result.value != null ? wijmo.Globalize.format(result.value, format || result.format || col.format) : '';
                        }
                    }
                    return result;
                };
                // Updated the cell reference of the formula for updating the rows\columns of the FlexSheet.
                FlexSheet.prototype._updateCellRef = function (cellData, sheetIndex, index, count, isAdding, isRow) {
                    var updatedCellData, matches, cellRefIndex, changed, cellRef, cellRefMatchIndex, cellRefMatchIndexes, cellRefs, cellRef1, cellRef2, sheetRefIndex, sheetRef1, sheetRef2, cellRange, updatedCellRef, oldFormulas = [], newFormulas = [], cellAddress1, cellAddress2;
                    // Match the cell range paramter of the formula.  i.e. 'A1:B1'
                    matches = cellData.match(/((\w+)\!)?\$?[A-Za-z]{1,2}\$?\d+:((\w+)\!)?\$?[A-Za-z]{1,2}\$?\d+/g);
                    // If there is no cell range parameter, we will match the single cell paramter. i.e. 'A1'
                    if (!matches || matches.length === 0) {
                        matches = cellData.match(/((\w+)\!)?\$?[A-Za-z]{1,2}\$?\d+/g);
                    }
                    if (!!matches && matches.length > 0) {
                        cellRefMatchIndexes = [];
                        for (cellRefIndex = 0; cellRefIndex < matches.length; cellRefIndex++) {
                            cellRefMatchIndexes[cellRefIndex] = cellData.indexOf(matches[cellRefIndex]);
                        }
                        for (cellRefIndex = 0; cellRefIndex < matches.length; cellRefIndex++) {
                            sheetRef1 = null;
                            cellRef1 = null;
                            cellRef2 = null;
                            cellRange = null;
                            cellAddress1 = null;
                            cellAddress2 = null;
                            cellRef = matches[cellRefIndex];
                            if (cellRef.indexOf(':') > 0) {
                                cellRefs = cellRef.split(':');
                                cellRef1 = cellRefs[0];
                                cellRef2 = cellRefs[1];
                                sheetRefIndex = cellRef1.indexOf('!');
                                if (sheetRefIndex >= 0) {
                                    sheetRef1 = cellRef1.substring(0, sheetRefIndex);
                                    cellRef1 = cellRef1.substring(sheetRefIndex + 1);
                                }
                                if (sheetIndex === this.selectedSheetIndex) {
                                    if (sheetRef1 && sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                else {
                                    if (!sheetRef1 || sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                sheetRefIndex = cellRef2.indexOf('!');
                                if (sheetRefIndex >= 0) {
                                    sheetRef2 = cellRef2.substring(0, sheetRefIndex);
                                    cellRef2 = cellRef2.substring(sheetRefIndex + 1);
                                }
                                cellAddress1 = wijmo.xlsx.Workbook.tableAddress(cellRef1);
                                cellRange = new grid_1.CellRange(cellAddress1.row, cellAddress1.col);
                                cellAddress2 = wijmo.xlsx.Workbook.tableAddress(cellRef2);
                                cellRange.row2 = cellAddress2.row;
                                cellRange.col2 = cellAddress2.col;
                            }
                            else {
                                sheetRefIndex = cellRef.indexOf('!');
                                if (sheetRefIndex >= 0) {
                                    sheetRef1 = cellRef.substring(0, sheetRefIndex);
                                    cellRef1 = cellRef.substring(sheetRefIndex + 1);
                                }
                                else {
                                    cellRefMatchIndex = cellRefMatchIndexes[cellRefIndex];
                                    if (cellRefMatchIndex > 0 && /[\d\w]/.test(cellData[cellRefMatchIndex - 1])) {
                                        continue;
                                    }
                                    cellRef1 = cellRef;
                                }
                                if (sheetIndex === this.selectedSheetIndex) {
                                    if (sheetRef1 && sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                else {
                                    if (!sheetRef1 || sheetRef1.toLowerCase() !== this.selectedSheet.name.toLowerCase()) {
                                        continue;
                                    }
                                }
                                cellAddress1 = wijmo.xlsx.Workbook.tableAddress(cellRef1);
                                cellRange = new grid_1.CellRange(cellAddress1.row, cellAddress1.col);
                            }
                            if (cellRange) {
                                changed = false;
                                if (isRow) {
                                    if (isAdding) {
                                        if (cellRange.topRow >= index) {
                                            cellRange.row += count;
                                            cellRange.row2 += count;
                                            changed = true;
                                        }
                                        else if (cellRange.topRow < index && cellRange.bottomRow >= index) {
                                            if (cellRange.row < cellRange.row2) {
                                                cellRange.row2 += count;
                                            }
                                            else {
                                                cellRange.row += count;
                                            }
                                            changed = true;
                                        }
                                    }
                                    else {
                                        if (cellRange.topRow > index) {
                                            cellRange.row -= count;
                                            cellRange.row2 -= count;
                                            changed = true;
                                        }
                                        else {
                                            if (cellRange.isSingleCell) {
                                                if (cellRange.row >= index - count + 1) {
                                                    cellRange.row = index - count + 1;
                                                    cellRange.row2 = index - count + 1;
                                                    changed = true;
                                                }
                                            }
                                            else {
                                                if (cellRange.topRow >= index - count + 1) {
                                                    if (cellRange.row < cellRange.row2) {
                                                        cellRange.row = index - count + 1;
                                                        cellRange.row2 -= count;
                                                    }
                                                    else {
                                                        cellRange.row -= count;
                                                        cellRange.row2 = index - count + 1;
                                                    }
                                                    changed = true;
                                                }
                                                else if (cellRange.topRow < index - count + 1 && cellRange.bottomRow >= index - count + 1) {
                                                    if (cellRange.bottomRow > index) {
                                                        if (cellRange.row < cellRange.row2) {
                                                            cellRange.row2 -= count;
                                                        }
                                                        else {
                                                            cellRange.row -= count;
                                                        }
                                                    }
                                                    else {
                                                        if (cellRange.row < cellRange.row2) {
                                                            cellRange.row2 = index - count;
                                                        }
                                                        else {
                                                            cellRange.row = index - count;
                                                        }
                                                    }
                                                    changed = true;
                                                }
                                            }
                                        }
                                    }
                                }
                                else {
                                    if (isAdding) {
                                        if (cellRange.leftCol >= index) {
                                            cellRange.col += count;
                                            cellRange.col2 += count;
                                            changed = true;
                                        }
                                        else if (cellRange.leftCol < index && cellRange.rightCol >= index) {
                                            if (cellRange.col < cellRange.col2) {
                                                cellRange.col2 += count;
                                            }
                                            else {
                                                cellRange.col += count;
                                            }
                                            changed = true;
                                        }
                                    }
                                    else {
                                        if (cellRange.leftCol > index) {
                                            cellRange.col -= count;
                                            cellRange.col2 -= count;
                                            changed = true;
                                        }
                                        else {
                                            if (cellRange.isSingleCell) {
                                                if (cellRange.col >= index - count + 1) {
                                                    cellRange.col = index - count + 1;
                                                    cellRange.col2 = index - count + 1;
                                                    changed = true;
                                                }
                                            }
                                            else {
                                                if (cellRange.leftCol >= index - count + 1) {
                                                    if (cellRange.col < cellRange.col2) {
                                                        cellRange.col = index - count + 1;
                                                        cellRange.col2 -= count;
                                                    }
                                                    else {
                                                        cellRange.col -= count;
                                                        cellRange.col2 = index - count + 1;
                                                    }
                                                    changed = true;
                                                }
                                                else if (cellRange.leftCol < index - count + 1 && cellRange.rightCol >= index - count + 1) {
                                                    if (cellRange.rightCol > index) {
                                                        if (cellRange.col < cellRange.col2) {
                                                            cellRange.col2 -= count;
                                                        }
                                                        else {
                                                            cellRange.col -= count;
                                                        }
                                                    }
                                                    else {
                                                        if (cellRange.col < cellRange.col2) {
                                                            cellRange.col2 = index - count;
                                                        }
                                                        else {
                                                            cellRange.col = index - count;
                                                        }
                                                    }
                                                    changed = true;
                                                }
                                            }
                                        }
                                    }
                                }
                                if (changed) {
                                    if (!cellAddress2) {
                                        updatedCellRef = sheetRef1 ? sheetRef1 + '!' : '';
                                        updatedCellRef += wijmo.xlsx.Workbook.xlsxAddress(cellRange.row, cellRange.col, cellAddress1.absRow, cellAddress1.absCol);
                                    }
                                    else {
                                        updatedCellRef = sheetRef1 ? sheetRef1 + '!' : '';
                                        updatedCellRef += wijmo.xlsx.Workbook.xlsxAddress(cellRange.row, cellRange.col, cellAddress1.absRow, cellAddress1.absCol) + ':';
                                        updatedCellRef += (sheetRef2 ? sheetRef2 + '!' : '') + wijmo.xlsx.Workbook.xlsxAddress(cellRange.row2, cellRange.col2, cellAddress2.absRow, cellAddress2.absCol);
                                    }
                                    if (updatedCellData == null) {
                                        updatedCellData = cellData;
                                    }
                                    updatedCellData = updatedCellData.replace(new RegExp(cellRef.replace(/\$/g, '\\$'), 'gi'), function (content, index) {
                                        // Avoid to replace the replaced cell reference, when the updated the cell reference is tha same with the replaced cell reference. (TFS 275117)
                                        if (index + content.length >= cellRefMatchIndexes[cellRefIndex]) {
                                            return updatedCellRef;
                                        }
                                        else {
                                            return content;
                                        }
                                    });
                                }
                            }
                        }
                    }
                    return updatedCellData;
                };
                // Copy the rows of the FlexSheet to its selected sheet.
                FlexSheet.prototype._copyRowsToSelectedSheet = function () {
                    var i, self = this;
                    if (!self.selectedSheet) {
                        return;
                    }
                    self.selectedSheet.grid.rows.clear();
                    for (i = 0; i < self.rows.length; i++) {
                        self.selectedSheet.grid.rows.push(self.rows[i]);
                    }
                    setTimeout(function () {
                        self._setFlexSheetToDirty();
                        self.invalidate();
                    }, 10);
                };
                // Copy the columns of the FlexSheet to its selected sheet.
                // AlexI - made "internal" to fix TFS 292673
                /*private*/ FlexSheet.prototype._copyColumnsToSelectedSheet = function () {
                    var i, self = this;
                    if (!self.selectedSheet) {
                        return;
                    }
                    self.selectedSheet.grid.columns.clear();
                    for (i = 0; i < self.columns.length; i++) {
                        self.selectedSheet.grid.columns.push(self.columns[i]);
                    }
                    setTimeout(function () {
                        self._setFlexSheetToDirty();
                        self.invalidate();
                    }, 10);
                };
                // Parse the WorkbookTable instance to Table instance.
                FlexSheet.prototype._parseFromWorkbookTable = function (table) {
                    var tableRange, tableRefs, tableRef1, tableRef2, tableAddress1, tableAddress2, sheetTableColumns, tableColumn, tableStyle;
                    tableRefs = table.ref.split(':');
                    tableRef1 = tableRefs[0];
                    tableRef2 = tableRefs[1];
                    tableAddress1 = wijmo.xlsx.Workbook.tableAddress(tableRef1);
                    tableRange = new grid_1.CellRange(tableAddress1.row, tableAddress1.col);
                    tableAddress2 = wijmo.xlsx.Workbook.tableAddress(tableRef2);
                    tableRange.row2 = tableAddress2.row;
                    tableRange.col2 = tableAddress2.col;
                    if (table.columns && table.columns.length > 0) {
                        sheetTableColumns = [];
                        for (var i = 0; i < table.columns.length; i++) {
                            tableColumn = table.columns[i];
                            sheetTableColumns[i] = new sheet_1.TableColumn(tableColumn.name, tableColumn.totalRowLabel, tableColumn.totalRowFunction, tableColumn.showFilterButton);
                        }
                    }
                    if (table.style != null) {
                        if (this._isBuiltInStyleName(table.style.name)) {
                            tableStyle = this.getBuiltInTableStyle(table.style.name);
                        }
                        else {
                            tableStyle = this._parseFromWorkbookTableStyle(table.style);
                        }
                    }
                    return new sheet_1.Table(this, table.name, tableRange, tableStyle, sheetTableColumns, table.showHeaderRow, table.showTotalRow, table.showBandedColumns, table.showBandedRows, table.showFirstColumn, table.showLastColumn);
                };
                // Parse the WorkbookTableStyle instance to TableStyle instance.
                FlexSheet.prototype._parseFromWorkbookTableStyle = function (tableStyle) {
                    var sheetTableStyle = new sheet_1.TableStyle(tableStyle.name);
                    if (tableStyle.firstBandedColumnStyle != null) {
                        sheetTableStyle.firstBandedColumnStyle = this._parseFromWorkbookTableStyleElement(tableStyle.firstBandedColumnStyle);
                    }
                    if (tableStyle.firstBandedRowStyle != null) {
                        sheetTableStyle.firstBandedRowStyle = this._parseFromWorkbookTableStyleElement(tableStyle.firstBandedRowStyle);
                    }
                    if (tableStyle.firstColumnStyle != null) {
                        sheetTableStyle.firstColumnStyle = this._parseFromWorkbookTableStyleElement(tableStyle.firstColumnStyle);
                    }
                    if (tableStyle.firstHeaderCellStyle != null) {
                        sheetTableStyle.firstHeaderCellStyle = this._parseFromWorkbookTableStyleElement(tableStyle.firstHeaderCellStyle);
                    }
                    if (tableStyle.firstTotalCellStyle != null) {
                        sheetTableStyle.firstTotalCellStyle = this._parseFromWorkbookTableStyleElement(tableStyle.firstTotalCellStyle);
                    }
                    if (tableStyle.headerRowStyle != null) {
                        sheetTableStyle.headerRowStyle = this._parseFromWorkbookTableStyleElement(tableStyle.headerRowStyle);
                    }
                    if (tableStyle.lastColumnStyle != null) {
                        sheetTableStyle.lastColumnStyle = this._parseFromWorkbookTableStyleElement(tableStyle.lastColumnStyle);
                    }
                    if (tableStyle.lastHeaderCellStyle != null) {
                        sheetTableStyle.lastHeaderCellStyle = this._parseFromWorkbookTableStyleElement(tableStyle.lastHeaderCellStyle);
                    }
                    if (tableStyle.lastTotalCellStyle != null) {
                        sheetTableStyle.lastTotalCellStyle = this._parseFromWorkbookTableStyleElement(tableStyle.lastTotalCellStyle);
                    }
                    if (tableStyle.secondBandedColumnStyle != null) {
                        sheetTableStyle.secondBandedColumnStyle = this._parseFromWorkbookTableStyleElement(tableStyle.secondBandedColumnStyle);
                    }
                    if (tableStyle.secondBandedRowStyle != null) {
                        sheetTableStyle.secondBandedRowStyle = this._parseFromWorkbookTableStyleElement(tableStyle.secondBandedRowStyle);
                    }
                    if (tableStyle.totalRowStyle != null) {
                        sheetTableStyle.totalRowStyle = this._parseFromWorkbookTableStyleElement(tableStyle.totalRowStyle);
                    }
                    if (tableStyle.wholeTableStyle != null) {
                        sheetTableStyle.wholeTableStyle = this._parseFromWorkbookTableStyleElement(tableStyle.wholeTableStyle);
                    }
                    return sheetTableStyle;
                };
                // Parse the WorkbookTableStyleElement instance to Table style element.
                FlexSheet.prototype._parseFromWorkbookTableStyleElement = function (tableStyleElement) {
                    var sheetTableStyleEle;
                    sheetTableStyleEle = {
                        fontWeight: tableStyleElement.font && tableStyleElement.font.bold ? 'bold' : 'none',
                        fontStyle: tableStyleElement.font && tableStyleElement.font.italic ? 'italic' : 'none',
                        textDecoration: tableStyleElement.font && tableStyleElement.font.underline ? 'underline' : 'none',
                        fontFamily: tableStyleElement.font && tableStyleElement.font.family ? tableStyleElement.font.family : '',
                        fontSize: tableStyleElement.font && tableStyleElement.font.size ? tableStyleElement.font.size + 'px' : '',
                        color: tableStyleElement.font && tableStyleElement.font.color ? tableStyleElement.font.color : '',
                        backgroundColor: tableStyleElement.fill && tableStyleElement.fill.color ? tableStyleElement.fill.color : ''
                    };
                    if (tableStyleElement.borders) {
                        if (tableStyleElement.borders.left) {
                            grid_1.xlsx.FlexGridXlsxConverter._parseBorderStyle(tableStyleElement.borders.left.style, 'Left', sheetTableStyleEle);
                            sheetTableStyleEle.borderLeftColor = tableStyleElement.borders.left.color;
                        }
                        if (tableStyleElement.borders.right) {
                            grid_1.xlsx.FlexGridXlsxConverter._parseBorderStyle(tableStyleElement.borders.right.style, 'Right', sheetTableStyleEle);
                            sheetTableStyleEle.borderRightColor = tableStyleElement.borders.right.color;
                        }
                        if (tableStyleElement.borders.top) {
                            grid_1.xlsx.FlexGridXlsxConverter._parseBorderStyle(tableStyleElement.borders.top.style, 'Top', sheetTableStyleEle);
                            sheetTableStyleEle.borderTopColor = tableStyleElement.borders.top.color;
                        }
                        if (tableStyleElement.borders.bottom) {
                            grid_1.xlsx.FlexGridXlsxConverter._parseBorderStyle(tableStyleElement.borders.bottom.style, 'Bottom', sheetTableStyleEle);
                            sheetTableStyleEle.borderBottomColor = tableStyleElement.borders.bottom.color;
                        }
                        if (tableStyleElement.borders.vertical) {
                            grid_1.xlsx.FlexGridXlsxConverter._parseBorderStyle(tableStyleElement.borders.vertical.style, 'Vertical', sheetTableStyleEle);
                            sheetTableStyleEle.borderVerticalColor = tableStyleElement.borders.vertical.color;
                        }
                        if (tableStyleElement.borders.horizontal) {
                            grid_1.xlsx.FlexGridXlsxConverter._parseBorderStyle(tableStyleElement.borders.horizontal.style, 'Horizontal', sheetTableStyleEle);
                            sheetTableStyleEle.borderHorizontalColor = tableStyleElement.borders.horizontal.color;
                        }
                    }
                    if (tableStyleElement.size != null) {
                        sheetTableStyleEle.size = tableStyleElement.size;
                    }
                    return sheetTableStyleEle;
                };
                // Parse the FlexSheet table to workbook table.
                FlexSheet.prototype._parseToWorkbookTable = function (table) {
                    var workbookTable = new wijmo.xlsx.WorkbookTable(), tableRange = table.range, cellRef1, cellRef2;
                    workbookTable.name = table.name;
                    cellRef1 = wijmo.xlsx.Workbook.xlsxAddress(tableRange.topRow, tableRange.leftCol);
                    cellRef2 = wijmo.xlsx.Workbook.xlsxAddress(tableRange.bottomRow, tableRange.rightCol);
                    workbookTable.ref = cellRef1 + ':' + cellRef2;
                    if (table.style != null) {
                        if (table.style.isBuiltIn) {
                            workbookTable.style = new wijmo.xlsx.WorkbookTableStyle();
                            workbookTable.style.name = table.style.name;
                        }
                        else {
                            workbookTable.style = this._parseToWorkbookTableStyle(table.style);
                        }
                    }
                    workbookTable.showBandedColumns = table.showBandedColumns;
                    workbookTable.showBandedRows = table.showBandedRows;
                    workbookTable.showHeaderRow = table.showHeaderRow;
                    workbookTable.showTotalRow = table.showTotalRow;
                    workbookTable.showFirstColumn = table.showFirstColumn;
                    workbookTable.showLastColumn = table.showLastColumn;
                    for (var i = 0; i < table.columns.length; i++) {
                        var column = table.columns[i], workbookTableColumn = new wijmo.xlsx.WorkbookTableColumn();
                        workbookTableColumn.name = column.name;
                        workbookTableColumn.totalRowLabel = column.totalRowLabel;
                        workbookTableColumn.totalRowFunction = column.totalRowFunction;
                        workbookTableColumn.showFilterButton = column.showFilterButton;
                        workbookTable.columns.push(workbookTableColumn);
                    }
                    return workbookTable;
                };
                // Parse the FlexSheet table style to workbook table style.
                FlexSheet.prototype._parseToWorkbookTableStyle = function (tableStyle) {
                    var workbookTableStyle = new wijmo.xlsx.WorkbookTableStyle();
                    workbookTableStyle.name = tableStyle.name;
                    if (tableStyle.firstBandedColumnStyle != null) {
                        workbookTableStyle.firstBandedColumnStyle = this._parseToWorkbookTableStyleElement(tableStyle.firstBandedColumnStyle, true);
                    }
                    if (tableStyle.firstBandedRowStyle != null) {
                        workbookTableStyle.firstBandedRowStyle = this._parseToWorkbookTableStyleElement(tableStyle.firstBandedRowStyle, true);
                    }
                    if (tableStyle.firstColumnStyle != null) {
                        workbookTableStyle.firstColumnStyle = this._parseToWorkbookTableStyleElement(tableStyle.firstColumnStyle);
                    }
                    if (tableStyle.firstHeaderCellStyle != null) {
                        workbookTableStyle.firstHeaderCellStyle = this._parseToWorkbookTableStyleElement(tableStyle.firstHeaderCellStyle);
                    }
                    if (tableStyle.firstTotalCellStyle != null) {
                        workbookTableStyle.firstTotalCellStyle = this._parseToWorkbookTableStyleElement(tableStyle.firstTotalCellStyle);
                    }
                    if (tableStyle.headerRowStyle != null) {
                        workbookTableStyle.headerRowStyle = this._parseToWorkbookTableStyleElement(tableStyle.headerRowStyle);
                    }
                    if (tableStyle.lastColumnStyle != null) {
                        workbookTableStyle.lastColumnStyle = this._parseToWorkbookTableStyleElement(tableStyle.lastColumnStyle);
                    }
                    if (tableStyle.lastHeaderCellStyle != null) {
                        workbookTableStyle.lastHeaderCellStyle = this._parseToWorkbookTableStyleElement(tableStyle.lastHeaderCellStyle);
                    }
                    if (tableStyle.lastTotalCellStyle != null) {
                        workbookTableStyle.lastTotalCellStyle = this._parseToWorkbookTableStyleElement(tableStyle.lastTotalCellStyle);
                    }
                    if (tableStyle.secondBandedColumnStyle != null) {
                        workbookTableStyle.secondBandedColumnStyle = this._parseToWorkbookTableStyleElement(tableStyle.secondBandedColumnStyle, true);
                    }
                    if (tableStyle.secondBandedRowStyle != null) {
                        workbookTableStyle.secondBandedRowStyle = this._parseToWorkbookTableStyleElement(tableStyle.secondBandedRowStyle, true);
                    }
                    if (tableStyle.totalRowStyle != null) {
                        workbookTableStyle.totalRowStyle = this._parseToWorkbookTableStyleElement(tableStyle.totalRowStyle);
                    }
                    if (tableStyle.wholeTableStyle != null) {
                        workbookTableStyle.wholeTableStyle = this._parseToWorkbookTableStyleElement(tableStyle.wholeTableStyle);
                    }
                    return workbookTableStyle;
                };
                // Parse the FlexSheet table style element to workbook table style element.
                FlexSheet.prototype._parseToWorkbookTableStyleElement = function (tableStyleElement, isBandedStyle) {
                    if (isBandedStyle === void 0) { isBandedStyle = false; }
                    var workbookTableStyleEle, workbookTableStyleEleOM = grid_1.xlsx.FlexGridXlsxConverter._parseCellStyle(tableStyleElement, true);
                    if (isBandedStyle) {
                        workbookTableStyleEle = new wijmo.xlsx.WorkbookTableBandedStyle();
                        workbookTableStyleEle.size = tableStyleElement.size;
                    }
                    else {
                        workbookTableStyleEle = new wijmo.xlsx.WorkbookTableCommonStyle();
                    }
                    workbookTableStyleEle._deserialize(workbookTableStyleEleOM);
                    return workbookTableStyleEle;
                };
                // Check whether the style name is built-in table style of excel.
                FlexSheet.prototype._isBuiltInStyleName = function (styleName) {
                    var styleIndex;
                    if (styleName.search(/TableStyleLight/i) === 0) {
                        styleIndex = +styleName.substring(15);
                        if (!isNaN(styleIndex) && styleIndex >= 1 && styleIndex <= 21) {
                            return true;
                        }
                    }
                    else if (styleName.search(/TableStyleMedium/i) === 0) {
                        styleIndex = +styleName.substring(16);
                        if (!isNaN(styleIndex) && styleIndex >= 1 && styleIndex <= 28) {
                            return true;
                        }
                    }
                    else if (styleName.search(/TableStyleDark/i) === 0) {
                        styleIndex = +styleName.substring(14);
                        if (!isNaN(styleIndex) && styleIndex >= 1 && styleIndex <= 11) {
                            return true;
                        }
                    }
                    return false;
                };
                // Gets the table instance of FlexSheet by table name.
                FlexSheet.prototype._getTable = function (name) {
                    var tabel;
                    if (!this.tables) {
                        return null;
                    }
                    for (var i = 0; i < this.tables.length; i++) {
                        tabel = this.tables[i];
                        if (tabel.name.toLowerCase() === name.toLowerCase()) {
                            return tabel;
                        }
                    }
                    return null;
                };
                // Add table in FlexSheet.
                FlexSheet.prototype._addTable = function (range, tableName, tableStyle, columns, options, sheet) {
                    var table, showHeaderRow, showTotalRow, showBandedColumns, showBandedRows, showFirstColumn, showLastColumn;
                    if (tableName == null || this._getTable(tableName) != null) {
                        tableName = this._getUniqueTableName();
                    }
                    if (options == null) {
                        table = new sheet_1.Table(this, tableName, range, tableStyle, columns);
                    }
                    else {
                        showHeaderRow = options.showHeaderRow != null ? options.showHeaderRow : true;
                        showTotalRow = options.showTotalRow != null ? options.showTotalRow : false;
                        showBandedColumns = options.showBandedColumns != null ? options.showBandedColumns : false;
                        showBandedRows = options.showBandedRows != null ? options.showBandedRows : true;
                        showFirstColumn = options.showFirstColumn != null ? options.showFirstColumn : false;
                        showLastColumn = options.showLastColumn != null ? options.showLastColumn : false;
                        table = new sheet_1.Table(this, tableName, range, tableStyle, columns, showHeaderRow, showTotalRow, showBandedColumns, showBandedRows, showFirstColumn, showLastColumn);
                    }
                    if (this._tables == null) {
                        this._tables = new wijmo.collections.ObservableArray();
                    }
                    this._tables.push(table);
                    if (sheet) {
                        sheet.tableNames.push(tableName);
                    }
                    else {
                        this.selectedSheet.tableNames.push(tableName);
                    }
                    return table;
                };
                // Check whether the reference is table column reference 
                FlexSheet.prototype._isTableColumnRef = function (cellData, cellRef) {
                    var regExp = new RegExp('\\[(\\s*@)?' + cellRef + '\\]', 'i');
                    return regExp.test(cellData);
                };
                // Get the unique name of the table.
                FlexSheet.prototype._getUniqueTableName = function () {
                    var validName = 'Table1', index = 2;
                    do {
                        if (this._getTable(validName) == null) {
                            break;
                        }
                        else {
                            validName = 'Table' + index;
                        }
                        index = index + 1;
                    } while (true);
                    return validName;
                };
                // Get theme color.
                FlexSheet.prototype._getThemeColor = function (theme, tint) {
                    var themeColor = this._colorThemes[theme], color, hslArray;
                    if (tint != null) {
                        color = new wijmo.Color('#' + themeColor);
                        hslArray = color.getHsl();
                        // About the tint value and theme color convert to rgb color, 
                        // please refer https://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.color.aspx
                        if (tint < 0) {
                            hslArray[2] = hslArray[2] * (1.0 + tint);
                        }
                        else {
                            hslArray[2] = hslArray[2] * (1.0 - tint) + (1 - 1 * (1.0 - tint));
                        }
                        color = wijmo.Color.fromHsl(hslArray[0], hslArray[1], hslArray[2]);
                        return color.toString();
                    }
                    // if the color value is undefined, we should return the themeColor (TFS 121712)
                    return '#' + themeColor;
                };
                // Create the built-in table style via its name
                FlexSheet.prototype._createBuiltInTableStyle = function (styleName) {
                    var styleIndex;
                    if (styleName.search(/TableStyleLight/i) === 0) {
                        styleIndex = +styleName.substring(15);
                        if (!isNaN(styleIndex) && styleIndex >= 1 && styleIndex <= 21) {
                            if (styleIndex <= 7) {
                                return this._generateTableLightStyle1(styleIndex - 1, styleName, true);
                            }
                            else if (styleIndex <= 14) {
                                return this._generateTableLightStyle2(styleIndex - 8, styleName);
                            }
                            else {
                                return this._generateTableLightStyle1(styleIndex - 15, styleName, false);
                            }
                        }
                    }
                    else if (styleName.search(/TableStyleMedium/i) === 0) {
                        styleIndex = +styleName.substring(16);
                        if (!isNaN(styleIndex) && styleIndex >= 1 && styleIndex <= 28) {
                            if (styleIndex <= 7) {
                                return this._generateTableMediumStyle1(styleIndex - 1, styleName);
                            }
                            else if (styleIndex <= 14) {
                                return this._generateTableMediumStyle2(styleIndex - 8, styleName);
                            }
                            else if (styleIndex <= 21) {
                                return this._generateTableMediumStyle3(styleIndex - 15, styleName);
                            }
                            else {
                                return this._generateTableMediumStyle4(styleIndex - 22, styleName);
                            }
                        }
                    }
                    else if (styleName.search(/TableStyleDark/i) === 0) {
                        styleIndex = +styleName.substring(14);
                        if (!isNaN(styleIndex) && styleIndex >= 1 && styleIndex <= 11) {
                            if (styleIndex <= 7) {
                                return this._generateTableDarkStyle1(styleIndex - 1, styleName);
                            }
                            else {
                                return this._generateTableDarkStyle2(styleIndex - 8, styleName);
                            }
                        }
                    }
                    return null;
                };
                FlexSheet.prototype._generateTableLightStyle1 = function (styleIndex, styleName, isLowerStyle) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 1 : styleIndex + 3, headerBorderWidth = isLowerStyle ? '1px' : '2px', totalBorderStyle = isLowerStyle ? 'solid' : 'double', totalBorderWidth = isLowerStyle ? '1px' : '3px';
                    tableStyle.wholeTableStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: 'solid',
                        borderTopWidth: '1px',
                        borderBottomColor: { theme: colorTheme },
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '1px'
                    };
                    tableStyle.firstColumnStyle = {
                        fontWeight: 'bold'
                    };
                    tableStyle.lastColumnStyle = {
                        fontWeight: 'bold'
                    };
                    tableStyle.headerRowStyle = {
                        borderBottomColor: { theme: colorTheme },
                        borderBottomStyle: 'solid',
                        borderBottomWidth: headerBorderWidth,
                        fontWeight: 'bold'
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: totalBorderStyle,
                        borderTopWidth: totalBorderWidth,
                        fontWeight: 'bold'
                    };
                    if (styleIndex === 0) {
                        tableStyle.wholeTableStyle.color = { theme: colorTheme };
                        tableStyle.firstColumnStyle.color = { theme: colorTheme };
                        tableStyle.lastColumnStyle.color = { theme: colorTheme };
                        tableStyle.headerRowStyle.color = { theme: colorTheme };
                        tableStyle.totalRowStyle.color = { theme: colorTheme };
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: 0, tint: -0.15 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: 0, tint: -0.15 }
                        };
                    }
                    else {
                        if (isLowerStyle) {
                            tableStyle.wholeTableStyle.color = { theme: colorTheme, tint: -0.25 };
                            tableStyle.firstColumnStyle.color = { theme: colorTheme, tint: -0.25 };
                            tableStyle.lastColumnStyle.color = { theme: colorTheme, tint: -0.25 };
                            tableStyle.headerRowStyle.color = { theme: colorTheme, tint: -0.25 };
                            tableStyle.totalRowStyle.color = { theme: colorTheme, tint: -0.25 };
                        }
                        else {
                            tableStyle.wholeTableStyle.color = { theme: 1 };
                            tableStyle.firstColumnStyle.color = { theme: 1 };
                            tableStyle.lastColumnStyle.color = { theme: 1 };
                            tableStyle.headerRowStyle.color = { theme: 1 };
                            tableStyle.totalRowStyle.color = { theme: 1 };
                        }
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.8 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.8 }
                        };
                    }
                    if (!isLowerStyle) {
                        tableStyle.wholeTableStyle.borderLeftColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderLeftStyle = 'solid';
                        tableStyle.wholeTableStyle.borderLeftWidth = '1px';
                        tableStyle.wholeTableStyle.borderRightColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderRightStyle = 'solid';
                        tableStyle.wholeTableStyle.borderRightWidth = '1px';
                        tableStyle.wholeTableStyle.borderHorizontalColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderHorizontalStyle = 'solid';
                        tableStyle.wholeTableStyle.borderHorizontalWidth = '1px';
                        tableStyle.wholeTableStyle.borderVerticalColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderVerticalStyle = 'solid';
                        tableStyle.wholeTableStyle.borderVerticalWidth = '1px';
                    }
                    return tableStyle;
                };
                FlexSheet.prototype._generateTableLightStyle2 = function (styleIndex, styleName) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 1 : styleIndex + 3;
                    tableStyle.wholeTableStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: 'solid',
                        borderTopWidth: '1px',
                        borderBottomColor: { theme: colorTheme },
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '1px',
                        borderLeftColor: { theme: colorTheme },
                        borderLeftStyle: 'solid',
                        borderLeftWidth: '1px',
                        borderRightColor: { theme: colorTheme },
                        borderRightStyle: 'solid',
                        borderRightWidth: '1px',
                        color: { theme: 1 }
                    };
                    tableStyle.firstBandedRowStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: 'solid',
                        borderTopWidth: '1px'
                    };
                    tableStyle.secondBandedRowStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: 'solid',
                        borderTopWidth: '1px'
                    };
                    tableStyle.firstBandedColumnStyle = {
                        borderLeftColor: { theme: colorTheme },
                        borderLeftStyle: 'solid',
                        borderLeftWidth: '1px'
                    };
                    tableStyle.secondBandedColumnStyle = {
                        borderLeftColor: { theme: colorTheme },
                        borderLeftStyle: 'solid',
                        borderLeftWidth: '1px'
                    };
                    tableStyle.firstColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.lastColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.headerRowStyle = {
                        backgroundColor: { theme: colorTheme },
                        fontWeight: 'bold',
                        color: { theme: 0 }
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: 'double',
                        borderTopWidth: '3px',
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    return tableStyle;
                };
                FlexSheet.prototype._generateTableMediumStyle1 = function (styleIndex, styleName) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 1 : styleIndex + 3;
                    tableStyle.wholeTableStyle = {
                        borderTopStyle: 'solid',
                        borderTopWidth: '1px',
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '1px',
                        borderLeftStyle: 'solid',
                        borderLeftWidth: '1px',
                        borderRightStyle: 'solid',
                        borderRightWidth: '1px',
                        borderHorizontalStyle: 'solid',
                        borderHorizontalWidth: '1px',
                        color: { theme: 1 }
                    };
                    if (styleIndex === 0) {
                        tableStyle.wholeTableStyle.borderTopColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderBottomColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderLeftColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderRightColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderHorizontalColor = { theme: colorTheme };
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: 0, tint: -0.15 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: 0, tint: -0.15 }
                        };
                    }
                    else {
                        tableStyle.wholeTableStyle.borderTopColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderBottomColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderLeftColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderRightColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderHorizontalColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.8 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.8 }
                        };
                    }
                    tableStyle.firstColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.lastColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.headerRowStyle = {
                        backgroundColor: { theme: colorTheme },
                        fontWeight: 'bold',
                        color: { theme: 0 }
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: 'double',
                        borderTopWidth: '3px',
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    return tableStyle;
                };
                FlexSheet.prototype._generateTableMediumStyle2 = function (styleIndex, styleName) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 1 : styleIndex + 3;
                    tableStyle.wholeTableStyle = {
                        borderVerticalStyle: 'solid',
                        borderVerticalWidth: '1px',
                        borderVerticalColor: { theme: 0 },
                        borderHorizontalStyle: 'solid',
                        borderHorizontalWidth: '1px',
                        borderHorizontalColor: { theme: 0 },
                        color: { theme: 1 }
                    };
                    if (styleIndex === 0) {
                        tableStyle.wholeTableStyle.backgroundColor = { theme: 0, tint: -0.15 };
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: 0, tint: -0.35 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: 0, tint: -0.35 }
                        };
                    }
                    else {
                        tableStyle.wholeTableStyle.backgroundColor = { theme: colorTheme, tint: 0.8 };
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.6 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.6 }
                        };
                    }
                    tableStyle.firstColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 0 },
                        backgroundColor: { theme: colorTheme }
                    };
                    tableStyle.lastColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 0 },
                        backgroundColor: { theme: colorTheme }
                    };
                    tableStyle.headerRowStyle = {
                        borderBottomColor: { theme: 0 },
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '3px',
                        backgroundColor: { theme: colorTheme },
                        fontWeight: 'bold',
                        color: { theme: 0 }
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: 0 },
                        borderTopStyle: 'solid',
                        borderTopWidth: '3px',
                        backgroundColor: { theme: colorTheme },
                        fontWeight: 'bold',
                        color: { theme: 0 }
                    };
                    return tableStyle;
                };
                FlexSheet.prototype._generateTableMediumStyle3 = function (styleIndex, styleName) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 1 : styleIndex + 3;
                    tableStyle.wholeTableStyle = {
                        borderTopStyle: 'solid',
                        borderTopWidth: '2px',
                        borderTopColor: { theme: 1 },
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '2px',
                        borderBottomColor: { theme: 1 },
                        color: { theme: 1 }
                    };
                    if (styleIndex === 0) {
                        tableStyle.wholeTableStyle.borderLeftColor = { theme: 1 };
                        tableStyle.wholeTableStyle.borderLeftStyle = 'solid';
                        tableStyle.wholeTableStyle.borderLeftWidth = '1px';
                        tableStyle.wholeTableStyle.borderRightColor = { theme: 1 };
                        tableStyle.wholeTableStyle.borderRightStyle = 'solid';
                        tableStyle.wholeTableStyle.borderRightWidth = '1px';
                        tableStyle.wholeTableStyle.borderVerticalColor = { theme: 1 };
                        tableStyle.wholeTableStyle.borderVerticalStyle = 'solid';
                        tableStyle.wholeTableStyle.borderVerticalWidth = '1px';
                        tableStyle.wholeTableStyle.borderHorizontalColor = { theme: 1 };
                        tableStyle.wholeTableStyle.borderHorizontalStyle = 'solid';
                        tableStyle.wholeTableStyle.borderHorizontalWidth = '1px';
                    }
                    tableStyle.firstBandedRowStyle = {
                        backgroundColor: { theme: 0, tint: -0.35 }
                    };
                    tableStyle.firstBandedColumnStyle = {
                        backgroundColor: { theme: 0, tint: -0.35 }
                    };
                    tableStyle.firstColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 0 },
                        backgroundColor: { theme: colorTheme }
                    };
                    tableStyle.lastColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 0 },
                        backgroundColor: { theme: colorTheme }
                    };
                    tableStyle.headerRowStyle = {
                        borderBottomColor: { theme: 1 },
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '2px',
                        backgroundColor: { theme: colorTheme },
                        fontWeight: 'bold',
                        color: { theme: 0 }
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: 1 },
                        borderTopStyle: 'double',
                        borderTopWidth: '3px'
                    };
                    return tableStyle;
                };
                FlexSheet.prototype._generateTableMediumStyle4 = function (styleIndex, styleName) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 1 : styleIndex + 3;
                    tableStyle.wholeTableStyle = {
                        borderTopStyle: 'solid',
                        borderTopWidth: '1px',
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '1px',
                        borderLeftStyle: 'solid',
                        borderLeftWidth: '1px',
                        borderRightStyle: 'solid',
                        borderRightWidth: '1px',
                        borderVerticalStyle: 'solid',
                        borderVerticalWidth: '1px',
                        borderHorizontalStyle: 'solid',
                        borderHorizontalWidth: '1px',
                        color: { theme: 1 }
                    };
                    if (styleIndex === 0) {
                        tableStyle.wholeTableStyle.borderTopColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderBottomColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderLeftColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderRightColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderVerticalColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.borderHorizontalColor = { theme: colorTheme };
                        tableStyle.wholeTableStyle.backgroundColor = { theme: 0, tint: -0.15 };
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: 0, tint: -0.35 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: 0, tint: -0.35 }
                        };
                    }
                    else {
                        tableStyle.wholeTableStyle.borderTopColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderBottomColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderLeftColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderRightColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderVerticalColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.borderHorizontalColor = { theme: colorTheme, tint: 0.4 };
                        tableStyle.wholeTableStyle.backgroundColor = { theme: colorTheme, tint: 0.8 };
                        tableStyle.firstBandedRowStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.6 }
                        };
                        tableStyle.firstBandedColumnStyle = {
                            backgroundColor: { theme: colorTheme, tint: 0.6 }
                        };
                    }
                    tableStyle.firstColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.lastColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.headerRowStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: colorTheme },
                        borderTopStyle: 'solid',
                        borderTopWidth: '2px',
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    return tableStyle;
                };
                FlexSheet.prototype._generateTableDarkStyle1 = function (styleIndex, styleName) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 1 : styleIndex + 3, tint = styleIndex === 0 ? 0.25 : -0.25;
                    tableStyle.wholeTableStyle = {
                        color: { theme: 0 }
                    };
                    tableStyle.firstBandedRowStyle = {
                        backgroundColor: { theme: colorTheme, tint: tint }
                    };
                    tableStyle.firstBandedColumnStyle = {
                        backgroundColor: { theme: colorTheme, tint: tint }
                    };
                    tableStyle.firstColumnStyle = {
                        borderRightColor: { theme: 0 },
                        borderRightStyle: 'solid',
                        borderRightWidth: '2px',
                        fontWeight: 'bold',
                        color: { theme: 0 },
                        backgroundColor: { theme: colorTheme, tint: tint }
                    };
                    tableStyle.lastColumnStyle = {
                        borderLeftColor: { theme: 0 },
                        borderLeftStyle: 'solid',
                        borderLeftWidth: '2px',
                        fontWeight: 'bold',
                        color: { theme: 0 },
                        backgroundColor: { theme: colorTheme, tint: tint }
                    };
                    tableStyle.headerRowStyle = {
                        borderBottomColor: { theme: 0 },
                        borderBottomStyle: 'solid',
                        borderBottomWidth: '2px',
                        fontWeight: 'bold',
                        color: { theme: 0 },
                        backgroundColor: { theme: 1 }
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: 0 },
                        borderTopStyle: 'solid',
                        borderTopWidth: '2px',
                        fontWeight: 'bold',
                        color: { theme: 0 }
                    };
                    if (styleIndex === 0) {
                        tableStyle.wholeTableStyle.backgroundColor = { theme: colorTheme, tint: 0.5 };
                        tableStyle.totalRowStyle.backgroundColor = { theme: colorTheme, tint: 0.15 };
                    }
                    else {
                        tableStyle.wholeTableStyle.backgroundColor = { theme: colorTheme };
                        tableStyle.totalRowStyle.backgroundColor = { theme: colorTheme, tint: -0.5 };
                    }
                    return tableStyle;
                };
                FlexSheet.prototype._generateTableDarkStyle2 = function (styleIndex, styleName) {
                    var tableStyle = new sheet_1.TableStyle(styleName, true), colorTheme = styleIndex === 0 ? 0 : 2 * styleIndex + 2, colorTheme2 = styleIndex === 0 ? 1 : 2 * styleIndex + 3, tint = styleIndex === 0 ? -0.15 : 0.8;
                    tableStyle.wholeTableStyle = {
                        backgroundColor: { theme: colorTheme, tint: tint }
                    };
                    tableStyle.firstBandedRowStyle = {
                        backgroundColor: { theme: colorTheme, tint: tint - 0.2 }
                    };
                    tableStyle.firstBandedColumnStyle = {
                        backgroundColor: { theme: colorTheme, tint: tint - 0.2 }
                    };
                    tableStyle.firstColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.lastColumnStyle = {
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    tableStyle.headerRowStyle = {
                        color: { theme: 0 },
                        backgroundColor: { theme: colorTheme2 }
                    };
                    tableStyle.totalRowStyle = {
                        borderTopColor: { theme: 1 },
                        borderTopStyle: 'double',
                        borderTopWidth: '3px',
                        fontWeight: 'bold',
                        color: { theme: 1 }
                    };
                    return tableStyle;
                };
                /**
                 * Overrides the template used to instantiate @see:FlexSheet control.
                 */
                FlexSheet.controlTemplate = '<div style="width:100%;height:100%">' +
                    '<div wj-part="container" style="width:100%">' + // (start)a container contains original flexgrid to hide the horizontal scrollbar.
                    grid_1.FlexGrid.controlTemplate +
                    '</div>' + // (end)a container contains original flexgrid to hide the horizontal scrollbar.
                    '<div wj-part="tab-holder" style="width:100%; min-width:100px">' + // sheet scrollbar splitter
                    '</div>' +
                    '<div wj-part="context-menu" style="display:none;z-index:100"></div>' +
                    '</div>';
                return FlexSheet;
            }(grid_1.FlexGrid));
            sheet_1.FlexSheet = FlexSheet;
            /**
             * Provides arguments for the @see:FlexSheet.draggingRowColumn event.
             */
            var DraggingRowColumnEventArgs = /** @class */ (function (_super) {
                __extends(DraggingRowColumnEventArgs, _super);
                /**
                 * Initializes a new instance of the @see:DraggingRowColumnEventArgs class.
                 *
                 * @param isDraggingRows Indicates whether the dragging event is triggered due to dragging rows or columns.
                 * @param isShiftKey Indicates whether the shift key is pressed when dragging.
                 */
                function DraggingRowColumnEventArgs(isDraggingRows, isShiftKey) {
                    var _this = _super.call(this) || this;
                    _this._isDraggingRows = isDraggingRows;
                    _this._isShiftKey = isShiftKey;
                    return _this;
                }
                Object.defineProperty(DraggingRowColumnEventArgs.prototype, "isDraggingRows", {
                    /**
                     * Gets a value indicating whether the event refers to dragging rows or columns.
                     */
                    get: function () {
                        return this._isDraggingRows;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(DraggingRowColumnEventArgs.prototype, "isShiftKey", {
                    /**
                     * Gets a value indicating whether the shift key is pressed.
                     */
                    get: function () {
                        return this._isShiftKey;
                    },
                    enumerable: true,
                    configurable: true
                });
                return DraggingRowColumnEventArgs;
            }(wijmo.EventArgs));
            sheet_1.DraggingRowColumnEventArgs = DraggingRowColumnEventArgs;
            /**
             * Provides arguments for unknown function events.
             */
            var UnknownFunctionEventArgs = /** @class */ (function (_super) {
                __extends(UnknownFunctionEventArgs, _super);
                /**
                 * Initializes a new instance of the @see:UnknownFunctionEventArgs class.
                 *
                 * @param funcName The name of the unknown function.
                 * @param params The parameters' value list of the nuknown function.
                 */
                function UnknownFunctionEventArgs(funcName, params) {
                    var _this = _super.call(this) || this;
                    _this._funcName = funcName;
                    _this._params = params;
                    return _this;
                }
                Object.defineProperty(UnknownFunctionEventArgs.prototype, "funcName", {
                    /**
                     * Gets the name of the unknown function.
                     */
                    get: function () {
                        return this._funcName;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(UnknownFunctionEventArgs.prototype, "params", {
                    /**
                     * Gets the parameters' value list of the nuknown function.
                     */
                    get: function () {
                        return this._params;
                    },
                    enumerable: true,
                    configurable: true
                });
                return UnknownFunctionEventArgs;
            }(wijmo.EventArgs));
            sheet_1.UnknownFunctionEventArgs = UnknownFunctionEventArgs;
            /**
             * Provides arguments for rows or columns changed events.
             */
            var RowColumnChangedEventArgs = /** @class */ (function (_super) {
                __extends(RowColumnChangedEventArgs, _super);
                /**
                 * Initializes a new instance of the @see:RowColumnChangedEventArgs class.
                 *
                 * @param index The start index of the changed rows or columns.
                 * @param count The added or removed count of the rows or columns.
                 * @param added The value indicates the event is for adding ot removing rows or columns.
                 */
                function RowColumnChangedEventArgs(index, count, added) {
                    var _this = _super.call(this) || this;
                    _this._index = index;
                    _this._count = count;
                    _this._added = added;
                    return _this;
                }
                Object.defineProperty(RowColumnChangedEventArgs.prototype, "index", {
                    /**
                     * Gets the start index of the changed rows or columns.
                     */
                    get: function () {
                        return this._index;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(RowColumnChangedEventArgs.prototype, "count", {
                    /**
                     * Gets the added or removed count of the rows or columns.
                     */
                    get: function () {
                        return this._count;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(RowColumnChangedEventArgs.prototype, "added", {
                    /**
                    * Gets the value indicates the event is for adding ot removing rows or columns.
                    */
                    get: function () {
                        return this._added;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(RowColumnChangedEventArgs.prototype, "isAdd", {
                    /*
                     * Gets the value indicates the event is for adding ot removing rows or columns.
                     */
                    get: function () {
                        wijmo._deprecated('RowColumnChangedEventArgs.isAdd', 'RowColumnChangedEventArgs.added');
                        return this._added;
                    },
                    enumerable: true,
                    configurable: true
                });
                return RowColumnChangedEventArgs;
            }(wijmo.EventArgs));
            sheet_1.RowColumnChangedEventArgs = RowColumnChangedEventArgs;
            /**
             * Defines the extension of the @see:GridPanel class, which is used by <b>FlexSheet</b> where
             * the base @see:FlexGrid class uses @see:GridPanel. For example, the <b>cells</b> property returns an instance
             * of this class.
             */
            var FlexSheetPanel = /** @class */ (function (_super) {
                __extends(FlexSheetPanel, _super);
                /**
                 * Initializes a new instance of the @see:FlexSheetPanel class.
                 *
                 * @param grid The @see:FlexGrid object that owns the panel.
                 * @param cellType The type of cell in the panel.
                 * @param rows The rows displayed in the panel.
                 * @param cols The columns displayed in the panel.
                 * @param element The HTMLElement that hosts the cells in the control.
                 */
                function FlexSheetPanel(grid, cellType, rows, cols, element) {
                    return _super.call(this, grid, cellType, rows, cols, element) || this;
                }
                /**
                 * Gets a @see:SelectedState value that indicates the selected state of a cell.
                 *
                 * Overrides this method to support multiple selection showSelectedHeaders for @see:FlexSheet
                 *
                 * @param r Specifies Row index of the cell.
                 * @param c Specifies Column index of the cell.
                 * @param rng @see:CellRange that contains the cell that would be included.
                 */
                FlexSheetPanel.prototype.getSelectedState = function (r, c, rng) {
                    var selections, selectionCnt, index, selection, selectedState, mergedRange;
                    if (!this.grid) {
                        return undefined;
                    }
                    mergedRange = this.grid.getMergedRange(this, r, c);
                    selections = this.grid.selectedSheet ? this.grid.selectedSheet.selectionRanges : null;
                    selectedState = _super.prototype.getSelectedState.call(this, r, c, rng);
                    selectionCnt = selections ? selections.length : 0;
                    if (selectedState === grid_1.SelectedState.None && selectionCnt > 0) {
                        for (index = 0; index < selections.length; index++) {
                            selection = selections[index];
                            if (selection && selection instanceof grid_1.CellRange) {
                                if (this.cellType === grid_1.CellType.Cell) {
                                    if (mergedRange) {
                                        if (mergedRange.contains(selection.row, selection.col)) {
                                            if (index === selectionCnt - 1 && !this.grid._isClicking) {
                                                return this.grid.showMarquee ? grid_1.SelectedState.None : grid_1.SelectedState.Cursor;
                                            }
                                            return grid_1.SelectedState.Selected;
                                        }
                                        if (mergedRange.intersects(selection)) {
                                            return grid_1.SelectedState.Selected;
                                        }
                                    }
                                    if (selection.row === r && selection.col === c) {
                                        if (index === selectionCnt - 1 && !this.grid._isClicking) {
                                            return this.grid.showMarquee ? grid_1.SelectedState.None : grid_1.SelectedState.Cursor;
                                        }
                                        return grid_1.SelectedState.Selected;
                                    }
                                    if (selection.contains(r, c)) {
                                        return grid_1.SelectedState.Selected;
                                    }
                                }
                                if (this.grid.showSelectedHeaders & grid_1.HeadersVisibility.Row
                                    && this.cellType === grid_1.CellType.RowHeader
                                    && selection.containsRow(r)) {
                                    return grid_1.SelectedState.Selected;
                                }
                                if (this.grid.showSelectedHeaders & grid_1.HeadersVisibility.Column
                                    && this.cellType === grid_1.CellType.ColumnHeader
                                    && selection.containsColumn(c)) {
                                    return grid_1.SelectedState.Selected;
                                }
                            }
                        }
                    }
                    return selectedState;
                };
                /**
                 * Gets the value stored in a cell in the panel.
                 *
                 * @param r The row index of the cell.
                 * @param c The index, name, or binding of the column that contains the cell.
                 * @param formatted Whether to format the value for display.
                 */
                FlexSheetPanel.prototype.getCellData = function (r, c, formatted) {
                    var value, col, bcol, cellStyle, data;
                    // get column index by name or binding
                    if (wijmo.isString(c)) {
                        c = this.columns.indexOf(c);
                        if (c < 0) {
                            throw 'Invalid column name or binding.';
                        }
                    }
                    if (r >= this.rows.length || wijmo.asNumber(c, false, true) >= this.columns.length) {
                        return null;
                    }
                    value = _super.prototype.getCellData.call(this, r, c, formatted);
                    col = this.columns[wijmo.asNumber(c, false, true)];
                    bcol = this.grid ? this.grid._getBindingColumn(this, r, col) : col;
                    if (formatted) {
                        data = _super.prototype.getCellData.call(this, r, c, false);
                        cellStyle = this.grid ? this.grid._getCellStyle(r, c) : null;
                        if (wijmo.isNumber(data) && data !== 0 && !!bcol && !bcol.format && !bcol.dataMap && !cellStyle) {
                            value = data.toString();
                        }
                    }
                    return value;
                };
                /**
                 * Sets the content of a cell in the panel.
                 *
                 * @param r The index of the row that contains the cell.
                 * @param c The index, name, or binding of the column that contains the cell.
                 * @param value The value to store in the cell.
                 * @param coerce A value indicating whether to change the value automatically to match the column's data type.
                 * @param invalidate Whether to invalidate the FlexSheet to show the change.
                 * @return Returns true if the value is stored successfully, otherwise false (failed cast).
                 */
                FlexSheetPanel.prototype.setCellData = function (r, c, value, coerce, invalidate) {
                    if (coerce === void 0) { coerce = true; }
                    if (invalidate === void 0) { invalidate = true; }
                    var parsedDateVal, orgVal = this.getCellData(r, c, false), isPasting = this.grid._isPasting;
                    if (coerce && value && wijmo.isString(value) && value[0] !== '\'') {
                        if (this.grid.columns[c].dataType !== wijmo.DataType.String && !wijmo.isNullOrWhiteSpace(value) && !isNaN(+value)) {
                            value = +value;
                        }
                        else if (this.grid.columns[c].dataType === wijmo.DataType.Boolean) {
                            value = wijmo.changeType(value, wijmo.DataType.Boolean, null);
                        }
                        else if (value[0] !== '=') {
                            parsedDateVal = wijmo.Globalize.parseDate(value, '');
                            if (parsedDateVal) {
                                value = parsedDateVal;
                            }
                        }
                    }
                    // When the cell data is formula, we shall not force to change the data type of the cell data.
                    if ((value && wijmo.isString(value) && (value[0] === '=' || value[0] === '\'')) || wijmo.isString(orgVal)) {
                        coerce = false;
                    }
                    return _super.prototype.setCellData.call(this, r, c, value, coerce && !isPasting, invalidate);
                };
                // renders a cell
                // It overrides the _renderCell method of the parent class GridPanel.
                FlexSheetPanel.prototype._renderCell = function (row, r, c, vrng, state, ctr) {
                    var cell, cellStyle, cellIndex = r * this.grid.columns.length + c, mr = this.grid.getMergedRange(this, r, c), table, updatedCtr;
                    updatedCtr = _super.prototype._renderCell.call(this, row, r, c, vrng, state, ctr);
                    if (this.cellType !== wijmo.grid.CellType.Cell) {
                        return updatedCtr;
                    }
                    // skip over cells that have been merged over
                    if (mr) {
                        if (cellIndex > mr.topRow * this.grid.columns.length + mr.leftCol) {
                            return updatedCtr;
                        }
                    }
                    cell = row.childNodes[ctr];
                    if (cell) {
                        if (this.grid.editRange == null || !this.grid.editRange.contains(r, c)) {
                            // if the cell is located in Table, will apply the related table styles for the cell.
                            if (this.grid.selectedSheet) {
                                table = this.grid.selectedSheet.findTable(r, c);
                                if (table) {
                                    table._updateCell(r, c, cell);
                                }
                            }
                        }
                        if (wijmo.hasClass(cell, 'wj-state-selected') || wijmo.hasClass(cell, 'wj-state-multi-selected')) {
                            // If the cell is selected state, we'll remove the custom background color and font color style.
                            cell.style.backgroundColor = '';
                            cell.style.color = '';
                        }
                        else if (this.grid.selectedSheet) {
                            // If the cell removes selected state, we'll resume the custom background color and font color style.
                            cellStyle = this.grid.selectedSheet._styledCells[cellIndex];
                            if (cellStyle) {
                                if (cellStyle.backgroundColor !== '') {
                                    cell.style.backgroundColor = cellStyle.backgroundColor;
                                }
                                if (cellStyle.color !== '') {
                                    cell.style.color = cellStyle.color;
                                }
                            }
                        }
                    }
                    return updatedCtr;
                };
                return FlexSheetPanel;
            }(grid_1.GridPanel));
            sheet_1.FlexSheetPanel = FlexSheetPanel;
            /**
             * Represents a row used to display column header information for a bound sheet.
             */
            var HeaderRow = /** @class */ (function (_super) {
                __extends(HeaderRow, _super);
                /**
                * Initializes a new instance of the HeaderRow class.
                */
                function HeaderRow() {
                    var _this = _super.call(this) || this;
                    _this.isReadOnly = true;
                    return _this;
                }
                return HeaderRow;
            }(grid_1.Row));
            sheet_1.HeaderRow = HeaderRow;
            /**
             * Represents a defined name item of FlexSheet.
             */
            var DefinedName = /** @class */ (function () {
                /**
                 * Initializes a new instance of the DefinedName class.
                 *
                 * @param owner The owner @see: FlexSheet control.
                 * @param name The name of the defined name item.
                 * @param value The value of the defined name item.
                 * @param sheetName The sheet name indicates the defined name item works in which sheet of FlexSheet.  If omitted, the defined name item works in all sheets of FlexSheet.
                 */
                function DefinedName(owner, name, value, sheetName) {
                    this._owner = owner;
                    this._name = name;
                    this._value = value;
                    if (sheetName != null) {
                        if (owner._validateSheetName(sheetName)) {
                            this._sheetName = sheetName;
                        }
                        else {
                            throw 'The sheet name:(' + sheetName + ') does not exist in FlexSheet.';
                        }
                    }
                }
                Object.defineProperty(DefinedName.prototype, "name", {
                    /**
                     * Gets or sets the name of the defined name item.
                     */
                    get: function () {
                        return this._name;
                    },
                    set: function (value) {
                        var oldName;
                        if (this._name !== value) {
                            if (!this._owner._checkExistDefinedName(name, this._sheetName)) {
                                oldName = this._name;
                                this._name = value;
                                this._owner._updateFormulasWithNameUpdating(oldName, this._name);
                            }
                            else {
                                throw 'The ' + name + ' already existed in definedNames.';
                            }
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(DefinedName.prototype, "value", {
                    /**
                     * Gets or sets the value of the defined name item.
                     */
                    get: function () {
                        return this._value;
                    },
                    set: function (val) {
                        if (this._value !== val) {
                            this._value = val;
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(DefinedName.prototype, "sheetName", {
                    /**
                     * Gets the sheetName of the defined name item.
                     */
                    get: function () {
                        return this._sheetName;
                    },
                    enumerable: true,
                    configurable: true
                });
                return DefinedName;
            }());
            sheet_1.DefinedName = DefinedName;
        })(sheet = grid_1.sheet || (grid_1.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid_1) {
        var sheet;
        (function (sheet_1) {
            'use strict';
            /**
             * Represents a sheet within the @see:FlexSheet control.
             */
            var Sheet = /** @class */ (function () {
                /**
                 * Initializes a new instance of the @see:Sheet class.
                 *
                 * @param owner The owner @see: FlexSheet control.
                 * @param grid The associated @see:FlexGrid control used to store the sheet data. If not specified then the
                 * new <b>FlexGrid</b> control will be created.
                 * @param sheetName The name of the sheet within the @see:FlexSheet control.
                 * @param rows The row count for the sheet.
                 * @param cols The column count for the sheet.
                 */
                function Sheet(owner, grid, sheetName, rows, cols) {
                    this._visible = true;
                    this._unboundSortDesc = new wijmo.collections.ObservableArray();
                    this._currentStyledCells = {};
                    this._currentMergedRanges = {};
                    this._isEmptyGrid = false;
                    this._rowSettings = [];
                    this._scrollPosition = new wijmo.Point();
                    this._freezeHiddenRowCnt = 0;
                    this._freezeHiddenColumnCnt = 0;
                    this._tableNames = [];
                    /**
                     * Occurs after the sheet name has changed.
                     */
                    this.nameChanged = new wijmo.Event();
                    /**
                     * Occurs after the visible of sheet has changed.
                     */
                    this.visibleChanged = new wijmo.Event();
                    var self = this, insertRows, insertCols, i;
                    self._owner = owner;
                    self._name = sheetName;
                    if (wijmo.isNumber(rows) && !isNaN(rows) && rows >= 0) {
                        self._rowCount = rows;
                    }
                    else {
                        self._rowCount = 200;
                    }
                    if (wijmo.isNumber(cols) && !isNaN(cols) && cols >= 0) {
                        self._columnCount = cols;
                    }
                    else {
                        self._columnCount = 20;
                    }
                    self._grid = grid || this._createGrid();
                    self._grid.itemsSourceChanged.addHandler(this._gridItemsSourceChanged, this);
                    // Add header row for the grid of the bind sheet.
                    self._addHeaderRow();
                    self._unboundSortDesc.collectionChanged.addHandler(function () {
                        var arr = self._unboundSortDesc, i, sd, row;
                        for (i = 0; i < arr.length; i++) {
                            sd = wijmo.tryCast(arr[i], _UnboundSortDescription);
                            if (!sd) {
                                throw 'sortDescriptions array must contain SortDescription objects.';
                            }
                        }
                        if (self._owner) {
                            self._owner.rows.beginUpdate();
                            self._owner.rows.sort(self._compareRows());
                            if (!self._owner._isUndoing) {
                                for (i = 0; i < self._owner.rows.length; i++) {
                                    row = self._owner.rows[i];
                                    if (i !== row._idx) {
                                        self._owner._updateFormulaForReorderingRows(row._idx, i);
                                    }
                                }
                            }
                            self._owner.rows.endUpdate();
                            self._owner.rows._dirty = true;
                            self._owner.rows._update();
                            // Synch with current sheet.
                            if (self._owner.selectedSheet) {
                                self._owner._copyTo(self._owner.selectedSheet);
                                self._owner._copyFrom(self._owner.selectedSheet);
                            }
                        }
                    });
                }
                Object.defineProperty(Sheet.prototype, "grid", {
                    /**
                     * Gets the associated @see:FlexGrid control used to store the sheet data.
                     */
                    get: function () {
                        if (this._grid['wj_sheetInfo'] == null) {
                            this._grid['wj_sheetInfo'] = {};
                        }
                        return this._grid;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "name", {
                    /**
                     * Gets or sets the name of the sheet.
                     */
                    get: function () {
                        return this._name;
                    },
                    set: function (value) {
                        if (!wijmo.isNullOrWhiteSpace(value) && ((this._name && this._name.toLowerCase() !== value.toLowerCase()) || !this._name)) {
                            var e = new wijmo.PropertyChangedEventArgs('sheetName', this._name, value);
                            this._name = value;
                            this.grid['wj_sheetInfo'].name = value;
                            this.onNameChanged(e);
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "visible", {
                    /**
                     * Gets or sets the sheet visibility.
                     */
                    get: function () {
                        return this._visible;
                    },
                    set: function (value) {
                        if (this._visible !== value) {
                            this._visible = value;
                            this.grid['wj_sheetInfo'].visible = value;
                            this.onVisibleChanged(new wijmo.EventArgs());
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "rowCount", {
                    /**
                     * Gets or sets the number of rows in the sheet.
                     */
                    get: function () {
                        if (this._grid != null) {
                            return this._grid.rows.length;
                        }
                        return 0;
                    },
                    set: function (value) {
                        var rowIndex;
                        if (!!this.itemsSource) {
                            return;
                        }
                        if (wijmo.isNumber(value) && !isNaN(value) && value >= 0 && this._rowCount !== value) {
                            if (this._rowCount < value) {
                                for (rowIndex = 0; rowIndex < (value - this._rowCount); rowIndex++) {
                                    this.grid.rows.push(new grid_1.Row());
                                }
                            }
                            else {
                                this.grid.rows.splice(value, this._rowCount - value);
                            }
                            this._rowCount = value;
                            // If the sheet is current selected sheet of the flexsheet, 
                            // we should synchronize the updating of the sheet to the flexsheet.
                            if (this._owner && this._owner.selectedSheet && this._name === this._owner.selectedSheet.name) {
                                this._owner._copyFrom(this, true);
                            }
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "columnCount", {
                    /**
                     * Gets or sets the number of columns in the sheet.
                     */
                    get: function () {
                        if (this._grid != null) {
                            return this._grid.columns.length;
                        }
                        return 0;
                    },
                    set: function (value) {
                        var colIndex;
                        if (!!this.itemsSource) {
                            return;
                        }
                        if (wijmo.isNumber(value) && !isNaN(value) && value >= 0 && this._columnCount !== value) {
                            if (this._columnCount < value) {
                                for (colIndex = 0; colIndex < (value - this._columnCount); colIndex++) {
                                    this._grid.columns.push(new grid_1.Column());
                                }
                            }
                            else {
                                this._grid.columns.splice(value, this._columnCount - value);
                            }
                            this._columnCount = value;
                            // If the sheet is current selected sheet of the flexsheet, 
                            // we should synchronize the updating of the sheet to the flexsheet.
                            if (this._owner && this._owner.selectedSheet && this._name === this._owner.selectedSheet.name) {
                                this._owner._copyFrom(this, true);
                            }
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "selectionRanges", {
                    /**
                     * Gets the selection array.
                     */
                    get: function () {
                        var _this = this;
                        if (!this._selectionRanges) {
                            this._selectionRanges = new wijmo.collections.ObservableArray();
                            this._selectionRanges.collectionChanged.addHandler(function () {
                                var selectionCnt, lastSelection;
                                if (_this._owner && !_this._owner._isClicking) {
                                    selectionCnt = _this._selectionRanges.length;
                                    if (selectionCnt > 0) {
                                        lastSelection = _this._selectionRanges[selectionCnt - 1];
                                        if (lastSelection && lastSelection instanceof grid_1.CellRange) {
                                            _this._owner.selection = lastSelection;
                                        }
                                    }
                                    if (selectionCnt > 1) {
                                        _this._owner._enableMulSel = true;
                                        _this._owner.refresh(false);
                                    }
                                    else {
                                        _this._owner.invalidate();
                                    }
                                    _this._owner._enableMulSel = false;
                                }
                            }, this);
                        }
                        return this._selectionRanges;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "itemsSource", {
                    /**
                     * Gets or sets the array or @see:ICollectionView for the @see:FlexGrid instance of the sheet.
                     */
                    get: function () {
                        if (this._grid != null) {
                            return this._grid.itemsSource;
                        }
                        return null;
                    },
                    set: function (value) {
                        var self = this;
                        if (self._grid == null) {
                            self._createGrid();
                            self._grid.itemsSourceChanged.addHandler(self._gridItemsSourceChanged, self);
                        }
                        if (self._isEmptyGrid) {
                            self._clearGrid();
                        }
                        self._grid.loadedRows.addHandler(function () {
                            self._addHeaderRow();
                        });
                        self._grid.itemsSource = value;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "_styledCells", {
                    /*
                     * Gets or sets the styled cells
                     * This property uses the cell index as the key and stores the @ICellStyle object as the value.
                     * { 1: { fontFamily: xxxx, fontSize: xxxx, .... }, 2: {...}, ... }
                     */
                    get: function () {
                        if (!this._currentStyledCells) {
                            this._currentStyledCells = {};
                        }
                        return this._currentStyledCells;
                    },
                    set: function (value) {
                        this._currentStyledCells = value;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "_mergedRanges", {
                    /*
                     * Gets or sets the merge ranges.
                     * This property uses the cell index as the key and stores the @CellRange object as the value.
                     * { 1: CellRange(row = 1, col = 1, row2 = 3, col2 = 4), 2: CellRange(), ...}
                     */
                    get: function () {
                        if (!this._currentMergedRanges) {
                            this._currentMergedRanges = {};
                        }
                        return this._currentMergedRanges;
                    },
                    set: function (value) {
                        this._currentMergedRanges = value;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Sheet.prototype, "tableNames", {
                    /**
                     * Gets the names of tables render in this sheet.
                     */
                    get: function () {
                        return this._tableNames;
                    },
                    enumerable: true,
                    configurable: true
                });
                /**
                 * Raises the @see:nameChanged event.
                 */
                Sheet.prototype.onNameChanged = function (e) {
                    this.nameChanged.raise(this, e);
                };
                /**
                 * Raises the @see:visibleChanged event.
                 */
                Sheet.prototype.onVisibleChanged = function (e) {
                    this.visibleChanged.raise(this, e);
                };
                /**
                 * Gets the style of specified cell.
                 *
                 * @param rowIndex the row index of the specified cell.
                 * @param columnIndex the column index of the specified cell.
                 */
                Sheet.prototype.getCellStyle = function (rowIndex, columnIndex) {
                    var cellIndex, rowCnt = this._grid.rows.length, colCnt = this._grid.columns.length;
                    if (rowIndex >= rowCnt || columnIndex >= colCnt) {
                        return null;
                    }
                    cellIndex = rowIndex * colCnt + columnIndex;
                    return this._styledCells[cellIndex];
                };
                /**
                 * Finds the table via the cell location.
                 *
                 * @param rowIndex the row index of the specified cell.
                 * @param columnIndex the column index of the specified cell.
                 */
                Sheet.prototype.findTable = function (rowIndex, columnIndex) {
                    var tableName, table, tableRange;
                    for (var i = 0; i < this.tableNames.length; i++) {
                        tableName = this.tableNames[i];
                        table = this._owner._getTable(tableName);
                        if (table != null) {
                            tableRange = table.range;
                            if (rowIndex >= tableRange.topRow && rowIndex <= tableRange.bottomRow
                                && columnIndex >= tableRange.leftCol && columnIndex <= tableRange.rightCol) {
                                return table;
                            }
                        }
                    }
                    return null;
                };
                // Attach the sheet to the @see: FlexSheet control as owner.
                Sheet.prototype._attachOwner = function (owner) {
                    if (this._owner !== owner) {
                        this._owner = owner;
                    }
                };
                // Update the sheet name with valid name.
                Sheet.prototype._setValidName = function (validName) {
                    this._name = validName;
                    this.grid['wj_sheetInfo'].name = validName;
                };
                // Store the row settings FlexSheet.
                Sheet.prototype._storeRowSettings = function () {
                    var rowIdx = 0, row;
                    this._rowSettings = [];
                    for (; rowIdx < this._grid.rows.length; rowIdx++) {
                        row = this._owner.rows[rowIdx];
                        if (row) {
                            this._rowSettings[rowIdx] = {
                                height: row.height,
                                allowMerging: row.allowMerging,
                                isCollapsed: row instanceof grid_1.GroupRow ? row.isCollapsed : null,
                                visible: row.visible
                            };
                        }
                    }
                };
                // Set the row settings to the sheet grid.
                Sheet.prototype._setRowSettings = function () {
                    var rowIdx = 0, row, rowSetting;
                    for (; rowIdx < this._rowSettings.length; rowIdx++) {
                        rowSetting = this._rowSettings[rowIdx];
                        if (rowSetting) {
                            row = this._grid.rows[rowIdx];
                            row.height = rowSetting.height;
                            row.allowMerging = rowSetting.allowMerging;
                            row.visible = rowSetting.visible;
                            if (row instanceof grid_1.GroupRow) {
                                row.isCollapsed = rowSetting.isCollapsed;
                            }
                        }
                    }
                };
                // comparison function used in rows sort for unbound sheet.
                Sheet.prototype._compareRows = function () {
                    var self = this, sortDesc = this._unboundSortDesc;
                    return function (a, b) {
                        for (var i = 0; i < sortDesc.length; i++) {
                            // get values
                            var sd = sortDesc[i], v1 = a._ubv && sd.column ? a._ubv[sd.column._hash] : '', v2 = b._ubv && sd.column ? b._ubv[sd.column._hash] : '';
                            // if the cell value is formula, we should try to evaluate this formula.
                            if (wijmo.isString(v1) && v1[0] === '=') {
                                v1 = self._owner.evaluate(v1);
                                if (v1 != null && !wijmo.isPrimitive(v1)) {
                                    v1 = v1.value;
                                }
                            }
                            if (wijmo.isString(v2) && v2[0] === '=') {
                                v2 = self._owner.evaluate(v2);
                                if (v2 != null && !wijmo.isPrimitive(v2)) {
                                    v2 = v2.value;
                                }
                            }
                            // check for NaN (isNaN returns true for NaN but also for non-numbers)
                            if (v1 !== v1)
                                v1 = null;
                            if (v2 !== v2)
                                v2 = null;
                            // ignore case when sorting  (but add the original string to keep the 
                            // strings different and the sort consistent, 'aa' between 'AA' and 'bb')
                            if (wijmo.isString(v1))
                                v1 = v1.toLowerCase() + v1;
                            if (wijmo.isString(v2))
                                v2 = v2.toLowerCase() + v2;
                            // compare the values (at last!)
                            if (v1 === '' || v1 == null) {
                                return 1;
                            }
                            if (v2 === '' || v2 == null) {
                                return -1;
                            }
                            var cmp = (v1 < v2) ? -1 : (v1 > v2) ? +1 : 0;
                            if (wijmo.isString(v1) && wijmo.isNumber(v2)) {
                                cmp = 1;
                            }
                            if (wijmo.isString(v2) && wijmo.isNumber(v1)) {
                                cmp = -1;
                            }
                            if (cmp !== 0) {
                                return sd.ascending ? +cmp : -cmp;
                            }
                        }
                        return 0;
                    };
                };
                // Create a blank flexsheet.
                Sheet.prototype._createGrid = function () {
                    var hostElement = document.createElement('div'), grid, column, colIndex, rowIndex;
                    this._isEmptyGrid = true;
                    // We should append the host element of the data grid of current sheet to body before creating data grid,
                    // this will make the host element to inherit the style of body (TFS 121713)
                    hostElement.style.visibility = 'hidden';
                    document.body.appendChild(hostElement);
                    grid = new grid_1.FlexGrid(hostElement);
                    document.body.removeChild(hostElement);
                    for (rowIndex = 0; rowIndex < this._rowCount; rowIndex++) {
                        grid.rows.push(new grid_1.Row());
                    }
                    for (colIndex = 0; colIndex < this._columnCount; colIndex++) {
                        column = new grid_1.Column();
                        // Setting the required property of the column to false for the data grid of current sheet.
                        // TFS #126125
                        column.isRequired = false;
                        grid.columns.push(column);
                    }
                    // Add sheet related info into the flexgrid.
                    // This property contains the name, style of cells and merge cells of current sheet.
                    grid['wj_sheetInfo'] = {
                        name: this.name,
                        visible: this.visible,
                        styledCells: this._styledCells,
                        mergedRanges: this._mergedRanges
                    };
                    return grid;
                };
                // Clear the grid of the sheet.
                Sheet.prototype._clearGrid = function () {
                    this._grid.rows.clear();
                    this._grid.columns.clear();
                    this._grid.columnHeaders.columns.clear();
                    this._grid.rowHeaders.rows.clear();
                };
                // Items source changed handler for the grid of the sheet.
                Sheet.prototype._gridItemsSourceChanged = function () {
                    var self = this;
                    // If the sheet is current seleced sheet of the flexsheet, we should synchronize the updating of the sheet to the flexsheet.
                    if (self._owner && self._owner.selectedSheet && self._name === self._owner.selectedSheet.name) {
                        self._owner._filter.clear();
                        self._owner._copyFrom(self, false);
                        setTimeout(function () {
                            self._owner._setFlexSheetToDirty();
                            self._owner.invalidate();
                        }, 10);
                    }
                };
                // Add header row for the bound grid.
                Sheet.prototype._addHeaderRow = function () {
                    var row, col;
                    if (this._grid.itemsSource && !(this._grid.rows[0] instanceof sheet_1.HeaderRow)) {
                        var row = new sheet_1.HeaderRow(), col;
                        for (var i = 0; i < this._grid.columns.length; i++) {
                            col = this._grid.columns[i];
                            if (!row._ubv) {
                                row._ubv = {};
                            }
                            row._ubv[col._hash] = col.header;
                        }
                        this._grid.rows.insert(0, row);
                    }
                };
                return Sheet;
            }());
            sheet_1.Sheet = Sheet;
            /**
             * Defines the collection of the @see:Sheet objects.
             */
            var SheetCollection = /** @class */ (function (_super) {
                __extends(SheetCollection, _super);
                function SheetCollection() {
                    var _this = _super !== null && _super.apply(this, arguments) || this;
                    _this._current = -1;
                    /**
                     * Occurs when the @see:SheetCollection is cleared.
                     */
                    _this.sheetCleared = new wijmo.Event();
                    /**
                     * Occurs when the <b>selectedIndex</b> property changes.
                     */
                    _this.selectedSheetChanged = new wijmo.Event();
                    /**
                     * Occurs after the name of the sheet in the collection has changed.
                     */
                    _this.sheetNameChanged = new wijmo.Event();
                    /**
                     * Occurs after the visible of the sheet in the collection has changed.
                     */
                    _this.sheetVisibleChanged = new wijmo.Event();
                    return _this;
                }
                /**
                 * Raises the sheetCleared event.
                 */
                SheetCollection.prototype.onSheetCleared = function () {
                    this.sheetCleared.raise(this, new wijmo.EventArgs());
                };
                Object.defineProperty(SheetCollection.prototype, "selectedIndex", {
                    /**
                     * Gets or sets the index of the currently selected sheet.
                     */
                    get: function () {
                        return this._current;
                    },
                    set: function (index) {
                        this._moveCurrentTo(+index);
                    },
                    enumerable: true,
                    configurable: true
                });
                /**
                 * Raises the <b>currentChanged</b> event.
                 *
                 * @param e @see:PropertyChangedEventArgs that contains the event data.
                 */
                SheetCollection.prototype.onSelectedSheetChanged = function (e) {
                    this.selectedSheetChanged.raise(this, e);
                };
                /**
                 * Inserts an item at a specific position in the array.
                 * Overrides the insert method of its base class @see:ObservableArray.
                 *
                 * @param index Position where the item will be added.
                 * @param item Item to add to the array.
                 */
                SheetCollection.prototype.insert = function (index, item) {
                    var name;
                    name = item.name ? this.getValidSheetName(item) : this._getUniqueName();
                    if (name !== item.name) {
                        item.name = name;
                    }
                    _super.prototype.insert.call(this, index, item);
                    this._postprocessSheet(item);
                };
                /**
                 * Adds one or more items to the end of the array.
                 * Overrides the push method of its base class @see:ObservableArray.
                 *
                 * @param ...item One or more items to add to the array.
                 * @return The new length of the array.
                 */
                SheetCollection.prototype.push = function () {
                    var item = [];
                    for (var _i = 0; _i < arguments.length; _i++) {
                        item[_i] = arguments[_i];
                    }
                    var currentLength = this.length, idx = 0, name;
                    for (; idx < item.length; idx++) {
                        name = item[idx].name ? this.getValidSheetName(item[idx]) : this._getUniqueName();
                        if (name !== item[idx].name) {
                            item[idx].name = name;
                        }
                        _super.prototype.push.call(this, item[idx]);
                        this._postprocessSheet(item[idx]);
                    }
                    return this.length;
                };
                /**
                 * Removes and/or adds items to the array.
                 * Overrides the splice method of its base class @see:ObservableArray.
                 *
                 * @param index Position where items will be added or removed.
                 * @param count Number of items to remove from the array.
                 * @param item Item to add to the array.
                 * @return An array containing the removed elements.
                 */
                SheetCollection.prototype.splice = function (index, count, item) {
                    var name;
                    if (item) {
                        name = item.name ? this.getValidSheetName(item) : this._getUniqueName();
                        if (name !== item.name) {
                            item.name = name;
                        }
                        this._postprocessSheet(item);
                        return _super.prototype.splice.call(this, index, count, item);
                    }
                    else {
                        return _super.prototype.splice.call(this, index, count, item);
                    }
                };
                /**
                 * Removes an item at a specific position in the array.
                 * Overrides the removeAt method of its base class @see:ObservableArray.
                 *
                 * @param index Position of the item to remove.
                 */
                SheetCollection.prototype.removeAt = function (index) {
                    var succeeded = this.hide(index);
                    if (succeeded) {
                        _super.prototype.removeAt.call(this, index);
                        if (index < this.selectedIndex) {
                            this._current -= 1;
                        }
                    }
                };
                /**
                 * Raises the <b>sheetNameChanged</b> event.
                 */
                SheetCollection.prototype.onSheetNameChanged = function (e) {
                    this.sheetNameChanged.raise(this, e);
                };
                /**
                 * Raises the <b>sheetVisibleChanged</b> event.
                 */
                SheetCollection.prototype.onSheetVisibleChanged = function (e) {
                    this.sheetVisibleChanged.raise(this, e);
                };
                /**
                 * Selects the first sheet in the @see:FlexSheet control.
                 */
                SheetCollection.prototype.selectFirst = function () {
                    return this._moveCurrentTo(0);
                };
                /**
                 * Selects the last sheet in the owner @see:FlexSheet control.
                 */
                SheetCollection.prototype.selectLast = function () {
                    return this._moveCurrentTo(this.length - 1);
                };
                /**
                 * Selects the previous sheet in the owner @see:FlexSheet control.
                 */
                SheetCollection.prototype.selectPrevious = function () {
                    return this._moveCurrentTo(this._current - 1);
                };
                /**
                 * Select the next sheet in the owner @see:FlexSheet control.
                 */
                SheetCollection.prototype.selectNext = function () {
                    return this._moveCurrentTo(this._current + 1);
                };
                /**
                 * Hides the sheet at the specified position.
                 *
                 * @param pos The position of the sheet to hide.
                 */
                SheetCollection.prototype.hide = function (pos) {
                    var succeeded = false;
                    if (pos < 0 && pos >= this.length) {
                        return false;
                    }
                    if (!this[pos].visible) {
                        return false;
                    }
                    this[pos].visible = false;
                    return true;
                };
                /**
                 * Unhide and selects the @see:Sheet at the specified position.
                 *
                 * @param pos The position of the sheet to show.
                 */
                SheetCollection.prototype.show = function (pos) {
                    var succeeded = false;
                    if (pos < 0 && pos >= this.length) {
                        return false;
                    }
                    this[pos].visible = true;
                    this._moveCurrentTo(pos);
                    return true;
                };
                /**
                 * Clear the SheetCollection.
                 */
                SheetCollection.prototype.clear = function () {
                    _super.prototype.clear.call(this);
                    this._current = -1;
                    this.onSheetCleared();
                };
                /**
                 * Checks whether the sheet name is valid.
                 *
                 * @param sheet The @see:Sheet for which the name needs to check.
                 */
                SheetCollection.prototype.isValidSheetName = function (sheet) {
                    var sheetIndex = this._getSheetIndexFrom(sheet.name), currentSheetIndex = this.indexOf(sheet);
                    return (sheetIndex === -1 || sheetIndex === currentSheetIndex);
                };
                /**
                 * Gets the valid name for the sheet.
                 *
                 * @param currentSheet The @see:Sheet need get the valid name.
                 */
                SheetCollection.prototype.getValidSheetName = function (currentSheet) {
                    var validName = currentSheet.name, index = 1, currentSheetIndex = this.indexOf(currentSheet), sheetIndex;
                    do {
                        sheetIndex = this._getSheetIndexFrom(validName);
                        if (sheetIndex === -1 || sheetIndex === currentSheetIndex) {
                            break;
                        }
                        else {
                            validName = currentSheet.name.concat((index + 1).toString());
                        }
                        index = index + 1;
                    } while (true);
                    return validName;
                };
                // Move the current index to indicated position.
                SheetCollection.prototype._moveCurrentTo = function (pos) {
                    var searchedPos = pos, e;
                    if (pos < 0 || pos >= this.length) {
                        return false;
                    }
                    if (this._current < searchedPos || searchedPos === 0) {
                        while (searchedPos < this.length && !this[searchedPos].visible) {
                            searchedPos++;
                        }
                    }
                    else if (this._current > searchedPos) {
                        while (searchedPos >= 0 && !this[searchedPos].visible) {
                            searchedPos--;
                        }
                    }
                    if (searchedPos === this.length) {
                        searchedPos = pos;
                        while (searchedPos >= 0 && !this[searchedPos].visible) {
                            searchedPos--;
                        }
                    }
                    if (searchedPos < 0) {
                        return false;
                    }
                    if (searchedPos !== this._current) {
                        e = new wijmo.PropertyChangedEventArgs('sheetIndex', this._current, searchedPos);
                        this._current = searchedPos;
                        this.onSelectedSheetChanged(e);
                    }
                    return true;
                };
                // Get the index for the sheet in the SheetCollection.
                SheetCollection.prototype._getSheetIndexFrom = function (sheetName) {
                    var result = -1, sheet, name;
                    if (!sheetName) {
                        return result;
                    }
                    sheetName = sheetName.toLowerCase();
                    for (var i = 0; i < this.length; i++) {
                        sheet = this[i];
                        name = sheet.name ? sheet.name.toLowerCase() : '';
                        if (name === sheetName) {
                            return i;
                        }
                    }
                    return result;
                };
                // Post process the newly added sheet. 
                SheetCollection.prototype._postprocessSheet = function (item) {
                    var self = this;
                    // Update the sheet name via the sheetNameChanged event handler.
                    item.nameChanged.addHandler(function () {
                        var e, index = self._getSheetIndexFrom(item.name);
                        if (!self.isValidSheetName(item)) {
                            item._setValidName(self.getValidSheetName(item));
                        }
                        e = new wijmo.collections.NotifyCollectionChangedEventArgs(wijmo.collections.NotifyCollectionChangedAction.Change, item, wijmo.isNumber(index) ? index : self.length - 1);
                        self.onSheetNameChanged(e);
                    });
                    item.visibleChanged.addHandler(function () {
                        var index = self._getSheetIndexFrom(item.name), e = new wijmo.collections.NotifyCollectionChangedEventArgs(wijmo.collections.NotifyCollectionChangedAction.Change, item, wijmo.isNumber(index) ? index : self.length - 1);
                        self.onSheetVisibleChanged(e);
                    });
                };
                // Get the unique name for the sheet in the SheetCollection.
                SheetCollection.prototype._getUniqueName = function () {
                    var validName = 'Sheet1', index = 2;
                    do {
                        if (this._getSheetIndexFrom(validName) === -1) {
                            break;
                        }
                        else {
                            validName = 'Sheet' + index;
                        }
                        index = index + 1;
                    } while (true);
                    return validName;
                };
                return SheetCollection;
            }(wijmo.collections.ObservableArray));
            sheet_1.SheetCollection = SheetCollection;
            /*
             * Represents the control that shows tabs for switching between @see:FlexSheet sheets.
             */
            var _SheetTabs = /** @class */ (function (_super) {
                __extends(_SheetTabs, _super);
                /*
                 * Initializes a new instance of the @see:_SheetTabs class.
                 *
                 * @param element The DOM element that will host the control, or a selector for the host element (e.g. '#theCtrl').
                 * @param owner The @see: FlexSheet control what the SheetTabs control works with.
                 * @param options JavaScript object containing initialization data for the control.
                 */
                function _SheetTabs(element, owner, options) {
                    var _this = _super.call(this, element, options) || this;
                    _this._rtl = false;
                    _this._sheetTabClicked = false;
                    var self = _this;
                    self._owner = owner;
                    self._sheets = owner.sheets;
                    self._rtl = getComputedStyle(self._owner.hostElement).direction == 'rtl';
                    if (self.hostElement.attributes['tabindex']) {
                        self.hostElement.attributes.removeNamedItem('tabindex');
                    }
                    self._initControl();
                    self.deferUpdate(function () {
                        if (options) {
                            self.initialize(options);
                        }
                    });
                    return _this;
                }
                /*
                 * Override to refresh the control.
                 *
                 * @param fullUpdate Whether to update the control layout as well as the content.
                 */
                _SheetTabs.prototype.refresh = function (fullUpdate) {
                    this._tabContainer.innerHTML = '';
                    this._tabContainer.innerHTML = this._getSheetTabs();
                    if (this._rtl) {
                        this._adjustSheetsPosition();
                    }
                    this._adjustSize();
                };
                // The items source changed event handler.
                _SheetTabs.prototype._sourceChanged = function (sender, e) {
                    if (e === void 0) { e = wijmo.collections.NotifyCollectionChangedEventArgs.reset; }
                    var eArgs = e, index;
                    switch (eArgs.action) {
                        case wijmo.collections.NotifyCollectionChangedAction.Add:
                            index = eArgs.index - 1;
                            if (index < 0) {
                                index = 0;
                            }
                            this._tabContainer.innerHTML = '';
                            this._tabContainer.innerHTML = this._getSheetTabs();
                            if (this._rtl) {
                                this._adjustSheetsPosition();
                            }
                            this._adjustSize();
                            break;
                        case wijmo.collections.NotifyCollectionChangedAction.Remove:
                            this._tabContainer.removeChild(this._tabContainer.children[eArgs.index]);
                            if (this._tabContainer.hasChildNodes()) {
                                this._updateTabActive(eArgs.index, true);
                            }
                            this._adjustSize();
                            break;
                        default:
                            this.invalidate();
                            break;
                    }
                };
                // The current changed of the item source event handler.
                _SheetTabs.prototype._selectedSheetChanged = function (sender, e) {
                    this._updateTabActive(e.oldValue, false);
                    this._updateTabActive(e.newValue, true);
                    if (this._sheetTabClicked) {
                        this._sheetTabClicked = false;
                    }
                    else {
                        this._scrollToActiveSheet(e.newValue, e.oldValue);
                    }
                    this._adjustSize();
                };
                // Initialize the SheetTabs control.
                _SheetTabs.prototype._initControl = function () {
                    var self = this;
                    //apply template
                    self.applyTemplate('', self.getTemplate(), {
                        _sheetContainer: 'sheet-container',
                        _tabContainer: 'container',
                        _sheetPage: 'sheet-page',
                        _newSheet: 'new-sheet'
                    });
                    //init opts
                    if (self._rtl) {
                        self._sheetPage.style.right = '0px';
                        self._tabContainer.parentElement.style.right = self._sheetPage.clientWidth + 'px';
                        self._tabContainer.style.right = '0px';
                        self._tabContainer.style.cssFloat = 'right';
                        self._newSheet.style.right = (self._sheetPage.clientWidth + self._tabContainer.parentElement.clientWidth) + 'px';
                    }
                    self._adjustNavigationButtons(self._rtl);
                    self.addEventListener(self._newSheet, 'click', function (evt) {
                        var oldIndex = self._owner.selectedSheetIndex;
                        self._owner.addUnboundSheet();
                        self._scrollToActiveSheet(self._owner.selectedSheetIndex, oldIndex);
                    });
                    self._sheets.collectionChanged.addHandler(self._sourceChanged, self);
                    self._sheets.selectedSheetChanged.addHandler(self._selectedSheetChanged, self);
                    self._sheets.sheetNameChanged.addHandler(self._updateSheetName, self);
                    self._sheets.sheetVisibleChanged.addHandler(self._updateTabShown, self);
                    self._initSheetPage();
                    self._initSheetTab();
                };
                // Initialize the sheet tab part.
                _SheetTabs.prototype._initSheetTab = function () {
                    var self = this;
                    self.addEventListener(self._tabContainer, 'mousedown', function (evt) {
                        var li = evt.target, idx;
                        if (li instanceof HTMLLIElement) {
                            self._sheetTabClicked = true;
                            idx = self._getItemIndex(self._tabContainer, li);
                            self._scrollSheetTabContainer(li);
                            if (idx > -1) {
                                self._sheets.selectedIndex = idx;
                            }
                        }
                    });
                    //todo
                    //contextmenu
                };
                // Initialize the sheet pager part.
                _SheetTabs.prototype._initSheetPage = function () {
                    var self = this;
                    self.hostElement.querySelector('div.wj-sheet-page').addEventListener('click', function (e) {
                        var btn = e.target.toString() === '[object HTMLButtonElement]' ? e.target : e.target.parentElement, index = self._getItemIndex(self._sheetPage, btn), currentSheetTab;
                        if (self._sheets.length === 0) {
                            return;
                        }
                        switch (index) {
                            case 0:
                                self._sheets.selectFirst();
                                break;
                            case 1:
                                self._sheets.selectPrevious();
                                break;
                            case 2:
                                self._sheets.selectNext();
                                break;
                            case 3:
                                self._sheets.selectLast();
                                break;
                        }
                    });
                };
                // Get markup for the sheet tabs
                _SheetTabs.prototype._getSheetTabs = function () {
                    var html = '', i;
                    for (i = 0; i < this._sheets.length; i++) {
                        html += this._getSheetElement(this._sheets[i], this._sheets.selectedIndex === i);
                    }
                    return html;
                };
                // Get the markup for a sheet tab.
                _SheetTabs.prototype._getSheetElement = function (sheetItem, isActive) {
                    if (isActive === void 0) { isActive = false; }
                    var result = '<li';
                    if (!sheetItem.visible) {
                        result += ' class="hidden"';
                    }
                    else if (isActive) {
                        result += ' class="active"';
                    }
                    result += '>' + sheetItem.name + '</li>';
                    return result;
                };
                // Update the active state for the sheet tabs.
                _SheetTabs.prototype._updateTabActive = function (pos, active) {
                    if (pos < 0 || pos >= this._tabContainer.children.length) {
                        return;
                    }
                    if (active) {
                        wijmo.addClass(this._tabContainer.children[pos], 'active');
                    }
                    else {
                        wijmo.removeClass(this._tabContainer.children[pos], 'active');
                    }
                };
                // Update the show or hide state for the sheet tabs
                _SheetTabs.prototype._updateTabShown = function (sender, e) {
                    if (e.index < 0 || e.index >= this._tabContainer.children.length) {
                        return;
                    }
                    if (!e.item.visible) {
                        wijmo.addClass(this._tabContainer.children[e.index], 'hidden');
                    }
                    else {
                        wijmo.removeClass(this._tabContainer.children[e.index], 'hidden');
                    }
                    this._adjustSize();
                };
                // Adjust the size of the SheetTabs control.
                _SheetTabs.prototype._adjustSize = function () {
                    //adjust the size
                    var sheetCount = this._tabContainer.childElementCount, index, containerMaxWidth, width = 0, scrollLeft = 0;
                    if (this.hostElement.style.display === 'none') {
                        return;
                    }
                    // Get the scroll left of the tab container, before setting the size of the size of the tab container. (TFS 142788)
                    scrollLeft = this._tabContainer.parentElement.scrollLeft;
                    // Before adjusting the size of the sheet tab, we should reset the size to ''. (TFS #139846)
                    this._tabContainer.parentElement.style.width = '';
                    this._tabContainer.style.width = '';
                    this._sheetPage.parentElement.style.width = '';
                    for (index = 0; index < sheetCount; index++) {
                        width += this._tabContainer.children[index].offsetWidth + 1;
                    }
                    containerMaxWidth = this.hostElement.offsetWidth - this._sheetPage.offsetWidth - this._newSheet.offsetWidth - 2;
                    this._tabContainer.parentElement.style.width = (width > containerMaxWidth ? containerMaxWidth : width) + 'px';
                    this._tabContainer.style.width = width + 'px';
                    this._sheetPage.parentElement.style.width = this._sheetPage.offsetWidth + this._newSheet.offsetWidth + this._tabContainer.parentElement.offsetWidth + 3 + 'px';
                    // Reset the scroll left for the tab container. (TFS 142788)
                    this._tabContainer.parentElement.scrollLeft = scrollLeft;
                };
                // Get the index of the element in its parent container.
                _SheetTabs.prototype._getItemIndex = function (container, item) {
                    var idx = 0;
                    for (; idx < container.children.length; idx++) {
                        if (container.children[idx] === item) {
                            return idx;
                        }
                    }
                    return -1;
                };
                // Update the sheet tab name.
                _SheetTabs.prototype._updateSheetName = function (sender, e) {
                    this._tabContainer.querySelectorAll('li')[e.index].textContent = e.item.name;
                    this._adjustSize();
                };
                // Scroll the sheet tab container to display the invisible or partial visible sheet tab.
                _SheetTabs.prototype._scrollSheetTabContainer = function (currentSheetTab) {
                    var scrollLeft = this._tabContainer.parentElement.scrollLeft, sheetPageSize = this._sheetPage.offsetWidth, newSheetSize = this._newSheet.offsetWidth, containerSize = this._tabContainer.parentElement.offsetWidth, containerOffset;
                    if (this._rtl) {
                        switch (grid_1.FlexGrid['_getRtlMode']()) {
                            case 'rev':
                                containerOffset = -this._tabContainer.offsetLeft;
                                if (containerOffset + currentSheetTab.offsetLeft + currentSheetTab.offsetWidth > containerSize + scrollLeft) {
                                    this._tabContainer.parentElement.scrollLeft += currentSheetTab.offsetWidth;
                                }
                                else if (containerOffset + currentSheetTab.offsetLeft < scrollLeft) {
                                    this._tabContainer.parentElement.scrollLeft -= currentSheetTab.offsetWidth;
                                }
                                break;
                            case 'neg':
                                if (currentSheetTab.offsetLeft < scrollLeft) {
                                    this._tabContainer.parentElement.scrollLeft -= currentSheetTab.offsetWidth;
                                }
                                else if (currentSheetTab.offsetLeft + currentSheetTab.offsetWidth > containerSize + scrollLeft) {
                                    this._tabContainer.parentElement.scrollLeft += currentSheetTab.offsetWidth;
                                }
                                break;
                            default:
                                if (currentSheetTab.offsetLeft - newSheetSize + scrollLeft < 0) {
                                    this._tabContainer.parentElement.scrollLeft += currentSheetTab.offsetWidth;
                                }
                                else if (currentSheetTab.offsetLeft + currentSheetTab.offsetWidth - newSheetSize + scrollLeft > containerSize) {
                                    this._tabContainer.parentElement.scrollLeft -= currentSheetTab.offsetWidth;
                                }
                                break;
                        }
                    }
                    else {
                        if (currentSheetTab.offsetLeft + currentSheetTab.offsetWidth - sheetPageSize > containerSize + scrollLeft) {
                            this._tabContainer.parentElement.scrollLeft += currentSheetTab.offsetWidth;
                        }
                        else if (currentSheetTab.offsetLeft - sheetPageSize < scrollLeft) {
                            this._tabContainer.parentElement.scrollLeft -= currentSheetTab.offsetWidth;
                        }
                    }
                };
                // Adjust the position of each sheet tab for 'rtl' direction.
                _SheetTabs.prototype._adjustSheetsPosition = function () {
                    var sheets = this._tabContainer.querySelectorAll('li'), position = 0, sheet, index;
                    for (index = 0; index < sheets.length; index++) {
                        sheet = sheets[index];
                        sheet.style.cssFloat = 'right';
                        sheet.style.right = position + 'px';
                        position += sheets[index].clientWidth;
                    }
                };
                // Scroll to the active sheet tab.
                _SheetTabs.prototype._scrollToActiveSheet = function (newIndex, oldIndex) {
                    var sheets = this._tabContainer.querySelectorAll('li'), activeSheet, scrollLeft, i;
                    if (this._tabContainer.clientWidth > this._tabContainer.parentElement.clientWidth) {
                        scrollLeft = this._tabContainer.clientWidth - this._tabContainer.parentElement.clientWidth;
                    }
                    else {
                        scrollLeft = 0;
                    }
                    if (sheets.length > 0 && newIndex < sheets.length && oldIndex < sheets.length) {
                        if ((newIndex === 0 && !this._rtl) || (newIndex === sheets.length - 1 && this._rtl)) {
                            if (this._rtl) {
                                switch (grid_1.FlexGrid['_getRtlMode']()) {
                                    case 'rev':
                                        this._tabContainer.parentElement.scrollLeft = 0;
                                        break;
                                    case 'neg':
                                        this._tabContainer.parentElement.scrollLeft = -scrollLeft;
                                        break;
                                    default:
                                        this._tabContainer.parentElement.scrollLeft = scrollLeft;
                                        break;
                                }
                            }
                            else {
                                this._tabContainer.parentElement.scrollLeft = 0;
                            }
                            return;
                        }
                        if ((newIndex === 0 && this._rtl) || (newIndex === sheets.length - 1 && !this._rtl)) {
                            if (this._rtl) {
                                switch (grid_1.FlexGrid['_getRtlMode']()) {
                                    case 'rev':
                                        this._tabContainer.parentElement.scrollLeft = scrollLeft;
                                        break;
                                    case 'neg':
                                        this._tabContainer.parentElement.scrollLeft = 0;
                                        break;
                                    default:
                                        this._tabContainer.parentElement.scrollLeft = 0;
                                        break;
                                }
                            }
                            else {
                                this._tabContainer.parentElement.scrollLeft = scrollLeft;
                            }
                            return;
                        }
                        if (newIndex >= oldIndex) {
                            for (i = oldIndex + 1; i <= newIndex; i++) {
                                activeSheet = sheets[i];
                                this._scrollSheetTabContainer(activeSheet);
                            }
                        }
                        else {
                            for (i = oldIndex - 1; i >= newIndex; i--) {
                                activeSheet = sheets[i];
                                this._scrollSheetTabContainer(activeSheet);
                            }
                        }
                    }
                };
                // Adjust the direction for sheet navigation buttons' glyph.
                _SheetTabs.prototype._adjustNavigationButtons = function (rtl) {
                    var navBtns = this.hostElement.querySelectorAll('.wj-sheet-page button'), btnGlyph;
                    if (navBtns && navBtns.length === 4) {
                        if (rtl) {
                            btnGlyph = navBtns[0].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-step-backward');
                            wijmo.addClass(btnGlyph, 'wj-glyph-step-backward-rtl');
                            btnGlyph = navBtns[1].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-left');
                            wijmo.addClass(btnGlyph, 'wj-glyph-left-rtl');
                            btnGlyph = navBtns[2].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-right');
                            wijmo.addClass(btnGlyph, 'wj-glyph-right-rtl');
                            btnGlyph = navBtns[3].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-step-forward');
                            wijmo.addClass(btnGlyph, 'wj-glyph-step-forward-rtl');
                        }
                        else {
                            btnGlyph = navBtns[0].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-step-backward-rtl');
                            wijmo.addClass(btnGlyph, 'wj-glyph-step-backward');
                            btnGlyph = navBtns[1].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-left-rtl');
                            wijmo.addClass(btnGlyph, 'wj-glyph-left');
                            btnGlyph = navBtns[2].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-right-rtl');
                            wijmo.addClass(btnGlyph, 'wj-glyph-right');
                            btnGlyph = navBtns[3].querySelector('span');
                            wijmo.removeClass(btnGlyph, 'wj-glyph-step-forward-rtl');
                            wijmo.addClass(btnGlyph, 'wj-glyph-step-forward');
                        }
                    }
                };
                _SheetTabs.controlTemplate = '<div wj-part="sheet-container" class="wj-sheet" style="height:100%;position:relative">' +
                    '<div wj-part="sheet-page" class="wj-btn-group wj-sheet-page">' + // Sheets pageg
                    '<button type="button" class="wj-btn wj-btn-default">' +
                    '<span class="wj-sheet-icon wj-glyph-step-backward"></span>' +
                    '</button>' +
                    '<button type="button" class="wj-btn wj-btn-default">' +
                    '<span class="wj-sheet-icon wj-glyph-left"></span>' +
                    '</button>' +
                    '<button type="button" class="wj-btn wj-btn-default">' +
                    '<span class="wj-sheet-icon wj-glyph-right"></span>' +
                    '</button>' +
                    '<button type="button" class="wj-btn wj-btn-default">' +
                    '<span class="wj-sheet-icon wj-glyph-step-forward"></span>' +
                    '</button>' +
                    '</div>' +
                    '<div class="wj-sheet-tab" style="height:100%;overflow:hidden">' + //Sheet Tabs
                    '<ul wj-part="container"></ul>' +
                    '</div>' +
                    '<div wj-part="new-sheet" class="wj-new-sheet"><span class="wj-sheet-icon wj-glyph-file"></span></div>' +
                    '</div>';
                return _SheetTabs;
            }(wijmo.Control));
            sheet_1._SheetTabs = _SheetTabs;
            /*
             * Defines the class defining @see:FlexSheet column sorting criterion.
             */
            var _UnboundSortDescription = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:UnboundSortDescription class.
                 *
                 * @param column The column to sort the rows by.
                 * @param ascending The sort order.
                 */
                function _UnboundSortDescription(column, ascending) {
                    this._column = column;
                    this._ascending = ascending;
                }
                Object.defineProperty(_UnboundSortDescription.prototype, "column", {
                    /*
                     * Gets the column to sort the rows by.
                     */
                    get: function () {
                        return this._column;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(_UnboundSortDescription.prototype, "ascending", {
                    /*
                     * Gets the sort order.
                     */
                    get: function () {
                        return this._ascending;
                    },
                    enumerable: true,
                    configurable: true
                });
                return _UnboundSortDescription;
            }());
            sheet_1._UnboundSortDescription = _UnboundSortDescription;
        })(sheet = grid_1.sheet || (grid_1.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /**
             * Maintains sorting of the selected @see:Sheet of the @see:FlexSheet.
             */
            var SortManager = /** @class */ (function () {
                /**
                 * Initializes a new instance of the @see:SortManager class.
                 *
                 * @param owner The @see:FlexSheet control that owns this <b>SortManager</b>.
                 */
                function SortManager(owner) {
                    this._owner = owner;
                    this._sortDescriptions = new wijmo.collections.CollectionView();
                    this._committedList = [new ColumnSortDescription(-1, true)];
                    this._sortDescriptions.newItemCreator = function () {
                        return new ColumnSortDescription(-1, true);
                    };
                    this._refresh();
                }
                Object.defineProperty(SortManager.prototype, "sortDescriptions", {
                    /**
                     * Gets or sets the collection of the sort descriptions represented by the  @see:ColumnSortDescription objects.
                     */
                    get: function () {
                        return this._sortDescriptions;
                    },
                    set: function (value) {
                        this._sortDescriptions = value;
                        this.commitSort(true);
                        this._refresh();
                    },
                    enumerable: true,
                    configurable: true
                });
                /**
                 * Adds a blank sorting level to the sort descriptions.
                 *
                 * @param columnIndex The index of the column in the FlexSheet control.
                 * @param ascending The sort order for the sort level.
                 */
                SortManager.prototype.addSortLevel = function (columnIndex, ascending) {
                    if (ascending === void 0) { ascending = true; }
                    var item = this._sortDescriptions.addNew();
                    if (columnIndex != null && !isNaN(columnIndex) && wijmo.isInt(columnIndex)) {
                        item.columnIndex = columnIndex;
                    }
                    item.ascending = ascending;
                    this._sortDescriptions.commitNew();
                };
                /**
                 * Removes the current sorting level from the sort descriptions.
                 *
                 * @param columnIndex The index of the column in the FlexSheet control.
                 */
                SortManager.prototype.deleteSortLevel = function (columnIndex) {
                    var item;
                    if (columnIndex != null) {
                        item = this._getSortItem(columnIndex);
                    }
                    else {
                        item = this._sortDescriptions.currentItem;
                    }
                    if (item) {
                        this._sortDescriptions.remove(item);
                    }
                };
                /**
                 * Adds a copy of the current sorting level to the sort descriptions.
                 */
                SortManager.prototype.copySortLevel = function () {
                    var item = this._sortDescriptions.currentItem;
                    if (item) {
                        var newItem = this._sortDescriptions.addNew();
                        newItem.columnIndex = parseInt(item.columnIndex);
                        newItem.ascending = item.ascending;
                        this._sortDescriptions.commitNew();
                    }
                };
                /**
                 * Updates the current sort level.
                 *
                 * @param columnIndex The column index for the sort level.
                 * @param ascending The sort order for the sort level.
                 */
                SortManager.prototype.editSortLevel = function (columnIndex, ascending) {
                    if (columnIndex != null) {
                        this._sortDescriptions.currentItem.columnIndex = columnIndex;
                    }
                    if (ascending != null) {
                        this._sortDescriptions.currentItem.ascending = ascending;
                    }
                };
                /**
                 * Moves the current sorting level to a new position.
                 *
                 * @param offset The offset to move the current level by.
                 */
                SortManager.prototype.moveSortLevel = function (offset) {
                    var item = this._sortDescriptions.currentItem;
                    if (item) {
                        var arr = this._sortDescriptions.sourceCollection, index = arr.indexOf(item), newIndex = index + offset;
                        if (index > -1 && newIndex > -1) {
                            arr.splice(index, 1);
                            arr.splice(newIndex, 0, item);
                            this._sortDescriptions.refresh();
                            this._sortDescriptions.moveCurrentTo(item);
                        }
                    }
                };
                /**
                 * Check whether the sort item of specific column exists or not
                 *
                 * @param columnIndex The index of the column in the FlexSheet control.
                 */
                SortManager.prototype.checkSortItemExists = function (columnIndex) {
                    var i = 0, sortItemCnt = this._sortDescriptions.itemCount, sortItem;
                    for (; i < sortItemCnt; i++) {
                        sortItem = this._sortDescriptions.items[i];
                        if (+sortItem.columnIndex === columnIndex) {
                            return i;
                        }
                    }
                    return -1;
                };
                /**
                 * Commits the current sort descriptions to the FlexSheet control.
                 *
                 * @param undoable The boolean value indicating whether the commit sort action is undoable.
                 */
                SortManager.prototype.commitSort = function (undoable) {
                    var _this = this;
                    if (undoable === void 0) { undoable = true; }
                    var sd, newSortDesc, bindSortDesc, dataBindSortDesc, i, unSortDesc, sortAction, unboundRows, ecv, isCVItemsSource = this._owner.itemsSource && this._owner.itemsSource instanceof wijmo.collections.CollectionView;
                    if (!this._owner.selectedSheet) {
                        return;
                    }
                    this._owner._needCopyToSheet = false;
                    unSortDesc = this._owner.selectedSheet._unboundSortDesc;
                    if (undoable) {
                        sortAction = new sheet._SortColumnAction(this._owner);
                    }
                    if (this._sortDescriptions.itemCount > 0) {
                        this._committedList = this._cloneSortList(this._sortDescriptions.items);
                    }
                    else {
                        this._committedList = [new ColumnSortDescription(-1, true)];
                    }
                    if (this._owner.collectionView) {
                        ecv = this._owner.editableCollectionView;
                        if (ecv && ecv.currentEditItem && (ecv.items.indexOf(ecv.currentEditItem) !== -1 && !this._isEmpty(ecv.currentEditItem))) {
                            ecv.commitEdit();
                        }
                        // Try to get the unbound row in the bound sheet.
                        unboundRows = this._scanUnboundRows();
                        // Update sorting for the bind booksheet
                        this._owner.collectionView.beginUpdate();
                        this._owner.selectedSheet.grid.collectionView.beginUpdate();
                        bindSortDesc = this._owner.collectionView.sortDescriptions;
                        bindSortDesc.clear();
                        // Synch the sorts for the grid of current sheet.
                        if (isCVItemsSource === false) {
                            dataBindSortDesc = this._owner.selectedSheet.grid.collectionView.sortDescriptions;
                            dataBindSortDesc.clear();
                        }
                        for (i = 0; i < this._sortDescriptions.itemCount; i++) {
                            sd = this._sortDescriptions.items[i];
                            if (sd.columnIndex > -1) {
                                newSortDesc = new wijmo.collections.SortDescription(this._owner.columns[sd.columnIndex].binding, sd.ascending);
                                bindSortDesc.push(newSortDesc);
                                // Synch the sorts for the grid of current sheet.
                                if (isCVItemsSource === false) {
                                    dataBindSortDesc.push(newSortDesc);
                                }
                            }
                        }
                        this._owner.selectedSheet.selectionRanges.clear();
                        this._owner.collectionView.endUpdate();
                        this._owner.selectedSheet.grid.collectionView.endUpdate();
                        // Re-insert the unbound row into the sheet.
                        if (unboundRows) {
                            Object.keys(unboundRows).forEach(function (key) {
                                _this._owner.rows.splice(+key, 0, unboundRows[key]);
                            });
                        }
                    }
                    else {
                        // Update sorting for the unbound booksheet.
                        unSortDesc.clear();
                        for (i = 0; i < this._sortDescriptions.itemCount; i++) {
                            sd = this._sortDescriptions.items[i];
                            if (sd.columnIndex > -1) {
                                unSortDesc.push(new sheet._UnboundSortDescription(this._owner.columns[sd.columnIndex], sd.ascending));
                            }
                        }
                    }
                    if (undoable) {
                        sortAction.saveNewState();
                        this._owner.undoStack._addAction(sortAction);
                    }
                    this._owner._copiedRanges = null;
                    this._owner._needCopyToSheet = true;
                };
                /**
                 * Cancel the current sort descriptions to the FlexSheet control.
                 */
                SortManager.prototype.cancelSort = function () {
                    this._sortDescriptions.sourceCollection = this._committedList.slice();
                    this._refresh();
                };
                /**
                 * Clear the sort descriptions.
                 */
                SortManager.prototype.clearSort = function () {
                    this._sortDescriptions.sourceCollection = [];
                    this.commitSort();
                };
                // Updates the <b>sorts</b> collection based on the current @see:Sheet sort conditions.
                SortManager.prototype._refresh = function () {
                    var sortList = [], i, sd;
                    if (!this._owner.selectedSheet) {
                        return;
                    }
                    if (this._owner.collectionView && this._owner.collectionView.sortDescriptions.length > 0) {
                        for (i = 0; i < this._owner.collectionView.sortDescriptions.length; i++) {
                            sd = this._owner.collectionView.sortDescriptions[i];
                            sortList.push(new ColumnSortDescription(this._getColumnIndex(sd.property), sd.ascending));
                        }
                    }
                    else if (this._owner.selectedSheet && this._owner.selectedSheet._unboundSortDesc.length > 0) {
                        for (i = 0; i < this._owner.selectedSheet._unboundSortDesc.length; i++) {
                            sd = this._owner.selectedSheet._unboundSortDesc[i];
                            if (sd.column != null) {
                                sortList.push(new ColumnSortDescription(sd.column.index, sd.ascending));
                            }
                        }
                    }
                    else {
                        sortList.push(new ColumnSortDescription(-1, true));
                    }
                    this._sortDescriptions.sourceCollection = sortList;
                };
                // Get the index of the column by the binding property.
                SortManager.prototype._getColumnIndex = function (property) {
                    var i = 0, colCnt = this._owner.columns.length;
                    for (; i < colCnt; i++) {
                        if (this._owner.columns[i].binding === property) {
                            return i;
                        }
                    }
                    return -1;
                };
                // Get the sort item via the column index
                SortManager.prototype._getSortItem = function (columnIndex) {
                    var index = this.checkSortItemExists(columnIndex);
                    if (index > -1) {
                        return this._sortDescriptions.items[index];
                    }
                    return undefined;
                };
                // Scan the unbound row of the bound sheet.
                SortManager.prototype._scanUnboundRows = function () {
                    var rowIndex, processingRow, unboundRows;
                    for (rowIndex = 0; rowIndex < this._owner.rows.length; rowIndex++) {
                        processingRow = this._owner.rows[rowIndex];
                        if (!processingRow.dataItem) {
                            if (!(processingRow instanceof sheet.HeaderRow) && !(processingRow instanceof grid._NewRowTemplate)) {
                                if (!unboundRows) {
                                    unboundRows = {};
                                }
                                unboundRows[rowIndex] = processingRow;
                            }
                        }
                    }
                    return unboundRows;
                };
                // Clone the sort list.
                SortManager.prototype._cloneSortList = function (sortList) {
                    var cloneSortList = [];
                    for (var i = 0; i < sortList.length; i++) {
                        cloneSortList[i] = sortList[i].clone();
                    }
                    return cloneSortList;
                };
                // Check whether is empty object.
                SortManager.prototype._isEmpty = function (obj) {
                    // Speed up calls to hasOwnProperty
                    var hasOwnProperty = Object.prototype.hasOwnProperty;
                    // null and undefined are "empty"
                    if (obj == null) {
                        return true;
                    }
                    // Assume if it has a length property with a non-zero value
                    // that that property is correct.
                    if (obj.length > 0) {
                        return false;
                    }
                    if (obj.length === 0) {
                        return true;
                    }
                    // Otherwise, does it have any properties of its own?
                    // Note that this doesn't handle
                    // toString and valueOf enumeration bugs in IE < 9
                    for (var key in obj) {
                        if (hasOwnProperty.call(obj, key)) {
                            return false;
                        }
                    }
                    return true;
                };
                return SortManager;
            }());
            sheet.SortManager = SortManager;
            /**
             * Describes a @see:FlexSheet column sorting criterion.
             */
            var ColumnSortDescription = /** @class */ (function () {
                /**
                 * Initializes a new instance of the @see:ColumnSortDescription class.
                 *
                 * @param columnIndex Indicates which column to sort the rows by.
                 * @param ascending The sort order.
                 */
                function ColumnSortDescription(columnIndex, ascending) {
                    this._columnIndex = columnIndex;
                    this._ascending = ascending;
                }
                Object.defineProperty(ColumnSortDescription.prototype, "columnIndex", {
                    /**
                     * Gets or sets the column index.
                     */
                    get: function () {
                        return this._columnIndex;
                    },
                    set: function (value) {
                        this._columnIndex = value;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(ColumnSortDescription.prototype, "ascending", {
                    /**
                     * Gets or sets the ascending.
                     */
                    get: function () {
                        return this._ascending;
                    },
                    set: function (value) {
                        this._ascending = value;
                    },
                    enumerable: true,
                    configurable: true
                });
                /**
                 * Creates a copy of the ColumnSortDescription.
                 */
                ColumnSortDescription.prototype.clone = function () {
                    return new ColumnSortDescription(this._columnIndex, this._ascending);
                };
                return ColumnSortDescription;
            }());
            sheet.ColumnSortDescription = ColumnSortDescription;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /**
             * Controls undo and redo operations in the @see:FlexSheet.
             */
            var UndoStack = /** @class */ (function () {
                /**
                 * Initializes a new instance of the @see:UndoStack class.
                 *
                 * @param owner The @see:FlexSheet control that the @see:UndoStack works for.
                 */
                function UndoStack(owner) {
                    this.MAX_STACK_SIZE = 500;
                    this._stack = [];
                    this._pointer = -1;
                    this._resizingTriggered = false;
                    /**
                     * Occurs after the undo stack has changed.
                     */
                    this.undoStackChanged = new wijmo.Event();
                    var self = this;
                    self._owner = owner;
                    // Handles the cell edit action for editing cell
                    self._owner.prepareCellForEdit.addHandler(self._initCellEditAction, self);
                    self._owner.cellEditEnded.addHandler(function (sender, args) {
                        // For edit cell content.
                        if (args.data && (args.data.keyCode === 46 || args.data.keyCode === 8)) {
                            return;
                        }
                        if (self._pendingAction instanceof sheet._EditAction && !self._pendingAction.isPaste) {
                            self._afterProcessCellEditAction(self);
                        }
                    }, self);
                    // Handles the cell edit action for copy\paste operation
                    self._owner.pasting.addHandler(self._initCellEditActionForPasting, self);
                    self._owner.pastingCell.addHandler(function (sender, e) {
                        if (self._pendingAction instanceof sheet._EditAction) {
                            self._pendingAction.updateForPasting(e.range);
                        }
                        else if (self._pendingAction instanceof sheet._CutAction) {
                            self._pendingAction.updateForPasting(e.range);
                        }
                    }, self);
                    self._owner.pasted.addHandler(function () {
                        // For paste content to the cell.
                        if (self._pendingAction instanceof sheet._EditAction && self._pendingAction.isPaste) {
                            self._afterProcessCellEditAction(self);
                        }
                        else if (self._pendingAction instanceof sheet._CutAction) {
                            self._pendingAction.saveNewState();
                            self._addAction(self._pendingAction);
                            self._pendingAction = null;
                        }
                    }, self);
                    // Handles the resize column action
                    self._owner.resizingColumn.addHandler(function (sender, e) {
                        if (!self._resizingTriggered) {
                            self._pendingAction = new sheet._ColumnResizeAction(self._owner, e.panel, e.col);
                            self._resizingTriggered = true;
                        }
                    }, self);
                    self._owner.resizedColumn.addHandler(function (sender, e) {
                        if (self._pendingAction instanceof sheet._ColumnResizeAction && self._pendingAction.saveNewState()) {
                            self._addAction(self._pendingAction);
                        }
                        self._pendingAction = null;
                        self._resizingTriggered = false;
                    }, self);
                    // Handles the resize row action
                    self._owner.resizingRow.addHandler(function (sender, e) {
                        if (!self._resizingTriggered) {
                            self._pendingAction = new sheet._RowResizeAction(self._owner, e.panel, e.row);
                            self._resizingTriggered = true;
                        }
                    }, self);
                    self._owner.resizedRow.addHandler(function (sender, e) {
                        if (self._pendingAction instanceof sheet._RowResizeAction && self._pendingAction.saveNewState()) {
                            self._addAction(self._pendingAction);
                        }
                        self._pendingAction = null;
                        self._resizingTriggered = false;
                    }, self);
                    // Handle the changing rows\columns position action.
                    self._owner.draggingRowColumn.addHandler(function (sender, e) {
                        if (e.isShiftKey) {
                            if (e.isDraggingRows) {
                                self._pendingAction = new sheet._RowsChangedAction(self._owner);
                            }
                            else {
                                self._pendingAction = new sheet._ColumnsChangedAction(self._owner);
                            }
                        }
                    }, self);
                    self._owner.droppingRowColumn.addHandler(function () {
                        if (self._pendingAction && self._pendingAction.saveNewState()) {
                            self._addAction(self._pendingAction);
                        }
                        self._pendingAction = null;
                    }, self);
                }
                Object.defineProperty(UndoStack.prototype, "canUndo", {
                    /**
                     * Checks whether an undo action can be performed.
                     */
                    get: function () {
                        return this._pointer > -1 && this._pointer < this._stack.length;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(UndoStack.prototype, "canRedo", {
                    /**
                     * Checks whether a redo action can be performed.
                     */
                    get: function () {
                        return this._pointer + 1 > -1 && this._pointer + 1 < this._stack.length;
                    },
                    enumerable: true,
                    configurable: true
                });
                /**
                 * Raises the @see:undoStackChanged event.
                 */
                UndoStack.prototype.onUndoStackChanged = function () {
                    this.undoStackChanged.raise(this);
                };
                /**
                 * Undo the last action.
                 */
                UndoStack.prototype.undo = function () {
                    var action;
                    if (this.canUndo) {
                        action = this._stack[this._pointer];
                        this._beforeUndoRedo(action);
                        action.undo();
                        this._pointer--;
                        this.onUndoStackChanged();
                    }
                };
                /**
                 * Redo the last undone action.
                 */
                UndoStack.prototype.redo = function () {
                    var action;
                    if (this.canRedo) {
                        this._pointer++;
                        action = this._stack[this._pointer];
                        this._beforeUndoRedo(action);
                        action.redo();
                        this.onUndoStackChanged();
                    }
                };
                /*
                 * Add an action to the undo stack.
                 *
                 * @param action The @see:_UndoAction to add to the stack.
                 */
                UndoStack.prototype._addAction = function (action) {
                    // trim stack
                    if (this._stack.length > 0 && this._stack.length > this._pointer + 1) {
                        this._stack.splice(this._pointer + 1, this._stack.length - this._pointer - 1);
                    }
                    if (this._stack.length >= this.MAX_STACK_SIZE) {
                        this._stack.splice(0, this._stack.length - this.MAX_STACK_SIZE + 1);
                    }
                    // update pointer and add action to stack
                    this._pointer = this._stack.length;
                    this._stack.push(action);
                    this.onUndoStackChanged();
                };
                /*
                 * Removes the last undo action from the undo stack.
                 */
                UndoStack.prototype._pop = function () {
                    var action = this._stack[this._pointer];
                    this._pointer--;
                    return action;
                };
                /**
                 * Clears the undo stack.
                 */
                UndoStack.prototype.clear = function () {
                    this._stack.length = 0;
                };
                // initialize the cell edit action.
                UndoStack.prototype._initCellEditAction = function (sender, args) {
                    this._pendingAction = new sheet._EditAction(this._owner, args.range);
                };
                // initialize the cell edit action for pasting action.
                UndoStack.prototype._initCellEditActionForPasting = function () {
                    if (this._owner._isCutting) {
                        this._pendingAction = new sheet._CutAction(this._owner);
                    }
                    else {
                        this._pendingAction = new sheet._EditAction(this._owner);
                        this._pendingAction.markIsPaste();
                    }
                };
                // after processing the cell edit action.
                UndoStack.prototype._afterProcessCellEditAction = function (self) {
                    if (self._pendingAction instanceof sheet._EditAction && self._pendingAction.saveNewState()) {
                        self._addAction(this._pendingAction);
                    }
                    self._pendingAction = null;
                };
                // Called before an action is undone or redone.
                UndoStack.prototype._beforeUndoRedo = function (action) {
                    this._owner.selectedSheetIndex = action.sheetIndex;
                };
                return UndoStack;
            }());
            sheet.UndoStack = UndoStack;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Represents a Table within the @see:FlexSheet control.
             */
            var Table = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:Table class.
                 *
                 * @param owner The owner @see:FlexSheet control.
                 * @param name The name of the table.
                 * @param range The range of the table.
                 * @param style The table style to use with the table.  The default style is the 'TableStyleMedium9' built-in table style, if the style is omitted.
                 * @param columns The columns of the table.
                 * @param showHeaderRow Indicates whether show the header row for the table.  The default showHeaderRow is true, if the showHeaderRow is omitted.
                 * @param showTotalRow Indicates whether show the total row for the table.  The default showTotalRow is false, if the showTotalRow is omitted.
                 * @param showBandedColumns Indicating whether banded column formatting is applied.  The default showBandedColumns is false, if the showBandedColumns is omitted.
                 * @param showBandedRows Indicating whether banded row formatting is applied.  The default showBandedRows is true, if the showBandedRows is omitted.
                 * @param showFirstColumn Indicating whether the first column in the table should have the style applied.  The default showFirstColumn is false, if the showFirstColumn is omitted.
                 * @param showLastColumn Indicating whether the last column in the table should have the style applied.  The default showLastColumn is false, if the showLastColumn is omitted.
                 */
                function Table(owner, name, range, style, columns, showHeaderRow, showTotalRow, showBandedColumns, showBandedRows, showFirstColumn, showLastColumn) {
                    if (showHeaderRow === void 0) { showHeaderRow = true; }
                    if (showTotalRow === void 0) { showTotalRow = false; }
                    if (showBandedColumns === void 0) { showBandedColumns = false; }
                    if (showBandedRows === void 0) { showBandedRows = true; }
                    if (showFirstColumn === void 0) { showFirstColumn = false; }
                    if (showLastColumn === void 0) { showLastColumn = false; }
                    this._owner = owner;
                    this._name = name;
                    this._range = range.clone();
                    if (owner._containsMergedCells(range)) {
                        throw 'Table does not allow the merged cell within the table.';
                    }
                    if (style) {
                        this._style = style;
                    }
                    else {
                        this._style = owner.getBuiltInTableStyle('TableStyleMedium9');
                    }
                    if (columns != null && columns.length > 0) {
                        this._columns = columns;
                    }
                    else {
                        this._generateColumns(showHeaderRow);
                    }
                    this._owner.beginUpdate();
                    if (showHeaderRow != null) {
                        this._showHeaderRow = showHeaderRow;
                    }
                    if (showHeaderRow && range.rowSpan === 1) {
                        this._adjustTableRangeWithHeaderRow();
                    }
                    if (showTotalRow != null) {
                        this._showTotalRow = showTotalRow;
                    }
                    if (showTotalRow) {
                        this._adjustTableRangeWithTotalRow(false);
                        //this._updateTotalRow();
                    }
                    this._owner.endUpdate();
                    if (showBandedColumns != null) {
                        this._showBandedColumns = showBandedColumns;
                    }
                    if (showBandedRows != null) {
                        this._showBandedRows = showBandedRows;
                    }
                    if (showFirstColumn != null) {
                        this._showFirstColumn = showFirstColumn;
                    }
                    if (showLastColumn != null) {
                        this._showLastColumn = showLastColumn;
                    }
                }
                Object.defineProperty(Table.prototype, "name", {
                    /*
                     * Gets or sets the table name.
                     *
                     * The table name is used to reference the table programmatically.
                     */
                    get: function () {
                        return this._name;
                    },
                    set: function (value) {
                        var undoAction, oldName;
                        if (value == null || value === '') {
                            throw 'The name of the Table should not be empty.';
                        }
                        if (this._name.toLowerCase() !== value.toLowerCase()) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            oldName = this._name;
                            this._name = value;
                            this._owner._updateTableNameForSheet(oldName, value);
                            this._owner._updateFormulasWithNameUpdating(oldName, value, true);
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "sheet", {
                    /*
                     * Gets the @see:Sheet this table belongs to.
                     */
                    get: function () {
                        var flexSheet = this._owner, idx = flexSheet._getTableSheetIndex(this.name);
                        return idx > -1 ? flexSheet.sheets[idx] : null;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "range", {
                    /*
                     * Gets the range on the relevant sheet that the table occupies.
                     *
                     * The reference includes the totals row if it is visible.
                     */
                    get: function () {
                        return this._range.clone();
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "columns", {
                    /*
                     * Gets the table's columns.
                     */
                    get: function () {
                        return this._columns;
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "style", {
                    /*
                     * Gets or sets the @see:TableStyle associated with this table.
                     */
                    get: function () {
                        return this._style;
                    },
                    set: function (value) {
                        var undoAction;
                        if (value.name !== this._style.name /* && check whether the style name exists in FlexSheet */) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            this._style = value;
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                            this._owner.refresh();
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "showHeaderRow", {
                    /*
                     * Indicates whether the table should include a header row.
                     */
                    get: function () {
                        return this._showHeaderRow;
                    },
                    set: function (value) {
                        var undoAction;
                        if (value !== this._showHeaderRow) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            this._showHeaderRow = value;
                            this._owner.beginUpdate();
                            this._adjustTableRangeWithHeaderRow();
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                            this._owner.endUpdate();
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "showTotalRow", {
                    /*
                     * Indicates whether the table should include a total row.
                     */
                    get: function () {
                        return this._showTotalRow;
                    },
                    set: function (value) {
                        var undoAction;
                        if (value !== this._showTotalRow) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            this._showTotalRow = value;
                            this._owner.beginUpdate();
                            this._adjustTableRangeWithTotalRow(true);
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                            this._owner.endUpdate();
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "showBandedColumns", {
                    /*
                     * Gets or sets a value that determines whether banded column
                     * formatting is applied.
                     */
                    get: function () {
                        return this._showBandedColumns;
                    },
                    set: function (value) {
                        var undoAction;
                        if (value !== this._showBandedColumns) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            this._showBandedColumns = value;
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                            this._owner.refresh();
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "showBandedRows", {
                    /*
                     * Gets or sets a value that determines whether banded row
                     * formatting is applied.
                     */
                    get: function () {
                        return this._showBandedRows;
                    },
                    set: function (value) {
                        var undoAction;
                        if (value !== this._showBandedRows) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            this._showBandedRows = value;
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                            this._owner.refresh();
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "showFirstColumn", {
                    /*
                     * Gets or sets a value that determines whether the first table
                     * column should have the style applied.
                     */
                    get: function () {
                        return this._showFirstColumn;
                    },
                    set: function (value) {
                        var undoAction;
                        if (value !== this._showFirstColumn) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            this._showFirstColumn = value;
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                            this._owner.refresh();
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(Table.prototype, "showLastColumn", {
                    /*
                     * Gets or sets a value that determines whether the last table
                     * column should have the style applied.
                     */
                    get: function () {
                        return this._showLastColumn;
                    },
                    set: function (value) {
                        var undoAction;
                        if (value !== this._showLastColumn) {
                            if (!this._owner._isUndoing) {
                                undoAction = new sheet._TableSettingAction(this._owner, this);
                            }
                            this._showLastColumn = value;
                            if (!this._owner._isUndoing) {
                                undoAction.saveNewState();
                                this._owner.undoStack._addAction(undoAction);
                                undoAction = null;
                            }
                            this._owner.refresh();
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                /*
                 * Gets the range of a specific column in the table.
                 *
                 * @param columnName the name of the Table Column.
                 */
                Table.prototype.getColumnRange = function (columnName) {
                    for (var i = 0; i < this._columns.length; i++) {
                        if (this._columns[i].name.toLowerCase() === columnName) {
                            var topRow = this._range.topRow, bottomRow = this._range.bottomRow, col = this._range.leftCol + i;
                            if (this._showHeaderRow) {
                                topRow += 1;
                            }
                            if (this._showTotalRow) {
                                bottomRow -= 1;
                            }
                            return new grid.CellRange(topRow, col, bottomRow, col);
                        }
                    }
                    return null;
                };
                /*
                 * Gets the table's data range.
                 */
                Table.prototype.getDataRange = function () {
                    var topRow = this._range.topRow, bottomRow = this._range.bottomRow;
                    if (this._showHeaderRow) {
                        topRow += 1;
                    }
                    if (this._showTotalRow) {
                        bottomRow -= 1;
                    }
                    return new grid.CellRange(topRow, this._range.leftCol, bottomRow, this._range.rightCol);
                };
                /*
                 * Gets the table's header row range.
                 */
                Table.prototype.getHeaderRange = function () {
                    if (this._showHeaderRow) {
                        return new grid.CellRange(this._range.topRow, this._range.leftCol, this._range.topRow, this._range.rightCol);
                    }
                    return null;
                };
                /*
                 * Gets the table's total row range.
                 */
                Table.prototype.getTotalRange = function () {
                    if (this._showTotalRow) {
                        return new grid.CellRange(this._range.bottomRow, this._range.leftCol, this._range.bottomRow, this._range.rightCol);
                    }
                    return null;
                };
                // Add table column in Table.
                Table.prototype._addColumn = function (index, columnName) {
                    var nameIndex = 1, tmpColumnName, column;
                    if (index <= 0 || index > this._columns.length) {
                        throw 'The column index is out of range.';
                    }
                    columnName = this._getUniqueColumnName(index, columnName);
                    column = new TableColumn(columnName);
                    this._columns.splice(index, 0, column);
                    if (this.showHeaderRow) {
                        this._owner.setCellData(this.range.topRow, this.range.leftCol + index, columnName);
                    }
                };
                // Update the table cell.
                Table.prototype._updateCell = function (rowIndex, colIndex, cell) {
                    var tableRowIndex = rowIndex - this._range.topRow, tableColIndex = colIndex - this._range.leftCol, appliedStyle;
                    if (this._style == null) {
                        return;
                    }
                    appliedStyle = this._getTableCellAppliedStyles(tableRowIndex, tableColIndex);
                    this._applyStylesForCell(appliedStyle, cell);
                };
                // Update the range of the table
                Table.prototype._updateTableRange = function (topRowChange, bottomRowChage, leftColChange, rightColChange) {
                    if (this._range.row <= this._range.row2) {
                        this._range.row += topRowChange;
                        this._range.row2 += bottomRowChage;
                    }
                    else {
                        this._range.row2 += topRowChange;
                        this._range.row += bottomRowChage;
                    }
                    if (this._range.col <= this._range.col2) {
                        this._range.col += leftColChange;
                        this._range.col2 += rightColChange;
                    }
                    else {
                        this._range.col2 += leftColChange;
                        this._range.col += rightColChange;
                    }
                };
                // Set range to the Table.
                Table.prototype._setTableRange = function (range, columns) {
                    var columnIndex;
                    this._range = range;
                    if (columns != null) {
                        this._columns.splice(0, this._columns.length);
                        for (columnIndex = 0; columnIndex < columns.length; columnIndex++) {
                            this._columns.push(columns[columnIndex]);
                        }
                    }
                };
                // Update name of the column
                Table.prototype._updateColumnName = function (columnIndex, columnName) {
                    var column = this._columns[columnIndex];
                    columnName = this._getUniqueColumnName(null, columnName);
                    column.name = columnName;
                    if (this._showHeaderRow) {
                        this._owner.setCellData(this._range.topRow, this._range.leftCol + columnIndex, columnName);
                    }
                };
                // Generates the columns for the table by the range of the table. 
                Table.prototype._generateColumns = function (showHeaderRow) {
                    var colIndex, columnName, column;
                    if (!this._range.isValid) {
                        throw 'The range of the table is invalid.';
                    }
                    this._columns = [];
                    for (var colIndex = 0; colIndex < this._range.columnSpan; colIndex++) {
                        if (this._range.rowSpan === 1) {
                            columnName = this._getUniqueColumnName(colIndex + 1);
                        }
                        else {
                            columnName = this._owner.getCellValue(this._range.topRow, this._range.leftCol + colIndex, false);
                            columnName = this._getUniqueColumnName(colIndex + 1, columnName.toString());
                        }
                        if (showHeaderRow) {
                            this._owner.setCellData(this._range.topRow, this._range.leftCol + colIndex, columnName);
                        }
                        column = new TableColumn(columnName);
                        if (colIndex === 0) {
                            column.totalRowLabel = 'Total';
                        }
                        else if (colIndex === this._range.columnSpan - 1) {
                            column.totalRowFunction = 'Sum';
                        }
                        this._columns.push(column);
                    }
                };
                // Get the table cell apllied table styles.
                Table.prototype._getTableCellAppliedStyles = function (cellRowIndex, cellColIndex) {
                    var appliedStyle = {}, isHeaderCell = false, isTotalCell = false, rowOffset = 0, firstSize, secondSize, totalSize, ret;
                    if (this._showHeaderRow) {
                        rowOffset = 1;
                    }
                    if (this._showHeaderRow && cellRowIndex === 0) {
                        isHeaderCell = true;
                    }
                    else if (this._showTotalRow && cellRowIndex === this._range.rowSpan - 1) {
                        isTotalCell = true;
                    }
                    this._extendStyle(appliedStyle, this._style.wholeTableStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                    if (!isHeaderCell && !isTotalCell) {
                        if (this._showBandedColumns && (this._style.firstBandedColumnStyle != null || this._style.secondBandedColumnStyle != null)) {
                            if (this._style.firstBandedColumnStyle) {
                                firstSize = this._style.firstBandedColumnStyle.size == null ? 1 : this._style.firstBandedColumnStyle.size;
                            }
                            else {
                                firstSize = 1;
                            }
                            if (this._style.secondBandedColumnStyle) {
                                secondSize = this._style.secondBandedColumnStyle.size == null ? 1 : this._style.secondBandedColumnStyle.size;
                            }
                            else {
                                secondSize = 1;
                            }
                            totalSize = firstSize + secondSize;
                            ret = cellColIndex % totalSize;
                            if (ret >= firstSize) {
                                if (this._style.secondBandedColumnStyle) {
                                    this._extendStyle(appliedStyle, this._style.secondBandedRowStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                                }
                            }
                            else {
                                if (this._style.firstBandedColumnStyle) {
                                    this._extendStyle(appliedStyle, this._style.firstBandedColumnStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                                }
                            }
                        }
                        if (this._showBandedRows && (this._style.firstBandedRowStyle != null || this._style.secondBandedRowStyle != null)) {
                            if (this._style.firstBandedRowStyle) {
                                firstSize = this._style.firstBandedRowStyle.size == null ? 1 : this._style.firstBandedRowStyle.size;
                            }
                            else {
                                firstSize = 1;
                            }
                            if (this._style.secondBandedRowStyle) {
                                secondSize = this._style.secondBandedRowStyle.size == null ? 1 : this._style.secondBandedRowStyle.size;
                            }
                            else {
                                secondSize = 1;
                            }
                            totalSize = firstSize + secondSize;
                            ret = (cellRowIndex - rowOffset) % totalSize;
                            if (ret >= firstSize) {
                                if (this._style.secondBandedRowStyle) {
                                    this._extendStyle(appliedStyle, this._style.secondBandedRowStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                                }
                            }
                            else {
                                if (this._style.firstBandedRowStyle) {
                                    this._extendStyle(appliedStyle, this._style.firstBandedRowStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                                }
                            }
                        }
                    }
                    if (this._showLastColumn && cellColIndex === this._range.columnSpan - 1 && this._style.lastColumnStyle) {
                        this._extendStyle(appliedStyle, this._style.lastColumnStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                    }
                    if (this._showFirstColumn && cellColIndex === 0 && this._style.firstColumnStyle) {
                        this._extendStyle(appliedStyle, this._style.firstColumnStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                    }
                    if (isHeaderCell) {
                        if (this._style.headerRowStyle) {
                            this._extendStyle(appliedStyle, this._style.headerRowStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                        }
                        if (cellColIndex === this._range.columnSpan - 1 && this._style.lastHeaderCellStyle) {
                            this._extendStyle(appliedStyle, this._style.lastHeaderCellStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                        }
                        if (cellColIndex === 0 && this._style.firstHeaderCellStyle) {
                            this._extendStyle(appliedStyle, this._style.firstHeaderCellStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                        }
                    }
                    else if (isTotalCell) {
                        if (this._style.totalRowStyle) {
                            this._extendStyle(appliedStyle, this._style.totalRowStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                        }
                        if (cellColIndex === this._range.columnSpan - 1 && this._style.lastTotalCellStyle) {
                            this._extendStyle(appliedStyle, this._style.lastTotalCellStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                        }
                        if (cellColIndex === 0 && this._style.firstTotalCellStyle) {
                            this._extendStyle(appliedStyle, this._style.firstTotalCellStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell);
                        }
                    }
                    return appliedStyle;
                };
                // Aplly the related table styles for the table cell.
                Table.prototype._applyStylesForCell = function (cellStyle, cell) {
                    var st = cell.style, styleInfoVal;
                    for (var styleProp in cellStyle) {
                        styleInfoVal = cellStyle[styleProp];
                        if (styleInfoVal) {
                            if (styleProp.toLowerCase().indexOf('color') > -1) {
                                st[styleProp] = this._getStrColor(styleInfoVal);
                            }
                            else {
                                st[styleProp] = styleInfoVal;
                            }
                        }
                    }
                };
                // Extend the table style.
                Table.prototype._extendStyle = function (dstStyle, srcStyle, cellRowIndex, cellColIndex, isHeaderCell, isTotalCell) {
                    var key, value;
                    for (var key in srcStyle) {
                        value = srcStyle[key];
                        if (value === null) {
                            continue;
                        }
                        if (key.indexOf('borderTop') > -1) {
                            if (cellRowIndex === 0 || isTotalCell) {
                                if (wijmo.isObject(value)) {
                                    dstStyle[key] = {};
                                    this._cloneThemeColor(dstStyle[key], value);
                                }
                                else {
                                    dstStyle[key] = value;
                                }
                            }
                        }
                        else if (key.indexOf('borderBottom') > -1) {
                            if (cellRowIndex === this._range.rowSpan - 1 || isHeaderCell) {
                                if (wijmo.isObject(value)) {
                                    dstStyle[key] = {};
                                    this._cloneThemeColor(dstStyle[key], value);
                                }
                                else {
                                    dstStyle[key] = value;
                                }
                            }
                        }
                        else if (key.indexOf('borderLeft') > -1) {
                            if (cellColIndex === 0) {
                                if (wijmo.isObject(value)) {
                                    dstStyle[key] = {};
                                    this._cloneThemeColor(dstStyle[key], value);
                                }
                                else {
                                    dstStyle[key] = value;
                                }
                            }
                        }
                        else if (key.indexOf('borderRight') > -1) {
                            if (cellColIndex === this._range.columnSpan - 1) {
                                if (wijmo.isObject(value)) {
                                    dstStyle[key] = {};
                                    this._cloneThemeColor(dstStyle[key], value);
                                }
                                else {
                                    dstStyle[key] = value;
                                }
                            }
                        }
                        else if (key.indexOf('borderHorizontal') > -1) {
                            if (cellRowIndex < this._range.rowSpan - 1) {
                                if (key === 'borderHorizontalStyle') {
                                    dstStyle['borderBottomStyle'] = value;
                                }
                                else if (key === 'borderHorizontalWidth') {
                                    dstStyle['borderBottomWidth'] = value;
                                }
                                else {
                                    if (wijmo.isObject(value)) {
                                        dstStyle['borderBottomColor'] = {};
                                        this._cloneThemeColor(dstStyle['borderBottomColor'], value);
                                    }
                                    else {
                                        dstStyle['borderBottomColor'] = value;
                                    }
                                }
                            }
                        }
                        else if (key.indexOf('borderVertical') > -1) {
                            if (cellColIndex < this._range.columnSpan - 1) {
                                if (key === 'borderVerticalStyle') {
                                    dstStyle['borderRightStyle'] = value;
                                }
                                else if (key === 'borderVerticalWidth') {
                                    dstStyle['borderRightWidth'] = value;
                                }
                                else {
                                    if (wijmo.isObject(value)) {
                                        dstStyle['borderRightColor'] = {};
                                        this._cloneThemeColor(dstStyle['borderRightColor'], value);
                                    }
                                    else {
                                        dstStyle['borderRightColor'] = value;
                                    }
                                }
                            }
                        }
                        else {
                            if (wijmo.isObject(value)) {
                                dstStyle[key] = {};
                                this._cloneThemeColor(dstStyle[key], value);
                            }
                            else {
                                dstStyle[key] = value;
                            }
                        }
                    }
                };
                // Clone the theme color.
                Table.prototype._cloneThemeColor = function (dstColor, srcColor) {
                    if (dstColor) {
                        dstColor.theme = srcColor.theme;
                        dstColor.tint = srcColor.tint;
                    }
                };
                // Get string color.
                Table.prototype._getStrColor = function (color) {
                    var strColor;
                    if (!wijmo.isString(color)) {
                        if (color != null) {
                            strColor = this._owner._getThemeColor(color.theme, color.tint);
                        }
                        else {
                            strColor = '';
                        }
                    }
                    else {
                        strColor = color;
                    }
                    return strColor;
                };
                // Get the subtotal function number for the releated subtotal function.
                Table.prototype._getSubtotalFunction = function (functionName) {
                    switch (functionName) {
                        case 'average':
                            return '101';
                        case 'countnums':
                            return '102';
                        case 'count':
                            return '103';
                        case 'max':
                            return '104';
                        case 'min':
                            return '105';
                        case 'stddev':
                            return '107';
                        case 'sum':
                            return '109';
                        case 'var':
                            return '110';
                    }
                    return null;
                };
                // Move down the table.
                Table.prototype._moveDownTable = function () {
                    var rowIndex, colIndex, cellData;
                    for (rowIndex = this._range.bottomRow; rowIndex >= this._range.topRow; rowIndex--) {
                        for (colIndex = this._range.leftCol; colIndex <= this._range.rightCol; colIndex++) {
                            cellData = this._owner.getCellData(rowIndex, colIndex, false);
                            this._owner.setCellData(rowIndex + 1, colIndex, cellData);
                            this._owner.setCellData(rowIndex, colIndex, '');
                        }
                    }
                    this._range.row += 1;
                    this._range.row2 += 1;
                };
                // Move down the cells below the table.
                Table.prototype._moveDownCellsBelowTable = function () {
                    var rowIndex, colIndex, cellData, cellStyle, cellIndex;
                    for (rowIndex = this._owner.rows.length - 2; rowIndex > this._range.bottomRow; rowIndex--) {
                        for (colIndex = this._range.leftCol; colIndex <= this._range.rightCol; colIndex++) {
                            cellData = this._owner.getCellData(rowIndex, colIndex, false);
                            this._owner.setCellData(rowIndex + 1, colIndex, cellData);
                            this._owner.setCellData(rowIndex, colIndex, '');
                            cellStyle = this._owner.selectedSheet.getCellStyle(rowIndex, colIndex);
                            if (cellStyle) {
                                cellIndex = (rowIndex + 1) * this._owner.columns.length + colIndex;
                                this._owner.selectedSheet._styledCells[cellIndex] = cellStyle;
                                cellIndex = rowIndex * this._owner.columns.length + colIndex;
                                this._owner.selectedSheet._styledCells[cellIndex] = null;
                            }
                        }
                    }
                };
                // Move up the cells below the table.
                Table.prototype._moveUpCellsBelowTable = function () {
                    var rowIndex, colIndex, cellData, cellStyle, cellIndex;
                    for (rowIndex = this._range.bottomRow + 1; rowIndex < this._owner.rows.length; rowIndex++) {
                        for (colIndex = this._range.leftCol; colIndex <= this._range.rightCol; colIndex++) {
                            cellData = this._owner.getCellData(rowIndex, colIndex, false);
                            this._owner.setCellData(rowIndex - 1, colIndex, cellData);
                            this._owner.setCellData(rowIndex, colIndex, '');
                            cellStyle = this._owner.selectedSheet.getCellStyle(rowIndex, colIndex);
                            if (cellStyle) {
                                cellIndex = (rowIndex - 1) * this._owner.columns.length + colIndex;
                                this._owner.selectedSheet._styledCells[cellIndex] = cellStyle;
                                cellIndex = rowIndex * this._owner.columns.length + colIndex;
                                this._owner.selectedSheet._styledCells[cellIndex] = null;
                            }
                        }
                    }
                };
                // Check whether other table is located below the table.
                Table.prototype._isOtherTableBelow = function () {
                    var rowIndex, colIndex;
                    for (rowIndex = this._range.bottomRow + 1; rowIndex < this._owner.rows.length; rowIndex++) {
                        for (colIndex = this._range.leftCol; colIndex <= this._range.rightCol; colIndex++) {
                            if (this._owner.selectedSheet.findTable(rowIndex, colIndex)) {
                                return true;
                            }
                        }
                    }
                    return false;
                };
                // Check whether need move down the table when show the header row.
                Table.prototype._needMoveDownTable = function () {
                    var i, cellData;
                    if (this._range.topRow === 0) {
                        return true;
                    }
                    for (i = 0; i < this._columns.length; i++) {
                        cellData = this._owner.getCellData(this._range.topRow - 1, this._range.leftCol + i, false);
                        if (cellData != null && cellData !== '') {
                            return true;
                        }
                    }
                    return false;
                };
                // Check whether need add new row in the flexsheet.    
                Table.prototype._needAddNewRow = function () {
                    var colIndex, cellData, cellStyle;
                    for (colIndex = this._range.leftCol; colIndex <= this._range.rightCol; colIndex++) {
                        cellData = this._owner.getCellData(this._owner.rows.length - 1, colIndex, false);
                        cellStyle = this._owner.selectedSheet.getCellStyle(this._owner.rows.length - 1, colIndex);
                        if ((cellData != null && cellData !== '') || cellStyle != null) {
                            return true;
                        }
                    }
                    return false;
                };
                // Check whether the column name has existed.
                Table.prototype._checkColumnNameExist = function (name) {
                    var index, column;
                    for (index = 0; index < this.columns.length; index++) {
                        column = this.columns[index];
                        if (column.name.toLowerCase() === name.toLowerCase()) {
                            return true;
                        }
                    }
                    return false;
                };
                // Adjust the table range with the change of the visiblity of the header row.
                Table.prototype._adjustTableRangeWithHeaderRow = function () {
                    var i, column;
                    if (this._showHeaderRow) {
                        if (this._needMoveDownTable()) {
                            if (this._isOtherTableBelow()) {
                                throw 'The operation is not allowed.  The operation is attempting to shift the cells in a table on the current sheet.';
                            }
                            if (this._needAddNewRow()) {
                                this._owner.rows.push(new grid.Row());
                            }
                            this._moveDownCellsBelowTable();
                            this._moveDownTable();
                        }
                        if (this._range.row <= this._range.row2) {
                            this._range.row -= 1;
                        }
                        else {
                            this._range.row2 -= 1;
                        }
                        for (i = 0; i < this._columns.length; i++) {
                            column = this._columns[i];
                            this._owner.setCellData(this._range.topRow, this._range.leftCol + i, column.name);
                        }
                    }
                    else {
                        for (i = this._range.leftCol; i <= this._range.rightCol; i++) {
                            this._owner.setCellData(this._range.topRow, i, '');
                        }
                        if (this._range.row <= this._range.row2) {
                            this._range.row += 1;
                        }
                        else {
                            this._range.row2 += 1;
                        }
                    }
                };
                // Adjust the table with the change of the visiblity of the total row.
                Table.prototype._adjustTableRangeWithTotalRow = function (isPropChange) {
                    var i;
                    //column: TableColumn,
                    //subtotalFun: string,
                    //totalCellContent;
                    if (this._showTotalRow) {
                        if (this._isOtherTableBelow()) {
                            throw 'The operation is not allowed.  The operation is attempting to shift the cells in a table on the current sheet.';
                        }
                        if (this._needAddNewRow()) {
                            this._owner.rows.push(new grid.Row());
                        }
                        this._moveDownCellsBelowTable();
                        if (isPropChange) {
                            if (this._range.row <= this._range.row2) {
                                this._range.row2 += 1;
                            }
                            else {
                                this._range.row += 1;
                            }
                        }
                        this._updateTotalRow();
                        //for (i = 0; i < this._columns.length; i++) {
                        //    column = this._columns[i];
                        //    if (column.totalRowFunction) {
                        //        subtotalFun = this._getSubtotalFunction(column.totalRowFunction.toLowerCase());
                        //        if (subtotalFun != null) {
                        //            totalCellContent = '=subtotal(' + subtotalFun + ', [' + column.name + '])';
                        //        } else {
                        //            totalCellContent = column.totalRowFunction[0] === '=' ? column.totalRowFunction : '=' + column.totalRowFunction;
                        //        }
                        //    } else {
                        //        totalCellContent = column.totalRowLabel;
                        //    }
                        //    this._owner.setCellData(this._range.bottomRow, this._range.leftCol + i, totalCellContent);
                        //}
                    }
                    else {
                        for (i = this._range.leftCol; i <= this._range.rightCol; i++) {
                            this._owner.setCellData(this._range.bottomRow, i, '');
                        }
                        this._moveUpCellsBelowTable();
                        if (isPropChange) {
                            if (this._range.row <= this._range.row2) {
                                this._range.row2 -= 1;
                            }
                            else {
                                this._range.row -= 1;
                            }
                        }
                    }
                };
                Table.prototype._updateTotalRow = function () {
                    var column, subtotalFun, totalCellContent;
                    if (this.showTotalRow) {
                        for (var i = 0; i < this._columns.length; i++) {
                            column = this._columns[i];
                            if (column.totalRowFunction) {
                                subtotalFun = this._getSubtotalFunction(column.totalRowFunction.toLowerCase());
                                if (subtotalFun != null) {
                                    totalCellContent = '=subtotal(' + subtotalFun + ', [' + column.name + '])';
                                }
                                else {
                                    totalCellContent = column.totalRowFunction[0] === '=' ? column.totalRowFunction : '=' + column.totalRowFunction;
                                }
                            }
                            else {
                                totalCellContent = column.totalRowLabel;
                            }
                            this._owner.setCellData(this._range.bottomRow, this._range.leftCol + i, totalCellContent);
                        }
                    }
                };
                // Get the unique name for the column.
                Table.prototype._getUniqueColumnName = function (index, columnName) {
                    var tmpColumnName, nameIndex = 1;
                    if (!columnName) {
                        columnName = 'Column' + index;
                    }
                    if (this._checkColumnNameExist(columnName)) {
                        tmpColumnName = columnName + nameIndex;
                        while (this._checkColumnNameExist(tmpColumnName)) {
                            nameIndex++;
                            tmpColumnName = columnName + nameIndex;
                        }
                        columnName = tmpColumnName;
                    }
                    return columnName;
                };
                return Table;
            }());
            sheet.Table = Table;
            /*
             * Represents a column within the @see:Table.
             */
            var TableColumn = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:TableColumn class.
                 *
                 * @param name The name of the table column.
                 * @param totalRowLabel The string to show in the totals row cell for the column.
                 * @param totalRowFunction The function to show in the totals row cell for this column.
                 * @param showFilterButton Indicating whether show the filter button for the table column.  The default value of showFilterButton is true.
                 */
                function TableColumn(name, totalRowLabel, totalRowFunction, showFilterButton) {
                    if (showFilterButton === void 0) { showFilterButton = true; }
                    this._name = name;
                    this._totalRowLabel = totalRowLabel;
                    this._totalRowFunction = totalRowFunction;
                    if (showFilterButton != null) {
                        this._showFilterButton = showFilterButton;
                    }
                }
                Object.defineProperty(TableColumn.prototype, "name", {
                    /*
                     * Gets the name of the table column. It is referenced through functions.
                     */
                    get: function () {
                        return this._name;
                    },
                    set: function (value) {
                        if (value !== this._name /* && check is valid column name. */) {
                            this._name = value;
                            // Todo:
                            // Update the formulas refer the column in FlexSheet.
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableColumn.prototype, "totalRowLabel", {
                    /*
                     * The string to show in the totals row cell for the column.
                     */
                    get: function () {
                        return this._totalRowLabel;
                    },
                    set: function (value) {
                        if (value !== this._totalRowLabel) {
                            this._totalRowLabel = value;
                            // Todo:
                            // Update the value for the total cell in the column.
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableColumn.prototype, "totalRowFunction", {
                    /*
                     * The function to show in the totals row cell for the column.
                     */
                    get: function () {
                        return this._totalRowFunction;
                    },
                    set: function (value) {
                        if (value !== this._totalRowFunction) {
                            this._totalRowFunction = value;
                            // Todo:
                            // Update the value for the total cell in the column.
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableColumn.prototype, "showFilterButton", {
                    /*
                     * Indicating whether show the filter button for the table column.
                     */
                    get: function () {
                        return this._showFilterButton;
                    },
                    set: function (value) {
                        if (this._showFilterButton !== value) {
                            this._showFilterButton = value;
                            // Todo:
                            // Update the header row cell to show/hide the filter button.
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                return TableColumn;
            }());
            sheet.TableColumn = TableColumn;
            /*
             * Represents a Table style for the @see:Table.
             */
            var TableStyle = /** @class */ (function () {
                /*
                 * Initializes a new instance of the @see:TableStyle class.
                 *
                 * @param name The name of the table style.
                 * @param isBuiltIn Indicates whether the table style is built-in style.
                 */
                function TableStyle(name, isBuiltIn) {
                    if (isBuiltIn === void 0) { isBuiltIn = false; }
                    this._name = name;
                    this._isBuiltIn = isBuiltIn;
                }
                Object.defineProperty(TableStyle.prototype, "name", {
                    /*
                     * Gets or sets the name of the table style.
                     */
                    get: function () {
                        return this._name;
                    },
                    set: function (value) {
                        if (value !== this._name) {
                            this._name = value;
                            // Todo:
                            // Update the styleName property of the tables apply this table style.
                        }
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "wholeTableStyle", {
                    /*
                     * Gets or sets the whole table style.
                     */
                    get: function () {
                        return this._wholeTableStyle;
                    },
                    set: function (value) {
                        this._wholeTableStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "firstBandedColumnStyle", {
                    /*
                     * Gets or sets the first banded column style.
                     */
                    get: function () {
                        return this._firstBandedColumnStyle;
                    },
                    set: function (value) {
                        this._firstBandedColumnStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "secondBandedColumnStyle", {
                    /*
                     * Gets or sets the second banded column style.
                     */
                    get: function () {
                        return this._secondBandedColumnStyle;
                    },
                    set: function (value) {
                        this._secondBandedColumnStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "firstBandedRowStyle", {
                    /*
                     * Gets or sets the first banded row style.
                     */
                    get: function () {
                        return this._firstBandedRowStyle;
                    },
                    set: function (value) {
                        this._firstBandedRowStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "secondBandedRowStyle", {
                    /*
                     * Gets or sets the second banded row style.
                     */
                    get: function () {
                        return this._secondBandedRowStyle;
                    },
                    set: function (value) {
                        this._secondBandedRowStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "firstColumnStyle", {
                    /*
                     * Gets or sets the first column style.
                     */
                    get: function () {
                        return this._firstColumnStyle;
                    },
                    set: function (value) {
                        this._firstColumnStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "lastColumnStyle", {
                    /*
                     * Gets or sets the last column style.
                     */
                    get: function () {
                        return this._lastColumnStyle;
                    },
                    set: function (value) {
                        this._lastColumnStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "headerRowStyle", {
                    /*
                     * Gets or sets the header row style.
                     */
                    get: function () {
                        return this._headerRowStyle;
                    },
                    set: function (value) {
                        this._headerRowStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "totalRowStyle", {
                    /*
                     * Gets or sets the total row style.
                     */
                    get: function () {
                        return this._totalRowStyle;
                    },
                    set: function (value) {
                        this._totalRowStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "firstHeaderCellStyle", {
                    /*
                     * Gets or sets the first cell style in the header row.
                     */
                    get: function () {
                        return this._firstHeaderCellStyle;
                    },
                    set: function (value) {
                        this._firstHeaderCellStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "lastHeaderCellStyle", {
                    /*
                     * Gets or sets the last cell style in the header row.
                     */
                    get: function () {
                        return this._lastHeaderCellStyle;
                    },
                    set: function (value) {
                        this._lastHeaderCellStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "firstTotalCellStyle", {
                    /*
                     * Gets or sets the first cell style in the total row.
                     */
                    get: function () {
                        return this._firstTotalCellStyle;
                    },
                    set: function (value) {
                        this._firstTotalCellStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "lastTotalCellStyle", {
                    /*
                     * Gets or sets the last cell style in the total row.
                     */
                    get: function () {
                        return this._lastTotalCellStyle;
                    },
                    set: function (value) {
                        this._lastTotalCellStyle = value;
                        // Todo:
                        // Re-render the tables apply this table style.
                    },
                    enumerable: true,
                    configurable: true
                });
                Object.defineProperty(TableStyle.prototype, "isBuiltIn", {
                    /*
                     * Indicates whether the table style is built-in style.
                     */
                    get: function () {
                        return this._isBuiltIn;
                    },
                    enumerable: true,
                    configurable: true
                });
                return TableStyle;
            }());
            sheet.TableStyle = TableStyle;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Defines a value filter for a column on a @see:FlexSheet control.
             *
             * Value filters contain an explicit list of values that should be
             * displayed by the sheet.
             */
            var _FlexSheetValueFilter = /** @class */ (function (_super) {
                __extends(_FlexSheetValueFilter, _super);
                function _FlexSheetValueFilter() {
                    return _super !== null && _super.apply(this, arguments) || this;
                }
                /*
                 * Gets a value that indicates whether a value passes the filter.
                 *
                 * @param value The value to test.
                 */
                _FlexSheetValueFilter.prototype.apply = function (value) {
                    var flexSheet = this.column.grid;
                    if (!(flexSheet instanceof sheet.FlexSheet)) {
                        return false;
                    }
                    // values? accept everything
                    if (!this.showValues || !Object.keys(this.showValues).length) {
                        return true;
                    }
                    if (flexSheet.rows[value] instanceof grid._NewRowTemplate) {
                        return true;
                    }
                    value = flexSheet.getCellValue(value, this.column.index, true);
                    // apply conditions
                    return this.showValues[value] != undefined;
                };
                return _FlexSheetValueFilter;
            }(wijmo.grid.filter.ValueFilter));
            sheet._FlexSheetValueFilter = _FlexSheetValueFilter;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * The editor used to inspect and modify @see:FlexSheetValueFilter objects.
             *
             * This class is used by the @see:FlexSheetFilter class; you
             * rarely use it directly.
             */
            var _FlexSheetValueFilterEditor = /** @class */ (function (_super) {
                __extends(_FlexSheetValueFilterEditor, _super);
                function _FlexSheetValueFilterEditor() {
                    return _super !== null && _super.apply(this, arguments) || this;
                }
                /*
                 * Updates editor with current filter settings.
                 */
                _FlexSheetValueFilterEditor.prototype.updateEditor = function () {
                    var col = this.filter.column, flexSheet = col.grid, colIndex = col.index, values = [], keys = {}, row, mergedRange, value, sv, currentFilterResult, otherFilterResult, text, orgText, cellRef;
                    // get list of unique values
                    if (this.filter.uniqueValues || (flexSheet.itemsSource != null && flexSheet.childItemsPath != null)) {
                        _super.prototype.updateEditor.call(this);
                        return;
                    }
                    // format and add unique values to the 'values' array
                    for (var i = 0; i < flexSheet.rows.length; i++) {
                        // Get the result of current filter for current row.
                        currentFilterResult = this.filter.apply(i);
                        // Get the result of other filters for current row.
                        sv = this.filter.showValues;
                        this.filter.showValues = null;
                        otherFilterResult = flexSheet._filter['_filter'](i);
                        this.filter.showValues = sv;
                        mergedRange = flexSheet.getMergedRange(flexSheet.cells, i, colIndex);
                        if (mergedRange && (i !== mergedRange.topRow || colIndex !== mergedRange.leftCol)) {
                            continue;
                        }
                        row = flexSheet.rows[i];
                        if (row instanceof sheet.HeaderRow || row instanceof grid.GroupRow || row instanceof grid._NewRowTemplate || (!row.visible && (currentFilterResult || !otherFilterResult))) {
                            continue;
                        }
                        value = flexSheet.getCellValue(i, colIndex);
                        value = value === '' ? null : value;
                        text = flexSheet.getCellValue(i, colIndex, true);
                        orgText = flexSheet.getCellData(i, colIndex, true);
                        if (!keys[text]) {
                            keys[text] = true;
                            if (orgText && orgText[0] === '=') {
                                cellRef = i + '_' + colIndex;
                            }
                            else {
                                cellRef = '';
                            }
                            values.push({ value: value, text: text, cellRef: cellRef });
                        }
                    }
                    // check the items that are currently selected
                    var showValues = this.filter.showValues;
                    if (!showValues || Object.keys(showValues).length == 0) {
                        for (var i = 0; i < values.length; i++) {
                            values[i].show = true;
                        }
                    }
                    else {
                        for (var key in showValues) {
                            for (var i = 0; i < values.length; i++) {
                                if (showValues[key] && values[i].cellRef !== '' && values[i].cellRef === showValues[key].cellRef) {
                                    showValues[values[i].text] = {
                                        show: true,
                                        cellRef: values[i].cellRef
                                    };
                                    values[i].show = true;
                                    delete showValues[key];
                                }
                                else if (values[i].text == key) {
                                    values[i].show = true;
                                    break;
                                }
                            }
                        }
                    }
                    // honor isContentHtml property
                    this['_lbValues'].isContentHtml = col.isContentHtml;
                    // load filter and apply immediately
                    this['_cmbFilter'].text = this.filter.filterText;
                    this['_filterText'] = this['_cmbFilter'].text.toLowerCase();
                    // show the values
                    this['_view'].pageSize = this.filter.maxValues;
                    this['_view'].sourceCollection = values;
                    this['_view'].moveCurrentToPosition(-1);
                };
                /*
                 * Updates filter to reflect the current editor values.
                 */
                _FlexSheetValueFilterEditor.prototype.updateFilter = function () {
                    var showValues = null, items = this['_view'].items;
                    if (this['_filterText'] || this['_cbSelectAll'].indeterminate) {
                        showValues = {};
                        for (var i = 0; i < items.length; i++) {
                            var item = items[i];
                            if (item.show) {
                                showValues[item.text] = {
                                    show: true,
                                    cellRef: item.cellRef
                                };
                            }
                        }
                    }
                    this['_filter'].showValues = showValues;
                    this['_filter'].filterText = this['_filterText'];
                };
                ;
                return _FlexSheetValueFilterEditor;
            }(wijmo.grid.filter.ValueFilterEditor));
            sheet._FlexSheetValueFilterEditor = _FlexSheetValueFilterEditor;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Defines a condition filter for a column on a @see:FlexSheet control.
             *
             * Condition filters contain two conditions that may be combined
             * using an 'and' or an 'or' operator.
             *
             * This class is used by the @see:FlexSheetFilter class; you will
             * rarely use it directly.
             */
            var _FlexSheetConditionFilter = /** @class */ (function (_super) {
                __extends(_FlexSheetConditionFilter, _super);
                function _FlexSheetConditionFilter() {
                    return _super !== null && _super.apply(this, arguments) || this;
                }
                /*
                 * Returns a value indicating whether a value passes this filter.
                 *
                 * @param value The value to test.
                 */
                _FlexSheetConditionFilter.prototype.apply = function (value) {
                    var col = this.column, flexSheet = col.grid, c1 = this.condition1, c2 = this.condition2, compareVal, compareVal1, compareVal2;
                    if (!(flexSheet instanceof sheet.FlexSheet)) {
                        return false;
                    }
                    // no binding or not active? accept everything
                    if (!this.isActive) {
                        return true;
                    }
                    if (flexSheet.rows[value] instanceof grid._NewRowTemplate) {
                        return true;
                    }
                    // retrieve the value
                    compareVal = flexSheet.getCellValue(value, col.index);
                    if (compareVal === '' && col.dataType !== wijmo.DataType.String) {
                        compareVal = null;
                    }
                    compareVal1 = compareVal2 = compareVal;
                    if (col.dataMap) {
                        compareVal = col.dataMap.getDisplayValue(compareVal);
                        compareVal1 = compareVal2 = compareVal;
                    }
                    else if (wijmo.isDate(compareVal)) {
                        if (wijmo.isString(c1.value) || wijmo.isString(c2.value)) {
                            compareVal = flexSheet.getCellValue(value, col.index, true);
                            compareVal1 = compareVal2 = compareVal;
                        }
                    }
                    else if (wijmo.isNumber(compareVal)) {
                        compareVal = wijmo.Globalize.parseFloat(flexSheet.getCellValue(value, col.index, true));
                        compareVal1 = compareVal2 = compareVal;
                        if (compareVal === 0 && !col.dataType) {
                            if (c1.isActive && c1.value === '') {
                                compareVal1 = compareVal.toString();
                            }
                            if (c2.isActive && c2.value === '') {
                                compareVal2 = compareVal2.toString();
                            }
                        }
                    }
                    // apply conditions
                    var rv1 = c1.apply(compareVal1), rv2 = c2.apply(compareVal2);
                    // combine results
                    if (c1.isActive && c2.isActive) {
                        return this.and ? rv1 && rv2 : rv1 || rv2;
                    }
                    else {
                        return c1.isActive ? rv1 : c2.isActive ? rv2 : true;
                    }
                };
                return _FlexSheetConditionFilter;
            }(wijmo.grid.filter.ConditionFilter));
            sheet._FlexSheetConditionFilter = _FlexSheetConditionFilter;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Defines a filter for a column on a @see:FlexSheet control.
             *
             * The @see:FlexSheetColumnFilter contains a @see:FlexSheetConditionFilter and a
             * @see:FlexSheetValueFilter; only one of them may be active at a time.
             *
             * This class is used by the @see:FlexSheetFilter class; you
             * rarely use it directly.
             */
            var _FlexSheetColumnFilter = /** @class */ (function (_super) {
                __extends(_FlexSheetColumnFilter, _super);
                /*
                 * Initializes a new instance of the @see:FlexSheetColumnFilter class.
                 *
                 * @param owner The @see:FlexSheetFilter that owns this column filter.
                 * @param column The @see:Column to filter.
                 */
                function _FlexSheetColumnFilter(owner, column) {
                    var _this = _super.call(this, owner, column) || this;
                    _this['_valueFilter'] = new sheet._FlexSheetValueFilter(column);
                    _this['_conditionFilter'] = new sheet._FlexSheetConditionFilter(column);
                    return _this;
                }
                return _FlexSheetColumnFilter;
            }(wijmo.grid.filter.ColumnFilter));
            sheet._FlexSheetColumnFilter = _FlexSheetColumnFilter;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * The editor used to inspect and modify column filters.
             *
             * This class is used by the @see:FlexSheetFilter class; you
             * rarely use it directly.
             */
            var _FlexSheetColumnFilterEditor = /** @class */ (function (_super) {
                __extends(_FlexSheetColumnFilterEditor, _super);
                /*
                 * Initializes a new instance of the @see:FlexSheetColumnFilterEditor class.
                 *
                 * @param element The DOM element that hosts the control, or a selector
                 * for the host element (e.g. '#theCtrl').
                 * @param filter The @see:FlexSheetColumnFilter to edit.
                 * @param sortButtons Whether to show sort buttons in the editor.
                 */
                function _FlexSheetColumnFilterEditor(element, filter, sortButtons) {
                    if (sortButtons === void 0) { sortButtons = true; }
                    var _this = _super.call(this, element, filter, sortButtons) || this;
                    var self = _this, btnAsc, btnDsc;
                    if (sortButtons) {
                        _this['_divSort'].style.display = '';
                    }
                    btnAsc = _this.cloneElement(_this['_btnAsc']);
                    btnDsc = _this.cloneElement(_this['_btnDsc']);
                    _this['_btnAsc'].parentNode.replaceChild(btnAsc, _this['_btnAsc']);
                    _this['_btnDsc'].parentNode.replaceChild(btnDsc, _this['_btnDsc']);
                    btnAsc.addEventListener('click', function (e) {
                        self._sortBtnClick(e, true);
                    });
                    btnDsc.addEventListener('click', function (e) {
                        self._sortBtnClick(e, false);
                    });
                    return _this;
                }
                // shows the value or filter editor
                _FlexSheetColumnFilterEditor.prototype._showFilter = function (filterType) {
                    // create editor if we have to
                    if (filterType == wijmo.grid.filter.FilterType.Value && this['_edtVal'] == null) {
                        this['_edtVal'] = new sheet._FlexSheetValueFilterEditor(this['_divEdtVal'], this.filter.valueFilter);
                    }
                    _super.prototype._showFilter.call(this, filterType);
                };
                // sort button click event handler
                _FlexSheetColumnFilterEditor.prototype._sortBtnClick = function (e, asceding) {
                    var column = this.filter.column, sortManager = column.grid.sortManager, sortIndex, offset, sortItem;
                    e.preventDefault();
                    e.stopPropagation();
                    sortIndex = sortManager.checkSortItemExists(column.index);
                    if (sortIndex > -1) {
                        // If the sort item for current column doesn't exist, we add new sort item for current column
                        sortManager.sortDescriptions.moveCurrentToPosition(sortIndex);
                        sortItem = sortManager.sortDescriptions.currentItem;
                        sortItem.ascending = asceding;
                        offset = -sortIndex;
                    }
                    else {
                        sortManager.addSortLevel(column.index, asceding);
                        offset = -(sortManager.sortDescriptions.items.length - 1);
                    }
                    // Move sort item for current column to first level.
                    sortManager.moveSortLevel(offset);
                    sortManager.commitSort();
                    // show current filter state
                    this.updateEditor();
                    // raise event so caller can close the editor and apply the new filter
                    this.onButtonClicked();
                };
                // Clone dom element and its child node
                _FlexSheetColumnFilterEditor.prototype.cloneElement = function (element) {
                    var cloneEle = element.cloneNode();
                    while (element.firstChild) {
                        cloneEle.appendChild(element.lastChild);
                    }
                    return cloneEle;
                };
                return _FlexSheetColumnFilterEditor;
            }(wijmo.grid.filter.ColumnFilterEditor));
            sheet._FlexSheetColumnFilterEditor = _FlexSheetColumnFilterEditor;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var wijmo;
(function (wijmo) {
    var grid;
    (function (grid) {
        var sheet;
        (function (sheet) {
            'use strict';
            /*
             * Implements an Excel-style filter for @see:FlexSheet controls.
             *
             * To enable filtering on a @see:FlexSheet control, create an instance
             * of the @see:_FlexSheetFilter and pass the grid as a parameter to the
             * constructor.
             */
            var _FlexSheetFilter = /** @class */ (function (_super) {
                __extends(_FlexSheetFilter, _super);
                function _FlexSheetFilter() {
                    return _super !== null && _super.apply(this, arguments) || this;
                }
                Object.defineProperty(_FlexSheetFilter.prototype, "filterDefinition", {
                    /*
                     * Gets or sets the current filter definition as a JSON string.
                     */
                    get: function () {
                        var def = {
                            defaultFilterType: this.defaultFilterType,
                            filters: []
                        };
                        for (var i = 0; i < this['_filters'].length; i++) {
                            var cf = this['_filters'][i];
                            if (cf && cf.column) {
                                if (cf.conditionFilter.isActive) {
                                    var cfc = cf.conditionFilter;
                                    def.filters.push({
                                        columnIndex: cf.column.index,
                                        type: 'condition',
                                        condition1: { operator: cfc.condition1.operator, value: cfc.condition1.value },
                                        and: cfc.and,
                                        condition2: { operator: cfc.condition2.operator, value: cfc.condition2.value }
                                    });
                                }
                                else if (cf.valueFilter.isActive) {
                                    var cfv = cf.valueFilter;
                                    def.filters.push({
                                        columnIndex: cf.column.index,
                                        type: 'value',
                                        filterText: cfv.filterText,
                                        showValues: cfv.showValues
                                    });
                                }
                            }
                        }
                        return JSON.stringify(def);
                    },
                    set: function (value) {
                        var def = JSON.parse(wijmo.asString(value));
                        this.clear();
                        this.defaultFilterType = def.defaultFilterType;
                        for (var i = 0; i < def.filters.length; i++) {
                            var cfs = def.filters[i], col = this.grid.columns[cfs.columnIndex], cf = this.getColumnFilter(col, true);
                            if (cf) {
                                switch (cfs.type) {
                                    case 'condition':
                                        var cfc = cf.conditionFilter;
                                        cfc.condition1.value = col.dataType == wijmo.DataType.Date // handle times/times: TFS 125144, 143453
                                            ? wijmo.changeType(cfs.condition1.value, col.dataType, null)
                                            : cfs.condition1.value;
                                        cfc.condition1.operator = cfs.condition1.operator;
                                        cfc.and = cfs.and;
                                        cfc.condition2.value = col.dataType == wijmo.DataType.Date
                                            ? wijmo.changeType(cfs.condition2.value, col.dataType, null)
                                            : cfs.condition2.value;
                                        cfc.condition2.operator = cfs.condition2.operator;
                                        break;
                                    case 'value':
                                        var cfv = cf.valueFilter;
                                        cfv.filterText = cfs.filterText;
                                        cfv.showValues = cfs.showValues;
                                        break;
                                }
                            }
                        }
                        this.apply();
                    },
                    enumerable: true,
                    configurable: true
                });
                /*
                 * Applies the current column filters to the sheet.
                 */
                _FlexSheetFilter.prototype.apply = function () {
                    var self = this;
                    self.grid.deferUpdate(function () {
                        var row, filterResult, groupCells, groupBottomRow = -1;
                        for (var i = 0; i < self.grid.rows.length; i++) {
                            row = self.grid.rows[i];
                            if (row instanceof sheet.HeaderRow || i <= groupBottomRow) {
                                continue;
                            }
                            groupBottomRow = -1;
                            filterResult = self['_filter'](i);
                            if (row instanceof grid.GroupRow) {
                                groupCells = row.getCellRange();
                                if (row.dataItem == null || row.dataItem instanceof wijmo.collections.CollectionViewGroup) {
                                    // Check the filter result of the group row for the common sheet.
                                    row.visible = self._checkGroupVisible(groupCells);
                                }
                                else {
                                    // Check the filter result for the hierarchical tree.
                                    row.visible = filterResult;
                                    groupBottomRow = groupCells.bottomRow;
                                    if (groupCells.isValid) {
                                        for (var r = groupCells.topRow; r <= groupCells.bottomRow; r++) {
                                            self.grid.rows[r].visible = filterResult;
                                        }
                                    }
                                }
                            }
                            else {
                                row.visible = filterResult;
                            }
                        }
                        // and fire the event
                        if (!self.grid._isCopying && !self.grid._resettingFilter) {
                            self.onFilterApplied();
                        }
                    });
                };
                /*
                 * Shows the filter editor for the given grid column.
                 *
                 * @param col The @see:Column that contains the filter to edit.
                 * @param ht A @see:wijmo.chart.HitTestInfo object containing the range of the cell that
                 * triggered the filter display.
                 */
                _FlexSheetFilter.prototype.editColumnFilter = function (col, ht) {
                    var self = this;
                    // remove current editor
                    self.closeEditor();
                    // get column by name or by reference
                    col = wijmo.isString(col)
                        ? self.grid.columns.getColumn(col)
                        : wijmo.asType(col, grid.Column, false);
                    // raise filterChanging event
                    var e = new grid.CellRangeEventArgs(self.grid.cells, new grid.CellRange(-1, col.index));
                    self.onFilterChanging(e);
                    if (e.cancel) {
                        return;
                    }
                    e.cancel = true; // assume the changes will be canceled
                    self._undoAcion = new sheet._FilteringAction(self.grid);
                    // get the filter and the editor
                    var div = document.createElement('div'), flt = self.getColumnFilter(col), edt = new sheet._FlexSheetColumnFilterEditor(div, flt, self.showSortButtons);
                    wijmo.addClass(div, 'wj-dropdown-panel');
                    // handle RTL
                    if (self.grid.rightToLeft) {
                        div.dir = 'rtl';
                    }
                    // apply filter when it changes
                    edt.filterChanged.addHandler(function () {
                        e.cancel = false; // the changes were not canceled
                        if (self._undoAcion) {
                            if (self._undoAcion.saveNewState()) {
                                self.grid.undoStack._addAction(self._undoAcion);
                            }
                            self._undoAcion = null;
                        }
                        setTimeout(function () {
                            if (!e.cancel) {
                                self.apply();
                            }
                        });
                    });
                    // close editor when editor button is clicked
                    edt.buttonClicked.addHandler(function () {
                        self.closeEditor();
                        self.grid.focus();
                        self.onFilterChanged(e);
                    });
                    // close editor when it loses focus (changes are not applied)
                    edt.lostFocus.addHandler(function () {
                        setTimeout(function () {
                            var ctl = wijmo.Control.getControl(self['_divEdt']);
                            if (ctl && !ctl.containsFocus()) {
                                self.closeEditor();
                            }
                        }, 10); //200); // let others handle it first
                    });
                    // get the header cell to position editor
                    var ch = self.grid.columnHeaders, r = ht ? ht.row : ch.rows.length - 1, c = ht ? ht.col : col.index, rc = ch.getCellBoundingRect(r, c), hdrCell = document.elementFromPoint(rc.left + rc.width / 2, rc.top + rc.height / 2);
                    hdrCell = wijmo.closest(hdrCell, '.wj-cell');
                    // show editor and give it focus
                    if (hdrCell) {
                        wijmo.showPopup(div, hdrCell, false, false, false);
                    }
                    else {
                        wijmo.showPopup(div, rc);
                    }
                    edt.focus();
                    // save reference to editor
                    self['_divEdt'] = div;
                    self['_edtCol'] = col;
                };
                /*
                 * Closes the filter editor.
                 */
                _FlexSheetFilter.prototype.closeEditor = function () {
                    if (this._undoAcion) {
                        this._undoAcion = null;
                    }
                    _super.prototype.closeEditor.call(this);
                };
                /*
                 * Gets the filter for the given column.
                 *
                 * @param col The @see:Column that the filter applies to (or column name or index).
                 * @param create Whether to create the filter if it does not exist.
                 */
                _FlexSheetFilter.prototype.getColumnFilter = function (col, create) {
                    if (create === void 0) { create = true; }
                    // get the column by name or index, check type
                    if (wijmo.isString(col)) {
                        col = this.grid.columns.getColumn(col);
                    }
                    else if (wijmo.isNumber(col)) {
                        col = this.grid.columns[col];
                    }
                    if (!col) {
                        return null;
                    }
                    col = wijmo.asType(col, grid.Column);
                    // look for the filter
                    for (var i = 0; i < this['_filters'].length; i++) {
                        if (this['_filters'][i].column == col) {
                            return this['_filters'][i];
                        }
                    }
                    // not found, create one now
                    if (create) {
                        var cf = new sheet._FlexSheetColumnFilter(this, col);
                        this['_filters'].push(cf);
                        return cf;
                    }
                    // not found, not created
                    return null;
                };
                // Check the visiblity of the group.
                _FlexSheetFilter.prototype._checkGroupVisible = function (range) {
                    var groupVisible = true, row;
                    for (var i = range.topRow + 1; i <= range.bottomRow; i++) {
                        row = this.grid.rows[i];
                        if (row) {
                            if (row instanceof grid.GroupRow) {
                                groupVisible = this._checkGroupVisible(row.getCellRange());
                            }
                            else {
                                groupVisible = this['_filter'](i);
                                if (groupVisible) {
                                    break;
                                }
                            }
                        }
                    }
                    return groupVisible;
                };
                return _FlexSheetFilter;
            }(wijmo.grid.filter.FlexGridFilter));
            sheet._FlexSheetFilter = _FlexSheetFilter;
        })(sheet = grid.sheet || (grid.sheet = {}));
    })(grid = wijmo.grid || (wijmo.grid = {}));
})(wijmo || (wijmo = {}));

