You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
687 lines
19 KiB
687 lines
19 KiB
import { getObjType } from '../utils/util';
|
|
import { isRealNum, isRealNull, valueIsError } from './validate';
|
|
import { update } from './format';
|
|
import formula from './formula';
|
|
import dayjs from "dayjs";
|
|
|
|
const error = {
|
|
v: "#VALUE!", //错误的参数或运算符
|
|
n: "#NAME?", //公式名称错误
|
|
na: "#N/A", //函数或公式中没有可用数值
|
|
r: "#REF!", //删除了由其他公式引用的单元格
|
|
d: "#DIV/0!", //除数是0或空单元格
|
|
nm: "#NUM!", //当公式或函数中某个数字有问题时
|
|
nl: "#NULL!", //交叉运算符(空格)使用不正确
|
|
sp: "#SPILL!" //数组范围有其它值
|
|
}
|
|
|
|
const func_methods = {
|
|
//单元格数据生成一维数组
|
|
getCellDataArr: function(rangeObj, nullCellType, isNeglectNullCell){
|
|
let dataArr = [];
|
|
|
|
if(rangeObj.data == null){
|
|
if(!isNeglectNullCell){
|
|
if(nullCellType === "number"){
|
|
dataArr.push(0);
|
|
}
|
|
else if(nullCellType === "text"){
|
|
dataArr.push("");
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
if(getObjType(rangeObj.data) === "array"){
|
|
for(let i = 0; i < rangeObj.data.length; i++){
|
|
for(let j = 0; j < rangeObj.data[i].length; j++){
|
|
let cell = rangeObj.data[i][j];
|
|
let value = cell
|
|
|
|
if(getObjType(cell) === 'object'){
|
|
value = cell.v
|
|
}
|
|
|
|
if(value == null ){
|
|
if(!isNeglectNullCell){
|
|
if(nullCellType === "number"){
|
|
value = 0;
|
|
}
|
|
else if(nullCellType === "text"){
|
|
value = '';
|
|
}
|
|
|
|
dataArr.push(value);
|
|
}
|
|
}
|
|
else{
|
|
dataArr.push(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
if(isRealNull(rangeObj.data.v)){
|
|
if(!isNeglectNullCell){
|
|
if(nullCellType == "number"){
|
|
dataArr.push(0);
|
|
}
|
|
else if(nullCellType == "text"){
|
|
dataArr.push("");
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
dataArr.push(rangeObj.data.v);
|
|
}
|
|
}
|
|
}
|
|
|
|
return dataArr;
|
|
},
|
|
//单元格数据生成二维数组
|
|
getCellDataDyadicArr: function(rangeObj, nullCellType){
|
|
let dataArr = [];
|
|
|
|
if(rangeObj.data == null){
|
|
let rowArr = [];
|
|
|
|
if(nullCellType == "number"){
|
|
rowArr.push(0);
|
|
}
|
|
else if(nullCellType == "text"){
|
|
rowArr.push("");
|
|
}
|
|
|
|
dataArr.push(rowArr);
|
|
}
|
|
else{
|
|
if(getObjType(rangeObj.data) == "array"){
|
|
for(let i = 0; i < rangeObj.data.length; i++){
|
|
let rowArr = [];
|
|
|
|
for(let j = 0; j < rangeObj.data[i].length; j++){
|
|
let cell = rangeObj.data[i][j];
|
|
let value = cell;
|
|
|
|
if(getObjType(cell) === 'object'){
|
|
value = cell.v
|
|
}
|
|
|
|
if(value == null){
|
|
if(nullCellType === "number"){
|
|
value = 0;
|
|
}
|
|
else if(nullCellType === "text"){
|
|
value = '';
|
|
}
|
|
}
|
|
|
|
rowArr.push(value);
|
|
}
|
|
|
|
dataArr.push(rowArr);
|
|
}
|
|
}
|
|
else{
|
|
let rowArr = [];
|
|
|
|
let value = rangeObj.data.v;
|
|
|
|
if(isRealNull(value)){
|
|
if(nullCellType == "number"){
|
|
value = 0;
|
|
}
|
|
else if(nullCellType == "text"){
|
|
value = "";
|
|
}
|
|
}
|
|
|
|
rowArr.push(value);
|
|
|
|
dataArr.push(rowArr);
|
|
}
|
|
}
|
|
|
|
return dataArr;
|
|
},
|
|
//数组数据生成一维数组
|
|
getDataArr: function(arr, isNeglectNaN){
|
|
let dataArr = [];
|
|
|
|
if(isNeglectNaN == null){
|
|
isNeglectNaN = false;
|
|
}
|
|
|
|
if(getObjType(arr[0]) == "array"){
|
|
for(let i = 0; i < arr.length; i++){
|
|
for(let j = 0; j < arr[i].length; j++){
|
|
if(isNeglectNaN && !isRealNum(arr[i][j])){
|
|
continue;
|
|
}
|
|
|
|
dataArr.push(arr[i][j]);
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
for(let i = 0; i < arr.length; i++){
|
|
if(isNeglectNaN && !isRealNum(arr[i])){
|
|
continue;
|
|
}
|
|
|
|
dataArr.push(arr[i]);
|
|
}
|
|
}
|
|
|
|
return dataArr;
|
|
},
|
|
getDataDyadicArr: function(arr){
|
|
let dataArr = [];
|
|
|
|
if(getObjType(arr[0]) == "array"){
|
|
for(let i = 0; i < arr.length; i++){
|
|
let rowArr = [];
|
|
|
|
for(let j = 0; j < arr[i].length; j++){
|
|
rowArr.push(arr[i][j]);
|
|
}
|
|
|
|
dataArr.push(rowArr);
|
|
}
|
|
}
|
|
else{
|
|
let rowArr = [];
|
|
|
|
for(let i = 0; i < arr.length; i++){
|
|
rowArr.push(arr[i]);
|
|
}
|
|
|
|
dataArr.push(rowArr);
|
|
}
|
|
|
|
return dataArr;
|
|
},
|
|
//是否是规则二维数组
|
|
isDyadicArr: function(arr){
|
|
let isDyadic = true;
|
|
|
|
if(arr.length > 1){
|
|
let collen = arr[0].length;
|
|
|
|
for(let i = 1; i < arr.length; i++){
|
|
if(arr[i].length != collen){
|
|
isDyadic = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return isDyadic;
|
|
},
|
|
//获取单个单元格数据,数组第一个值
|
|
getFirstValue: function(data, nullCellType){
|
|
let _this = this;
|
|
|
|
if(nullCellType == null){
|
|
nullCellType = "number";
|
|
}
|
|
|
|
let value;
|
|
|
|
if(getObjType(data) == "array"){
|
|
if(getObjType(data[0]) == "array"){
|
|
if(!_this.isDyadicArr(data)){
|
|
return error.v;
|
|
}
|
|
|
|
value = data[0][0];
|
|
}
|
|
else{
|
|
value = data[0];
|
|
}
|
|
}
|
|
else if(getObjType(data) == "object" && data.startCell != null){
|
|
if(data.data == null){
|
|
if(nullCellType == "number"){
|
|
value = 0;
|
|
}
|
|
else if(nullCellType == "text"){
|
|
value = "";
|
|
}
|
|
}
|
|
else{
|
|
let cell_r = window.luckysheetCurrentRow;
|
|
let cell_c = window.luckysheetCurrentColumn;
|
|
|
|
if(data.rowl == 1 && data.coll == 1){
|
|
value = data.data;
|
|
|
|
if(value == null || isRealNull(value.v)){
|
|
if(nullCellType == "number"){
|
|
value = 0;
|
|
}
|
|
else if(nullCellType == "text"){
|
|
value = "";
|
|
}
|
|
}
|
|
else{
|
|
value = value.v;
|
|
}
|
|
}
|
|
else{
|
|
if(data.data[0][0].mc != null && data.data[0][0].mc.rs == data.rowl && data.data[0][0].mc.cs == data.coll){
|
|
value = data.data[0][0];
|
|
|
|
if(value == null || isRealNull(value.v)){
|
|
if(nullCellType == "number"){
|
|
value = 0;
|
|
}
|
|
else if(nullCellType == "text"){
|
|
value = "";
|
|
}
|
|
}
|
|
else{
|
|
value = value.v;
|
|
}
|
|
}
|
|
else if(data.rowl == 1 || data.coll == 1){
|
|
let cellrange = formula.getcellrange(data.startCell);
|
|
let str = cellrange.row[0],
|
|
edr = str + data.rowl - 1,
|
|
stc = cellrange.column[0],
|
|
edc = stc + data.coll - 1;
|
|
|
|
if(data.rowl == 1){
|
|
if(cell_c < stc || cell_c > edc){
|
|
return error.v;
|
|
}
|
|
|
|
value = data.data[0][cell_c - stc];
|
|
}
|
|
else if(data.coll == 1){
|
|
if(cell_r < str || cell_r > edr){
|
|
return error.v;
|
|
}
|
|
|
|
value = data.data[cell_r - str][0];
|
|
}
|
|
|
|
if(value == null || isRealNull(value.v) || value.mc != null){
|
|
if(nullCellType == "number"){
|
|
value = 0;
|
|
}
|
|
else if(nullCellType == "text"){
|
|
value = "";
|
|
}
|
|
}
|
|
else{
|
|
value = value.v;
|
|
}
|
|
}
|
|
else{
|
|
return error.v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
value = data;
|
|
}
|
|
|
|
return value;
|
|
},
|
|
//获取单元格的逻辑值
|
|
getCellBoolen: function(data){
|
|
let _this = this;
|
|
|
|
let cumulative = _this.getFirstValue(data);
|
|
|
|
if(valueIsError(cumulative)){
|
|
return cumulative;
|
|
}
|
|
|
|
if(getObjType(cumulative) == "boolean"){
|
|
|
|
}
|
|
else if(getObjType(cumulative) == "string" && (cumulative.toLowerCase() == "true" || cumulative.toLowerCase() == "false")){
|
|
if(cumulative.toLowerCase() == "true"){
|
|
cumulative = true;
|
|
}
|
|
else if(cumulative.toLowerCase() == "false"){
|
|
cumulative = false;
|
|
}
|
|
}
|
|
else if(isRealNum(cumulative)){
|
|
cumulative = parseFloat(cumulative);
|
|
|
|
cumulative = cumulative == 0 ? false : true;
|
|
}
|
|
else{
|
|
return error.v;
|
|
}
|
|
|
|
return cumulative;
|
|
},
|
|
//获取单元格的日期
|
|
getCellDate: function(data){
|
|
let _this = this;
|
|
|
|
let date_text;
|
|
|
|
if(getObjType(data) == "array"){
|
|
if(getObjType(data[0]) == "array"){
|
|
if(!_this.isDyadicArr(data)){
|
|
return error.v;
|
|
}
|
|
|
|
date_text = data[0][0];
|
|
}
|
|
else{
|
|
date_text = data[0];
|
|
}
|
|
}
|
|
else if(getObjType(data) == "object" && data.startCell != null){
|
|
if(data.data == null || getObjType(data.data) == "array" || isRealNull(data.data.v)){
|
|
return error.v;
|
|
}
|
|
|
|
date_text = data.data.v;
|
|
|
|
if(data.data.ct != null && data.data.ct.t == "d"){
|
|
date_text = update("YYYY-MM-DD h:mm:ss", date_text);
|
|
}
|
|
}
|
|
else{
|
|
date_text = data;
|
|
}
|
|
|
|
return date_text;
|
|
},
|
|
getCellrangeDate: function(data){
|
|
let _this = this;
|
|
|
|
let date = [];
|
|
|
|
if(getObjType(data) == "array"){
|
|
if(getObjType(data[0]) == "array" && !_this.isDyadicArr(data)){
|
|
return error.v;
|
|
}
|
|
|
|
date = date.concat(_this.getDataArr(data, false));
|
|
}
|
|
else if(getObjType(data) == "object" && data.startCell != null){
|
|
if(data.data == null){
|
|
date.push(0);
|
|
}
|
|
else{
|
|
if(getObjType(data.data) == "array"){
|
|
for(let i = 0; i < data.data.length; i++){
|
|
for(let j = 0; j < data.data[i].length; j++){
|
|
if(data.data[i][j] != null && !isRealNull(data.data[i][j].v)){
|
|
let value = data.data[i][j].v;
|
|
|
|
if(data.data[i][j].ct != null && data.data[i][j].ct.t == "d"){
|
|
value = update("YYYY-MM-DD h:mm:ss", value);
|
|
}
|
|
|
|
date.push(value);
|
|
}
|
|
else{
|
|
date.push(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
let value = data.data.v;
|
|
|
|
if(data.data.ct != null && data.data.ct.t == "d"){
|
|
value = update("YYYY-MM-DD h:mm:ss", value);
|
|
}
|
|
|
|
date.push(value);
|
|
}
|
|
}
|
|
}
|
|
else{
|
|
date.push(data);
|
|
}
|
|
|
|
return date;
|
|
},
|
|
//获取正则字符串(处理 . * ? ~* ~?)
|
|
getRegExpStr: function(str){
|
|
return str.replace("~*", "\\*").replace("~?", "\\?").replace(".", "\\.").replace("*", ".*").replace("?", ".");
|
|
},
|
|
//阶乘
|
|
factorial: function(num){
|
|
if (num == 0 || num == 1) {
|
|
return 1;
|
|
}
|
|
else {
|
|
return (num * this.factorial(num - 1));
|
|
}
|
|
},
|
|
//双阶乘
|
|
factorialDouble: function(num){
|
|
if (num <= 0) {
|
|
return 1;
|
|
}
|
|
else {
|
|
return (num * this.factorialDouble(num - 2));
|
|
}
|
|
},
|
|
//总体方差
|
|
variance: function(num_arr){
|
|
let sum = 0, count = 0;
|
|
|
|
for(let i = 0; i < num_arr.length; i++){
|
|
let number = num_arr[i];
|
|
|
|
sum += number;
|
|
count++;
|
|
}
|
|
|
|
let avg = sum / count;
|
|
|
|
let sum_variance = 0;
|
|
|
|
for(let j = 0; j < num_arr.length; j++){
|
|
let number = num_arr[j];
|
|
|
|
sum_variance += (number - avg) * (number - avg);
|
|
}
|
|
|
|
return sum_variance / count;
|
|
},
|
|
//样本方差
|
|
variance_s: function(num_arr){
|
|
let sum = 0, count = 0;
|
|
|
|
for(let i = 0; i < num_arr.length; i++){
|
|
let number = num_arr[i];
|
|
|
|
sum += number;
|
|
count++;
|
|
}
|
|
|
|
let avg = sum / count;
|
|
|
|
let sum_variance = 0;
|
|
|
|
for(let j = 0; j < num_arr.length; j++){
|
|
let number = num_arr[j];
|
|
|
|
sum_variance += (number - avg) * (number - avg);
|
|
}
|
|
|
|
return sum_variance / (count - 1);
|
|
},
|
|
//总体标准偏差
|
|
standardDeviation: function(num_arr){
|
|
let sum = 0, count = 0;
|
|
|
|
for(let i = 0; i < num_arr.length; i++){
|
|
let number = num_arr[i];
|
|
|
|
sum += number;
|
|
count++;
|
|
}
|
|
|
|
let avg = sum / count;
|
|
|
|
let sum_variance = 0;
|
|
|
|
for(let j = 0; j < num_arr.length; j++){
|
|
let number = num_arr[j];
|
|
|
|
sum_variance += (number - avg) * (number - avg);
|
|
}
|
|
|
|
return Math.sqrt(sum_variance / count);
|
|
},
|
|
//样本标准偏差
|
|
standardDeviation_s: function(num_arr){
|
|
let sum = 0, count = 0;
|
|
|
|
for(let i = 0; i < num_arr.length; i++){
|
|
let number = num_arr[i];
|
|
|
|
sum += number;
|
|
count++;
|
|
}
|
|
|
|
let avg = sum / count;
|
|
|
|
let sum_variance = 0;
|
|
|
|
for(let j = 0; j < num_arr.length; j++){
|
|
let number = num_arr[j];
|
|
|
|
sum_variance += (number - avg) * (number - avg);
|
|
}
|
|
|
|
return Math.sqrt(sum_variance / (count - 1));
|
|
},
|
|
//是否是闰年
|
|
isLeapYear: function(year){
|
|
return new Date(year, 1, 29).getMonth() === 1;
|
|
},
|
|
//2月是否有29
|
|
feb29Between: function(date1, date2){
|
|
let _this = this;
|
|
|
|
let year1 = dayjs(date1).year();
|
|
let mar1year1 = dayjs().set({ 'year': year1, 'month': 2, 'date': 1 });
|
|
|
|
if (_this.isLeapYear(year1) && dayjs(date1) < dayjs(mar1year1) && dayjs(date2) >= dayjs(mar1year1)) {
|
|
return true;
|
|
}
|
|
|
|
let year2 = dayjs(date2).year();
|
|
let mar1year2 = dayjs().set({ 'year': year2, 'month': 2, 'date': 1 });
|
|
|
|
return (_this.isLeapYear(year2) && dayjs(date2) >= dayjs(mar1year2) && dayjs(date1) < dayjs(mar1year2));
|
|
},
|
|
//SQL 查询
|
|
findResultIndex: function(database, criterias){
|
|
let matches = {};
|
|
|
|
for (let i = 1; i < database[0].length; ++i) {
|
|
matches[i] = true;
|
|
}
|
|
|
|
let maxCriteriaLength = criterias[0].length;
|
|
|
|
for (i = 1; i < criterias.length; ++i) {
|
|
if (criterias[i].length > maxCriteriaLength) {
|
|
maxCriteriaLength = criterias[i].length;
|
|
}
|
|
}
|
|
|
|
for (let k = 1; k < database.length; ++k) {
|
|
for (let l = 1; l < database[k].length; ++l) {
|
|
let currentCriteriaResult = false;
|
|
let hasMatchingCriteria = false;
|
|
|
|
for (let j = 0; j < criterias.length; ++j) {
|
|
let criteria = criterias[j];
|
|
|
|
if (criteria.length < maxCriteriaLength) {
|
|
continue;
|
|
}
|
|
|
|
let criteriaField = criteria[0];
|
|
|
|
if (database[k][0] !== criteriaField) {
|
|
continue;
|
|
}
|
|
|
|
hasMatchingCriteria = true;
|
|
|
|
for (let p = 1; p < criteria.length; ++p) {
|
|
currentCriteriaResult = currentCriteriaResult || (new Function("return " + database[k][l] + criteria[p])()); // jshint ignore:line
|
|
}
|
|
}
|
|
|
|
if (hasMatchingCriteria) {
|
|
matches[l] = matches[l] && currentCriteriaResult;
|
|
}
|
|
}
|
|
}
|
|
|
|
let result = [];
|
|
|
|
for (let n = 0; n < database[0].length; ++n) {
|
|
if (matches[n]) {
|
|
result.push(n - 1);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
},
|
|
findField: function(database, title){
|
|
let index = null;
|
|
|
|
for (let i = 0; i < database.length; i++) {
|
|
if (database[i][0] == title) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (index == null) {
|
|
return error.v;
|
|
}
|
|
|
|
return index;
|
|
},
|
|
rest: function(array, idx){
|
|
idx = idx || 1;
|
|
|
|
if (!array || typeof array.slice !== 'function') {
|
|
return array;
|
|
}
|
|
|
|
return array.slice(idx);
|
|
},
|
|
compact: function(array){
|
|
if (!array) {
|
|
return array;
|
|
}
|
|
|
|
let result = [];
|
|
|
|
for (let i = 0; i < array.length; ++i) {
|
|
if (!array[i]) {
|
|
continue;
|
|
}
|
|
|
|
result.push(array[i]);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
|
|
export default func_methods;
|
|
|