/*
 * 此文件注册报表扩展的自定义公式
 * @Author:马少博 (ma.shaobo@qq.com)
 * @Date: 2018年12月15日14:19:30
 * @Last Modified by: 马少博
 * @Last Modified time:2018年12月25日19:22:04
 */
/* jshint esversion: 6 */
"use strict";

/**
 * 注册所有方法
 *
 */
function registAllFormula() {
    //表内公式
    regist_CF_GET_TAX_CS();
    regist_CF_GET_ZZS_LJ();
    regist_CF_GET_SDS_LJ();
    regist_CF_GET_BBSJ_NUM();
    regist_CF_GET_BBSJ_STR();
    regist_CF_GET_BBHJ();
    regist_CF_GET_VALU_NUM();
    regist_CF_GET_LSXX();
    regist_CF_GET_QYFZJG_BL();
    regist_CF_GET_ZZS_LJ_NEW();
    regist_CF_GET_NB_CELLDATA();
    //表间公式
    regist_SELF_TJ_FORMULA();
    regist_CF_GET_BJ_ZC();
    regist_CF_GET_BJ_ZC_SUM();
    regist_CF_GET_BJ_ZC_DIFF();

    //特殊取值公式
    regist_SPECIAL_VAL();
    regist_CELL();


    // checkbox部分取值
    regist_EQUAL_CHECK();
    regist_FZJG_FPBL();
    regist_DATESTR();

    //2019年2月19日10:19:29 新增
    //年报表格获取值
    regist_NB_GET_CELL_VAL();
    regist_TOFIND();
}

/*
'########::'########::'######:::'####::'######::'########:
 ##.... ##: ##.....::'##... ##::. ##::'##... ##:... ##..::
 ##:::: ##: ##::::::: ##:::..:::: ##:: ##:::..::::: ##::::
 ########:: ######::: ##::'####:: ##::. ######::::: ##::::
 ##.. ##::: ##...:::: ##::: ##::: ##:::..... ##:::: ##::::
 ##::. ##:: ##::::::: ##::: ##::: ##::'##::: ##:::: ##::::
 ##:::. ##: ########:. ######:::'####:. ######::::: ##::::
..:::::..::........:::......::::....:::......::::::..:::::
*/
/**
 * 注册 获取基本信息方法
 * 1. cf_get_tax_cs(String str,String as_flge)
 */
function regist_CF_GET_TAX_CS() {
    /**
     * 获取基本信息方法(根据 key 获取基本信息对应 value)
     */
    function CF_GET_TAX_CS() {
        this.name = "CF_GET_TAX_CS";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_TAX_CS.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_TAX_CS.prototype.description = function () {
        return {
            description: "获取基本信息方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_TAX_CS.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_TAX_CS.prototype.evaluateAsync = function (context) {
        try {
            var args = Array.prototype.slice.call(arguments).slice(1);
            var result;
            var arg1 = args[0];
            var arg2 = args[1];
            result = GLOBAL_STATIC_INFO[arg1] && GLOBAL_STATIC_INFO[arg1][arg2] || 0;
            return result;
        } catch (error) {
            consol.log(error);
            return 0;
        }
    };
    CF_GET_TAX_CS.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_TAX_CS", new CF_GET_TAX_CS());
}


/**
 * 注册 取增值税累计数方法
 * 2. cf_get_zzs_lj([Double col], [Double row], String as_flag)
 * TODO 小规模中暂时没有使用到
 */
function regist_CF_GET_ZZS_LJ() {
    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CF_GET_ZZS_LJ() {
        this.name = "CF_GET_ZZS_LJ";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_ZZS_LJ.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_ZZS_LJ.prototype.description = function () {
        return {
            description: "取增值税累计数方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_ZZS_LJ.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_ZZS_LJ.prototype.evaluateAsync = function (context) {
        try {

            var args = Array.prototype.slice.call(arguments).slice(1);
            var argLength = args.length;
            if (argLength == 3) {
                var row = args[1];
                var col = args[0];
                var flag = args[2];
            }
            var point = [row - 1, col - 1];
            var sheetName = context.ctx.source.getName();
            // 获取到坐标对应的nodeName
            //TODO 此处根据name获取到报表ID,然后根据属性获取
            var sheetId = sheetName.substr(6);
            var currentDataTable = extend_data[sheetName].data.datatable;
            var cell = currentDataTable[point[0]] && currentDataTable[point[0]][point[1]];
            var nodeNameVal = cell && cell.nodeName || "";
            var value = 0;
            if (nodeNameVal) {
                value = resolveFormulaVal(GLOBAL_JSON["lsxx"][sheetId] && GLOBAL_JSON["lsxx"][sheetId][nodeNameVal] && GLOBAL_JSON["lsxx"][sheetId][nodeNameVal].value || 0);
            }
            // debugger
            return value;
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    CF_GET_ZZS_LJ.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_ZZS_LJ", new CF_GET_ZZS_LJ());
}

/**
 * 注册 取所得税累计数方法
 * 3. cf_get_sds_lj([Double col], [Double row], String as_flag)
 */
function regist_CF_GET_SDS_LJ() {
    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CF_GET_SDS_LJ() {
        this.name = "CF_GET_SDS_LJ";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_SDS_LJ.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_SDS_LJ.prototype.description = function () {
        return {
            description: "取所得税累计数方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_SDS_LJ.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_SDS_LJ.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);
        try {
            // 此处是可能产生例外的语句
            var argLength = args.length;
            if (argLength == 3) {
                var row = args[1];
                var col = args[0];
                var flag = args[2];
            }

            var point = [row - 1, col - 1];
            var sheetName = context.ctx.source.getName();
            // 获取到坐标对应的nodeName
            //TODO 此处根据name获取到报表ID,然后根据属性获取
            var sheetId = sheetName.substr(6);
            var currentDataTable = extend_data[sheetName].data.datatable;
            var cell = currentDataTable[point[0]] && currentDataTable[point[0]][point[1]];
            var nodeNameVal = cell && cell.nodeName || "";
            var value = 0;
            if (nodeNameVal) {
                value = resolveFormulaVal((GLOBAL_JSON["lsxx"] && GLOBAL_JSON["lsxx"][sheetId] && GLOBAL_JSON["lsxx"][sheetId][nodeNameVal] && GLOBAL_JSON["lsxx"][sheetId][nodeNameVal].value) || 0);
            }
            return value;
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    CF_GET_SDS_LJ.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_SDS_LJ", new CF_GET_SDS_LJ());
}

/**
 * 注册 表间取数据的方法 - 数值
 * 4.cf_get_bbsj_num(String bbdm, [Double col], [Double row], String as_flag)
 * TODO 小规模中暂时没有用到
 */
function regist_CF_GET_BBSJ_NUM() {
    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CF_GET_BBSJ_NUM() {
        this.name = "CF_GET_BBSJ_NUM";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_BBSJ_NUM.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_BBSJ_NUM.prototype.description = function () {
        return {
            description: "表间取数据的方法 - 数值",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_BBSJ_NUM.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_BBSJ_NUM.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);
        var argLength = args.length;
        try {
            var sheetName = context.ctx.source.getName();
            var sheetIndex = spread.getSheetIndex(sheetName);
            if (argLength == 2) {
                var sheet = args[0].getSource();
                var _value = (sheet && sheet.getValue(args[0].getRow(), args[0].getColumn())) || 0;
                return resolveFormulaVal(_value);
            } else {
                return 0;
            }
        } catch (error) {
            // 此处是负责例外处理的语句
            console.log(error);
            return 0;
        }
    };
    CF_GET_BBSJ_NUM.prototype.isContextSensitive = function () {
        return true;
    };

    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_BBSJ_NUM", new CF_GET_BBSJ_NUM());
}
/**
 * 注册 表间取数据的方法-字符
 * 5. cf_get_bbsj_str(String bbdm,[Double col],[Double row],String as_flag)
 * TODO 小规模中暂时没有用到
 * @param {*} bbdm 报表代码全称(不包含版本号)
 * @param {*} col 列号
 * @param {*} row 行号
 * @param {*} as_flag 参数 BQ 本期数,SQ 上期数,SS 上三期数,SN 上年同期数
 */
function regist_CF_GET_BBSJ_STR() {
    /**
     * 表间取数据的方法-字符（包括上年数据、上期数据、本期数据等）
     */
    function CF_GET_BBSJ_STR() {
        this.name = "CF_GET_BBSJ_STR";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_BBSJ_STR.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_BBSJ_STR.prototype.description = function () {
        return {
            description: "表间取数据的方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_BBSJ_STR.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_BBSJ_STR.prototype.evaluateAsync = function (context) {
        var result;
        var args = Array.prototype.slice.call(arguments).slice(1);
        var argLength = args.length;
        try {
            var sheetName = context.ctx.source.getName();
            var sheetIndex = spread.getSheetIndex(sheetName);
            if (argLength == 2) {
                var sheet = args[0].getSource();
                var _value = (sheet && sheet.getValue(args[0].getRow(), args[0].getColumn())) || 0;
                return _value;
            } else {
                return 0;
            }
        } catch (error) {
            // 此处是负责例外处理的语句
            console.log(error);
            return 0;
        }
    };
    CF_GET_BBSJ_STR.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_BBSJ_STR", new CF_GET_BBSJ_STR());
}

/**
 * 注册 表间取数据的方法 - 合计（ 包括上年数据、 上期数据、 本期数据等数据的合计）
 * 6. cf_get_bbhj(String bbdm, String jdmc, String as_flag)
 * TODO 小规模中暂时没有用到
 */
function regist_CF_GET_BBHJ() {
    // 

    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CF_GET_BBHJ() {
        this.name = "CF_GET_BBHJ";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_BBHJ.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_BBHJ.prototype.description = function () {
        return {
            description: "表间取数据的方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_BBHJ.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_BBHJ.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);
        try {
            var sheetName = "table_" + args[1];
            var sheetIndex = spread.getSheetIndex(sheetName);
            var sheet = spread.sheets[sheetIndex];
            var nodeNameArr = args[2].split('|');
            var total = 0;
            for (var i = 1; i < arguments.length; i++) {
                var item = arguments[i];
                if (item && item.getRow) {
                    var row = item.getRow();
                    var rowCount = item.getRowCount();
                    var column = item.getColumn();
                    var columnCount = item.getColumnCount();

                    var sum = 0;
                    for (var j = row; j < row + rowCount; j++) {
                        for (var k = column; k < column + columnCount; k++) {
                            var nodeName = _getNodeNameBySheetName(j + 1, k + 1, sheetName) || "";
                            if (nodeName != "" && $.inArray(nodeName, nodeNameArr) > -1) {
                                var val = Number(getCellText(sheetIndex, j, k));
                                sum += resolveFormulaVal(val);
                            }
                        }
                    }
                    total += sum;
                }
            }
            return resolveFormulaVal(total);
        } catch (error) {
            // 此处是负责例外处理的语句
            console.log(error);
            return 0;
        }
    };
    CF_GET_BBHJ.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_BBHJ", new CF_GET_BBHJ());
}

/**
 * 注册 表间取数据的方法 - 带查询条件（ 包括上年数据、 上期数据、 本期数据等数据）
 * 7. cf_get_valu_num(String target, String consult, String as_flag)
 * 
 */
function regist_CF_GET_VALU_NUM() {
    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CF_GET_VALU_NUM() {
        this.name = "CF_GET_VALU_NUM";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_VALU_NUM.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_VALU_NUM.prototype.description = function () {
        return {
            description: "表间取数据的方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_VALU_NUM.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_VALU_NUM.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);
        try {
            var argLength = args.length;
            if (argLength == 3) {
                // target 目标节点名称（ 需要取数的节点名称）
                var target = args[0];
                //  参照物节点名称(满足条件的节点名称用 | 分隔, 取本表数据与某期数据对比)
                var consult = args[1];
                var flag = args[2];
            }
            // "12lc\",\"ysxmdmjmc|zzssl|yyssl\",\"SQ\"
            var value = "0";
            return resolveFormulaVal(value);
        } catch (error) {
            // 此处是负责例外处理的语句
            console.log(error);
            return 0;
        }
    };
    CF_GET_VALU_NUM.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_VALU_NUM", new CF_GET_VALU_NUM());
}

/**
 * 注册 表间取数据的方法 - 带查询条件（ 包括上年数据、 上期数据、 本期数据等数据）
 * 8. cf_get_valu_num(String target, String consult, String as_flag)
 * 
 */
function regist_CF_GET_LSXX() {
    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CF_GET_LSXX() {
        this.name = "CF_GET_LSXX";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_LSXX.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_LSXX.prototype.description = function () {
        return {
            description: "表间取数据的方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_LSXX.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_LSXX.prototype.evaluateAsync = function (context) {
        return 0;
    };
    CF_GET_LSXX.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_LSXX", new CF_GET_LSXX());
}

// function regist_CF_GET_LSXX() {
//     /**
//      * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
//      */
//     function CF_GET_LSXX() {
//         this.name = "CF_GET_LSXX";
//         this.maxArgs = 255;
//         this.minArgs = 1;
//     }
//     CF_GET_LSXX.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
//     CF_GET_LSXX.prototype.description = function () {
//         return {
//             description: "表间取数据的方法",
//             parameters: [{
//                 name: "value",
//                 repeatable: true,
//                 optional: true
//             }]
//         };
//     };
//     CF_GET_LSXX.prototype.acceptsReference = function () {
//         return true;
//     };
//     CF_GET_LSXX.prototype.evaluateAsync = function (context) {
//         return 0;
//     };
//     CF_GET_LSXX.prototype.isContextSensitive = function () {
//         return true;
//     };
//     GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_LSXX", new CF_GET_LSXX());
// }
/*
:'######::'##::::'##:'########:'########:'########:
'##... ##: ##:::: ##: ##.....:: ##.....::... ##..::
 ##:::..:: ##:::: ##: ##::::::: ##:::::::::: ##::::
. ######:: #########: ######::: ######:::::: ##::::
:..... ##: ##.... ##: ##...:::: ##...::::::: ##::::
'##::: ##: ##:::: ##: ##::::::: ##:::::::::: ##::::
. ######:: ##:::: ##: ########: ########:::: ##::::
:......:::..:::::..::........::........:::::..:::::
*/
/**
 * 注册 表间公式无条件正常处理方法
 * 9. CF_GET_BJ_ZC(String bbdm, String pos, String as_flag,String is_zero)
 * CF_GET_BJ_ZC(C:C,11:11,"JSXM_QCYE","BQ","N")
 */
function regist_CF_GET_BJ_ZC() {
    /**
     * 表间公式通用处理方法(报表代码,单元格名称或位置,本年同期、本年上期、上年同期（BQ,SQ,SN）,年初是否清零(Y/N))
     */
    function CF_GET_BJ_ZC() {
        this.name = "CF_GET_BJ_ZC";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_BJ_ZC.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_BJ_ZC.prototype.description = function () {
        return {
            description: "表间无条件取数据的方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_BJ_ZC.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_BJ_ZC.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);
        try {
            var argLength = args.length;
            if (argLength == 3) {
                for (var i = 1; i < arguments.length; i++) {
                    var item = arguments[i];
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        var sheet = item.getSource();
                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var val = sheet && sheet.getValue(j, k) || 0;
                                return val;
                            }
                        }
                    }
                }
            } else {
                var result;
                var sheetName = context.ctx.source.getName();
                var sheetIndex = spread.getSheetIndex(sheetName);
                var sheet = spread.sheets[sheetIndex];
                var valueArr = [];
                var sum = 0;
                for (var i = 1; i < arguments.length; i++) {
                    //
                    var item = arguments[i];
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();

                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var nodeName = _getNodeName(j + 1, k + 1, context) || "";
                                if (nodeName == args[2]) {

                                    var val = sheet && sheet.getValue(j, k) || 0;
                                    valueArr.push(val);
                                }
                            }
                        }
                    }
                }

                return valueArr.length > 0 ? valueArr[0] : 0;

            }
        } catch (error) {
            // 此处是负责例外处理的语句
            console.log(error);
            return 0;
        }
    };
    CF_GET_BJ_ZC.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_BJ_ZC", new CF_GET_BJ_ZC());
}

/**
 * 用于处理表间公式SUM合计情况
 *
 */
function regist_CF_GET_BJ_ZC_SUM() {
    function CF_GET_BJ_ZC_SUM() {
        this.name = "CF_GET_BJ_ZC_SUM";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_BJ_ZC_SUM.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_BJ_ZC_SUM.prototype.description = function () {
        return {
            description: "",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_BJ_ZC_SUM.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_BJ_ZC_SUM.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);

        try {
            var argLength = args.length;
            var result;
            var total = 0;
            var sum = 0;
            for (var i = 1; i < arguments.length; i++) {
                var item = arguments[i];
                if (item && item.getRow) {
                    var row = item.getRow();
                    var rowCount = item.getRowCount();
                    var column = item.getColumn();
                    var columnCount = item.getColumnCount();
                    var sheet = item.getSource();
                    var sheetName = context.ctx.source.getName();
                    var sheetIndex = spread.getSheetIndex(sheetName);
                    var valueArr = [];
                    var sum = 0;
                    // debugger
                    for (var j = row; j < row + rowCount; j++) {
                        for (var k = column; k < column + columnCount; k++) {
                            var nodeName = _getNodeName(j + 1, k + 1, context) || "";
                            if (nodeName == args[2]) {
                                var val = moneyToNumValue(getCellText(sheetIndex, j, k));
                                sum += resolveFormulaVal(val);
                            }
                        }
                    }
                    total += sum;
                }
            }
            return resolveFormulaVal(total);
        } catch (error) {
            // 此处是负责例外处理的语句
            console.log(error);
            return 0;
        }
    };
    CF_GET_BJ_ZC_SUM.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_BJ_ZC_SUM", new CF_GET_BJ_ZC_SUM());
}



/**
 * 此方法用于表间公式,处理不同报表之间的参数数据
 *
 * 例:=(CF_GET_BJ_ZC_DIFF(table_10101_003,"H20","BQ","N")+0)
 */
function regist_CF_GET_BJ_ZC_DIFF() {
    function CF_GET_BJ_ZC_DIFF() {
        this.name = "CF_GET_BJ_ZC_DIFF";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_BJ_ZC_DIFF.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_BJ_ZC_DIFF.prototype.description = function () {
        return {
            description: "",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_BJ_ZC_DIFF.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_BJ_ZC_DIFF.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);
        try {
            var argLength = args.length;
            if (argLength == 3) {
                var result;
                var sheetName = context.ctx.source.getName();
                var sheetIndex = spread.getSheetIndex(sheetName);
                var sheet = spread.sheets[sheetIndex];
                var sum = 0;
                for (var i = 1; i < arguments.length; i++) {
                    //
                    var item = arguments[i];
                    // 判断当item是一个引用参数时
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        var sheet = item.getSource();
                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {

                                var val = sheet.getValue(j, k) || 0;
                                sum += resolveFormulaVal(val);
                            }
                        }
                    }
                }
                return resolveFormulaVal(sum);
            } else if (argLength == 5) {
                // 此处是 其他表  并且获取不到点位信息时的判断条件
                var sheetName = args[1]; //当前报表名称
                var paramNodeName = args[2]; //当前传入的nodeName
                var sheetIndex = spread.getSheetIndex(sheetName);
                var sheet = spread.sheets[sheetIndex];
                var sum = 0;
                for (var i = 1; i < arguments.length; i++) {
                    var item = arguments[i];
                    // 判断当item是一个引用参数时
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        var sheet = item.getSource();
                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var nodeName = _getNodeNameBySheetName(j + 1, k + 1, sheetName) || "";
                                if (nodeName == paramNodeName) {
                                    var val = sheet.getValue(j, k) || 0;
                                    return resolveFormulaVal(val);
                                }
                            }
                        }
                    }
                }
                return 0;
            } else {
                //极端情况 就是依赖的表已经被删除
                //直接返回0就行
                return 0;
            }
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    CF_GET_BJ_ZC_DIFF.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_BJ_ZC_DIFF", new CF_GET_BJ_ZC_DIFF());
}

/**
 * 注册表间带条件的公式 
 * 用于带条件的公式处理(区分直接传入参数和传入报表代码获取NodeName的情况)
 *
 */
function regist_SELF_TJ_FORMULA() {
    /**
     * 取其他税种累计数的方法
     */
    function SELF_TJ_FORMULA() {
        this.name = "SELF_TJ_FORMULA";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    SELF_TJ_FORMULA.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    SELF_TJ_FORMULA.prototype.description = function () {
        return {
            description: "表间带条件的公式",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    SELF_TJ_FORMULA.prototype.acceptsReference = function () {
        return true;
    };
    SELF_TJ_FORMULA.prototype.isContextSensitive = function () {
        return true;
    };

    SELF_TJ_FORMULA.prototype.evaluateAsync = function (context) {
        var result;
        // 10102_003_02!B21, BQ, N
        var args = Array.prototype.slice.call(arguments).slice(1);
        try {
            if (args.length == 3) {
                var result;
                var sheetName = context.ctx.source.getName();
                var sheetIndex = spread.getSheetIndex(sheetName);
                var sheet = spread.sheets[sheetIndex];
                var sum = 0;
                for (var i = 1; i < arguments.length; i++) {
                    //
                    var item = arguments[i];
                    // 判断当item是一个引用参数时
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        var sheet = item.getSource();
                        /*
                         * 根据获取到的range来遍历单元格的值
                         *
                         * 此处按range的列来遍历，想按行遍历把两个循环顺序变一下就行
                         *
                         * Demo中对每个Range内的所有值执行了求和操作
                         *
                         * */
                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) { 
                                // 10414_027特殊处理，因为单元格为字符串                        
                                if (sheetName == "table_10414_027") {
                                    var val = (sheet && sheet.getValue(j, k)) || "";
                                    if (isNaN(val)) {
                                        //不是数字 直接返回
                                        sum = val;
                                        break;
                                    } else if (val == 0 && $.trim(val).length != 0) {
                                        //"000"
                                        sum = "1";
                                        break;
                                    } else {
                                        sum += resolveFormulaVal(val);
                                    }
                                } else {
                                    var val = (sheet && sheet.getValue(j, k)) || 0;
                                    sum += resolveFormulaVal(val);
                                }
                            }
                        }
                    }
                }
                if (sheetName == "table_10414_027") {
                    if ($.trim(sum).length == 0) {
                        return "0";
                    }
                    if (isNaN(sum) && $.trim(sum).length > 0) {
                        return "1";
                    } else {
                        return resolveFormulaVal(sum).toString();
                    }
                } else {
                    if (sum < 0) {
                        return resolveFormulaVal(sum);
                    } else {
                        return resolveFormulaVal(sum).toString();
                    }
                }
            } else if (args.length == 5) {

                // 此处是 其他表  并且获取不到点位信息时的判断条件
                var sheetName = args[1]; //当前报表名称
                var paramNodeName = args[2];
                var sheetIndex = spread.getSheetIndex(sheetName);
                var sheet = spread.sheets[sheetIndex];
                var sum = 0;
                for (var i = 1; i < arguments.length; i++) {
                    var item = arguments[i];
                    // 判断当item是一个引用参数时
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        var sheet = item.getSource();
                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var nodeName = _getNodeNameBySheetName(j + 1, k + 1, sheetName) || "";
                                if (nodeName == paramNodeName) {
                                    var val = sheet.getValue(j, k) || 0;
                                    return resolveFormulaVal(val);
                                }
                            }
                        }
                    }
                }
                return 0;
            } else {
                return 0;
            }
        } catch (error) {
            // 此处是负责例外处理的语句
            console.log(error);
            return 0;
        }
    };

    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("SELF_TJ_FORMULA", new SELF_TJ_FORMULA());
}

/*
'##::: ##:'########:'##:::::'##::::'###::::'########::'########::
 ###:: ##: ##.....:: ##:'##: ##:::'## ##::: ##.... ##: ##.... ##:
 ####: ##: ##::::::: ##: ##: ##::'##:. ##:: ##:::: ##: ##:::: ##:
 ## ## ##: ######::: ##: ##: ##:'##:::. ##: ##:::: ##: ##:::: ##:
 ##. ####: ##...:::: ##: ##: ##: #########: ##:::: ##: ##:::: ##:
 ##:. ###: ##::::::: ##: ##: ##: ##.... ##: ##:::: ##: ##:::: ##:
 ##::. ##: ########:. ###. ###:: ##:::: ##: ########:: ########::
..::::..::........:::...::...:::..:::::..::........:::........:::
*/



// INFO 无具体逻辑,只不过不为了让页面报错
function regist_CELL() {
    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CELL() {
        this.name = "CELL";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CELL.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CELL.prototype.description = function () {
        return {
            description: "自定义cell方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CELL.prototype.acceptsReference = function () {
        return true;
    };
    CELL.prototype.evaluateAsync = function (context) {
        return 0;
    };
    CELL.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CELL", new CELL());
}

/**
 * 某些checkbox需根据相应的值做出选中/不选中状态
 * 此公式仅适用于checkbox单元格中
 *
 */
function regist_EQUAL_CHECK() {
    function EQUAL_CHECK() {
        this.name = "EQUAL_CHECK";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    EQUAL_CHECK.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    EQUAL_CHECK.prototype.description = function () {
        return {
            description: "自定义cell方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    EQUAL_CHECK.prototype.acceptsReference = function () {
        return true;
    };
    EQUAL_CHECK.prototype.evaluateAsync = function (context) {
        try {
            var args = Array.prototype.slice.call(arguments).slice(1);
            // var value = 
            var currentValue = args[1];
            var _val = "";
            var valueArr = [];
            for (var i = 1; i < arguments.length; i++) {
                var item = arguments[i];
                // 判断当item是一个引用参数时
                if (item && item.getRow) {
                    var row = item.getRow();
                    var rowCount = item.getRowCount();
                    var column = item.getColumn();
                    var columnCount = item.getColumnCount();
                    var sheetName = context.ctx.source.getName();
                    var sheetIndex = spread.getSheetIndex(sheetName);
                    var sheet = spread.sheets[sheetIndex];
                    for (var j = row; j < row + rowCount; j++) {
                        for (var k = column; k < column + 1; k++) {
                            var val = sheet.getValue(j, k) || 0;
                            if (val) {
                                _val = val;
                            }
                        }
                    }
                }
            }
            // = IF(AND((L28 = 1), (J18 <= L26)), 1, IF(AND((L28 = 2), (J18 <= L26)), 1, 0))
            if (_val == "" || _val == 0) {

                if (currentValue == "10") {
                    return true;
                } else {
                    return currentValue == val || false;
                }
            } else {
                return currentValue == _val;
            }
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    EQUAL_CHECK.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("EQUAL_CHECK", new EQUAL_CHECK());
}

/**
 * 此方法用于特殊报表取值  隐藏行中包含自定义公式
 *
 */
function regist_SPECIAL_VAL() {
    /**
     * 获取基本信息方法(根据 key 获取基本信息对应 value)
     */
    function SPECIAL_VAL() {
        this.name = "SPECIAL_VAL";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    SPECIAL_VAL.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    SPECIAL_VAL.prototype.description = function () {
        return {
            description: "特殊报表取值方法",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    SPECIAL_VAL.prototype.acceptsReference = function () {
        return true;
    };
    SPECIAL_VAL.prototype.evaluateAsync = function (context) {
        try {
            var args = Array.prototype.slice.call(arguments).slice(1);
            var result = [];
            // 通过var comboBoxCellType = sheet.getCellType(x, y);获取comboBox对象后，根据comboBoxCellType.items()获取下拉框中的所有数据，然后通过循环遍历来获取您指定的值和文本
            // https://gcdn.grapecity.com.cn/forum.php?mod=viewthread&tid=43088&highlight=%CF%C2%C0%AD%2B%D6%B5
            if (args.length == 3) {
                var specialCode = args[1];
                var specialParam = args[2];
                var sheetName = context.ctx.source.getName();
                for (var i = 1; i < arguments.length; i++) {
                    var item = arguments[i];
                    // 判断当item是一个引用参数时
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        // var sheet = item.getSource();
                        var sheetName = context.ctx.source.getName();
                        var sheetIndex = spread.getSheetIndex(sheetName);
                        var sheet = spread.sheets[sheetIndex];

                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var extendSpecialName = _getSpecialNameBySheetName(j + 1, k + 1, sheetName) || "";
                                if (extendSpecialName && (extendSpecialName == specialCode)) {
                                    var val = sheet.getValue(j, k) || 0;
                                    var comboBoxCellType = sheet.getCellType(j, k);
                                    var list = comboBoxCellType.items();
                                    var _val = "";
                                    list.map(function (x) {
                                        if (x.text == val) {
                                            switch (specialParam) {
                                                case 'FLDM':
                                                    _val = x.value.split(',')[3];
                                                    break;
                                                case 'SL':
                                                    _val = x.value.split(',')[2];
                                                    break;
                                                case 'ZSPMDM':
                                                    _val = x.value.split(',')[0];
                                                    break;
                                                case 'ZSPMMC':
                                                    _val = x.value.split(',')[1];
                                                    break;
                                                case 'JMYYDM':
                                                    _val = x.value.split(' ')[0];
                                                    break;
                                                case 'JMXZDM':
                                                    _val = x.text.split(' ')[0];
                                                    break;
                                                case 'JMXMMC':
                                                    _val = x.value.split(' ')[1];
                                                    break;
                                            }
                                        }
                                    });
                                }
                            }
                        }
                        if (_val == '' && specialParam == 'SL') {
                            _val = 0;
                        }
                        return _val;
                    }
                }
            } else if (args.length == 4) {
                var specialCode = args[1];
                var specialParam = args[2];
                var slType = args[3];
                var sheetName = context.ctx.source.getName();
                for (var i = 1; i < arguments.length; i++) {
                    var item = arguments[i];
                    // 判断当item是一个引用参数时
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        // var sheet = item.getSource();
                        var sheetName = context.ctx.source.getName();
                        var sheetIndex = spread.getSheetIndex(sheetName);
                        var sheet = spread.sheets[sheetIndex];

                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var extendSpecialName = _getSpecialNameBySheetName(j + 1, k + 1, sheetName) || "";
                                if (extendSpecialName && (extendSpecialName == specialCode)) {
                                    var val = sheet.getValue(j, k) || 0;
                                    var comboBoxCellType = sheet.getCellType(j, k);
                                    var list = comboBoxCellType.items();
                                    var _val = "";
                                    list.map(function (x) {
                                        if (x.text == val) {
                                            if (specialParam == 'SL') {
                                                var zspmDm = Number(x.value.split(',')[0]);
                                                var clList = [101020105, 101020104, 101020202, 101020204, 101020205, 101020206, 101020207];
                                                var cjList = [101020101, 101020102, 101020107, 101020108, 101020201, 101020203, 101020299];
                                                if (slType == 'CJ' && clList.indexOf(zspmDm) == -1) {
                                                    _val = x.value.split(',')[2];
                                                } else if (slType == 'CL' && cjList.indexOf(zspmDm) == -1) {
                                                    _val = x.value.split(',')[2];
                                                } else {
                                                    _val = 0;
                                                }
                                            } else {
                                                _val = 0;
                                            }
                                        }
                                    });
                                }
                            }
                        }
                        return _val === '' ? 0 : _val;
                    }
                }
            } else {
                //其他意外情况处理
                return 0;
            }
            // return result;
        } catch (error) {
            consol.log(error);
            return 0;
        }
    };
    SPECIAL_VAL.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("SPECIAL_VAL", new SPECIAL_VAL());
}

/**
 * 此方法用于企业所得税10401_004分支机构报表根据独立部门标志取分配比例和分配所得税额
 *FZJG_FPBL(K:K,"FPBL")
 */
function regist_FZJG_FPBL() {
    /**
     *分支机构报表取分配比例和分配所得税额
     */
    function FZJG_FPBL() {
        this.name = "FZJG_FPBL";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    FZJG_FPBL.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    FZJG_FPBL.prototype.description = function () {
        return {
            description: "分支机构报表取分配比例和分配所得税额",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    FZJG_FPBL.prototype.acceptsReference = function () {
        return true;
    };
    FZJG_FPBL.prototype.evaluateAsync = function (context) {
        try {
            var args = Array.prototype.slice.call(arguments).slice(1);
            var sheetName = context.ctx.source.getName();
            var sheetIndex = spread.getSheetIndex(sheetName);
            var sheet = spread.sheets[sheetIndex];
            if (args.length == 2) {
                // 2个参数 根据独立部门标志取分配比例和分配所得税额
                var sum = 0;
                for (var i = 1; i < arguments.length; i++) {
                    var item = arguments[i];
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();
                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var nodeName = _getNodeName(j + 1, k + 1, context) || "";
                                if (nodeName === args[1]) {
                                    if (sheetName == "table_10414_043") {
                                        var flag2 = sheet.getValue(j, 13) || "";
                                    } else {
                                        var flag2 = sheet.getValue(j, 16) || "";
                                    }
                                    if (flag2 == 'dlbm') {
                                        var val = sheet && sheet.getValue(j, k) || 0;
                                        sum += Number(val)
                                    }
                                }
                            }
                        }
                    }
                }
                return sum;
            } else {
                // 三个参数 右上角取代理部门分配比例和分配税额合计
                var nodeName = args[1]
                var result = []
                for (var i = 1; i < arguments.length; i++) {
                    var item = arguments[i];
                    if (item && item.getRow) {
                        var row = item.getRow();
                        var rowCount = item.getRowCount();
                        var column = item.getColumn();
                        var columnCount = item.getColumnCount();

                        for (var j = row; j < row + rowCount; j++) {
                            for (var k = column; k < column + columnCount; k++) {
                                var nodeName = _getNodeName(j + 1, k + 1, context) || "";
                                if (nodeName === args[1]) {
                                    var val = sheet && sheet.getValue(j, k) || 0;
                                }
                            }
                        }
                    }
                }
                return val
            }

        } catch (error) {
            consol.log(error);
            return 0;
        }
    };
    FZJG_FPBL.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("FZJG_FPBL", new FZJG_FPBL());
}
/**
 *10411 扣缴所得税报告表 特殊处理税款所属时间公式
 *
 */
function regist_DATESTR() {
    /**
     * 扣缴所得税报告表 特殊处理税款所属时间公式
     */
    function DATESTR() {
        this.name = "DATESTR";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    DATESTR.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    DATESTR.prototype.description = function () {
        return {
            description: "扣缴所得税报告表 特殊处理税款所属时间公式",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    DATESTR.prototype.acceptsReference = function () {
        return true;
    };
    DATESTR.prototype.evaluateAsync = function (context) {
        try {
            var args = Array.prototype.slice.call(arguments).slice(1);
            var sheetName = context.ctx.source.getName();
            var sheetIndex = spread.getSheetIndex(sheetName);
            var sheet = spread.sheets[sheetIndex];
            var value = (sheet && sheet.getValue(args[0].getRow(), args[0].getColumn())) || "";
            if (value !== "") {
                var _value = value.split('-')[0] + '年' + value.split('-')[1] + '月' + value.split('-')[2] + '日'
            } else {
                var _value = ""
            }
            return _value;
        } catch (error) {
            consol.log(error);
            return 0;
        }
    };
    DATESTR.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("DATESTR", new DATESTR());
}


/**
 * 此方法用于表间公式,处理不同报表之间的参数数据
 *
 * 例:=(CF_GET_BJ_ZC_DIFF(table_10101_003,"H20","BQ","N")+0)
 */
function regist_TOFIND() {
    function TOFIND() {
        this.name = "TOFIND";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    TOFIND.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    TOFIND.prototype.description = function () {
        return {
            description: "",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    TOFIND.prototype.acceptsReference = function () {
        return true;
    };
    TOFIND.prototype.evaluateAsync = function (context) {
        var args = Array.prototype.slice.call(arguments).slice(1);
        try {
            var argLength = args.length;
            var sheetName = context.ctx.source.getName();
            var sheetIndex = spread.getSheetIndex(sheetName);
            var sheet = spread.sheets[sheetIndex];
            var result = -1;
            var val;
            for (var i = 1; i < arguments.length; i++) {
                //
                var item = arguments[i];
                // 判断当item是一个引用参数时
                if (item && item.getRow) {
                    var row = item.getRow();
                    var rowCount = item.getRowCount();
                    var column = item.getColumn();
                    var columnCount = item.getColumnCount();
                    var sheet = item.getSource();
                    for (var j = row; j < row + rowCount; j++) {
                        for (var k = column; k < column + columnCount; k++) {
                            val = sheet.getValue(j, k) || "";
                            if (val.indexOf(args[argLength - 1]) > -1) {
                                return 1
                            }
                        }
                    }
                }
            }
            return result;
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    TOFIND.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("TOFIND", new TOFIND());
}

/*
'##::::'##:'########:'########:'##::::'##::'#######::'########:::'######::
 ###::'###: ##.....::... ##..:: ##:::: ##:'##.... ##: ##.... ##:'##... ##:
 ####'####: ##:::::::::: ##:::: ##:::: ##: ##:::: ##: ##:::: ##: ##:::..::
 ## ### ##: ######:::::: ##:::: #########: ##:::: ##: ##:::: ##:. ######::
 ##. #: ##: ##...::::::: ##:::: ##.... ##: ##:::: ##: ##:::: ##::..... ##:
 ##:.:: ##: ##:::::::::: ##:::: ##:::: ##: ##:::: ##: ##:::: ##:'##::: ##:
 ##:::: ##: ########:::: ##:::: ##:::: ##:. #######:: ########::. ######::
..:::::..::........:::::..:::::..:::::..:::.......:::........::::......:::
*/

/**
 * 将金额转换为正常数字
 *"1,234,567.00" => "1234567.00"
 * @param {*} val
 * @returns
 */
function moneyToNumValue(val) {
    var num = $.trim(val);
    var ss = num.toString();
    if (ss.length == 0) {
        return "0";
    }
    return ss.replace(/,/g, "");
}

/**
 *将字符串类型数字值强转为数字
 *
 * @param {*} val
 * @returns
 */
function resolveFormulaVal(val) {
    return isNaN(val) ? 0 : Number(val);
}

/**
 * 根据当前表格的位置获取nodeName
 *
 * @param {*} row 行坐标 从0开始
 * @param {*} col 列坐标 从0开始
 * @param {*} context 全局上下文
 * @returns
 */
function _getNodeName(row, col, context) {
    var point = [row - 1, col - 1];
    var sheetName = context.ctx.source.getName();

    var currentDataTable = extend_data[sheetName].data.datatable;
    var cell = currentDataTable[point[0]] && currentDataTable[point[0]][point[1]];
    var nodeNameVal = cell && cell.nodeName || "";
    return nodeNameVal;
}

/**
 * 此方法用于没有context环境时  根据sheetName获取相应的nodeName
 *
 * @param {*} row
 * @param {*} col
 * @param {*} sheetName
 * @returns
 */
function _getNodeNameBySheetName(row, col, sheetName) {
    var point = [row - 1, col - 1];
    // var sheetName = context.ctx.source.getName();

    var currentDataTable = extend_data[sheetName].data.datatable;
    var cell = currentDataTable[point[0]] && currentDataTable[point[0]][point[1]];
    var nodeNameVal = cell && cell.nodeName || "";
    return nodeNameVal;
}

/**
 * 此方法用于没有context环境时  根据sheetName获取相应的nodeName
 *
 * @param {*} row
 * @param {*} col
 * @param {*} sheetName
 * @returns
 */
function _getSpecialNameBySheetName(row, col, sheetName) {
    var point = [row - 1, col - 1];
    var currentDataTable = extend_data[sheetName].data.datatable;
    var cell = currentDataTable[point[0]] && currentDataTable[point[0]][point[1]];
    return (cell && cell.specialCode) || "";
}
/**
 * 将传入的表内公式转为自定义格式标准格式
 *
 * @param {*} oldStr
 * @returns
 */
function _formulaHandler(oldStr) {
    //将公式置为大写
    oldStr = oldStr.toUpperCase();
    oldStr = oldStr.replace(/COL\(\)/gi, 'COLUMN()');
    // cf_get_bbhj(String bbdm, String jdmc, String as_flag)
    if (oldStr.indexOf('COLUMN(),ROW()') > -1) { }
}


/**
 *根据名字获取索引
 *
 * @param {*} sheetName
 * @param {*} name
 * @returns
 */
function getPosByName(sheetName, name) {
    var sheet = null;
    name = name.toUpperCase();
    $.each(extend_data, function (key) {
        if (key == sheetName) {
            sheet = extend_data[key];
        }
    });
    if (!sheet) {
        return [];
    }
    var optionDataTable = sheet.data.datatable;
    var posArr = [];
    $.each(optionDataTable, function (rowIndex, row) {
        $.each(row, function (colIndex, col) {
            var tdOption = optionDataTable[rowIndex][colIndex];
            if (tdOption.nodeName === name) {
                var pos = {
                    'rowIndex': rowIndex,
                    'colIndex': colIndex
                };
                posArr.push(pos);
            }
        });
    });
    return posArr;
}

// if(CF_GET_ZZS_LJ_NEW("ISXWXBQYBZ")="Y",1,0)
function regist_CF_GET_ZZS_LJ_NEW() {
    /**
     * 取所得税累计数方法(根据单元格的节点名称name取json对应数据)
     */
    function CF_GET_ZZS_LJ_NEW() {
        this.name = "CF_GET_ZZS_LJ_NEW";
    }
    CF_GET_ZZS_LJ_NEW.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_ZZS_LJ_NEW.prototype.evaluateAsync = function (context) {
        try {
            var args = Array.prototype.slice.call(arguments).slice(1);
            var nodeNameVal = args[0];
            var value = 0;
            if (nodeNameVal) {
                value = GLOBAL_JSON["wsxx"] && GLOBAL_JSON["wsxx"][nodeNameVal] && GLOBAL_JSON["wsxx"][nodeNameVal].value || 0;
                // 小微企业判断标志
                if (nodeNameVal == "ISXWXBQYBZ") {
                    if (value == "N") {
                        value = 0
                    } else if (value == "Y") {
                        value = 1
                    } else if (value == "X") {
                        value = 2
                    }
                }
            }

            return resolveFormulaVal(value);
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_ZZS_LJ_NEW", new CF_GET_ZZS_LJ_NEW());
}


/**
 * 注册 取10101_026中的单元格的值
 * 
 * cf_get_qyFzjg_bl([Double col], String nodeName, String cellType) => cf_get_qyfzjg_bl(F:F,"YBHWJLWXSSRHJ","hj")
 *
 * cellType: "HJ":合计单元格 "CELL":普通单元格
 * 
 */
function regist_CF_GET_QYFZJG_BL() {
    function CF_GET_QYFZJG_BL() {
        this.name = "CF_GET_QYFZJG_BL";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_QYFZJG_BL.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_QYFZJG_BL.prototype.description = function () {
        return {
            description: "获取特殊单元格的值",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_QYFZJG_BL.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_QYFZJG_BL.prototype.evaluateAsync = function (context) {
        try {
            var tableSource = arguments[1],
                nodeNameVal = arguments[2],
                cellType = arguments[3];
            if (tableSource && tableSource.getRow) {
                var row = context.row, // 获取当前行
                    rowCount = tableSource.getRowCount(), // 获取总行数
                    column = tableSource.getColumn(), // 获取当前列
                    sheet = tableSource.getSource();
                if (cellType == "HJ") {
                    // 获取合计单元值的值
                    for (var j = row; j < row + rowCount; j++) {
                        var nodeName = _getNodeName(j + 1, column + 1, context) || "";
                        if (nodeName != "" && nodeName == nodeNameVal) {
                            var val = sheet && sheet.getValue(j, column) || 0;
                            return val;
                        }
                    }
                } else {
                    // 获取普通单元值的值
                    var nodeName = _getNodeName(row + 1, column + 1, context) || "";
                    if (nodeName != "" && nodeName == nodeNameVal) {
                        var val = sheet && sheet.getValue(row, column) || 0;
                        return val;
                    }
                }
            }
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    CF_GET_QYFZJG_BL.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_QYFZJG_BL", new CF_GET_QYFZJG_BL());
}


/**
 * 获取年报中单元格的数据
 *
 */
function regist_NB_GET_CELL_VAL() {
    function NB_GET_CELL_VAL() {
        this.name = "NB_GET_CELL_VAL";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    NB_GET_CELL_VAL.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    NB_GET_CELL_VAL.prototype.description = function () {
        return {
            description: "获取年报中特殊单元格的值",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    NB_GET_CELL_VAL.prototype.acceptsReference = function () {
        return true;
    };
    NB_GET_CELL_VAL.prototype.evaluateAsync = function (context) {
        try {
            var tableSource = arguments[1],
                nodeNameVal = arguments[2],
                cellType = arguments[3];
            if (tableSource && tableSource.getRow) {
                var row = context.row, // 获取当前行
                    rowCount = tableSource.getRowCount(), // 获取总行数
                    column = tableSource.getColumn(), // 获取当前列
                    sheet = tableSource.getSource();
                if (cellType == "HJ") {
                    // 获取合计单元值的值
                    for (var j = row; j < row + rowCount; j++) {
                        var nodeName = _getNodeName(j + 1, column + 1, context) || "";
                        if (nodeName != "" && nodeName == nodeNameVal) {
                            var val = sheet && sheet.getValue(j, column) || 0;
                            return val;
                        }
                    }
                } else {
                    // 获取普通单元值的值
                    var nodeName = _getNodeName(row + 1, column + 1, context) || "";
                    if (nodeName != "" && nodeName == nodeNameVal) {
                        var val = sheet && sheet.getValue(row, column) || 0;
                        return val;
                    }
                }
            }
        } catch (error) {
            console.log(error);
            return 0;
        }
    };
    NB_GET_CELL_VAL.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("NB_GET_CELL_VAL", new NB_GET_CELL_VAL());
}

/**
 * 注册 根据codeName获取对应的数据 在年报的fllsxx里
 * 1. cf_get_nb_celldata(String nodeName,String year)
 * nodeName:节点名称 year：年度
 */
function regist_CF_GET_NB_CELLDATA() {
    function CF_GET_NB_CELLDATA() {
        this.name = "CF_GET_NB_CELLDATA";
        this.maxArgs = 255;
        this.minArgs = 1;
    }
    CF_GET_NB_CELLDATA.prototype = new GC.Spread.CalcEngine.Functions.AsyncFunction();
    CF_GET_NB_CELLDATA.prototype.description = function () {
        return {
            description: "根据codeName获取对应的数据",
            parameters: [{
                name: "value",
                repeatable: true,
                optional: true
            }]
        };
    };
    CF_GET_NB_CELLDATA.prototype.acceptsReference = function () {
        return true;
    };
    CF_GET_NB_CELLDATA.prototype.evaluateAsync = function (context) {
        try {
            var args = Array.prototype.slice.call(arguments).slice(1);
            var arg1 = args[0];
            var arg2 = args[1];
            var baseInfo = NB_getFllsxxBaseInfo(arg2);
            var cellObj = null;
            baseInfo.forEach(function (x) {
                if (x.code.toUpperCase() == arg1) {
                    cellObj = x.value;
                }
            });
            return cellObj;
        } catch (error) {
            return 0;
        }
    };
    CF_GET_NB_CELLDATA.prototype.isContextSensitive = function () {
        return true;
    };
    GC.Spread.CalcEngine.Functions.defineGlobalCustomFunction("CF_GET_NB_CELLDATA", new CF_GET_NB_CELLDATA());
}
