/**
|
* 计算多个数值的和
|
*
|
* @param val 数值型参数,可变长参数列表
|
* @returns 返回所有参数的和,如果参数列表为空或参数类型非数值型,则返回null
|
*/
|
function SUM(...val) {
|
try {
|
let num = null;
|
if (val && val.length > 0) {
|
val.forEach((item) => {
|
num += item;
|
});
|
}
|
return num;
|
} catch (error) {}
|
}
|
/**
|
* 计算传入参数中的最大值
|
*
|
* @param ...val 可变参数列表,用于计算最大值的数值或可转换为数值的类型
|
* @returns 返回最大值,如果参数列表为空或为null/undefined/'',则返回null
|
*/
|
function MAX(...val) {
|
try {
|
let max = null;
|
if (val && val.length > 0) {
|
val = val.filter((item) => item != null && item !== "");
|
if (val.length > 0) {
|
max = Math.max(...val);
|
} else {
|
max = null;
|
}
|
}
|
return max;
|
} catch (error) {}
|
}
|
/**
|
* 计算传入参数中的最小值
|
*
|
* @param val 可变参数,用于计算最小值的数值数组
|
* @returns 返回传入参数中的最小值,如果传入参数为空或所有值均为null或空字符串,则返回null
|
*/
|
function MIN(...val) {
|
try {
|
let min = null;
|
if (val && val.length > 0) {
|
val = val.filter((item) => item != null && item !== "");
|
if (val.length > 0) {
|
min = Math.min(...val);
|
}
|
}
|
return min;
|
} catch (error) {}
|
}
|
/**
|
* 计算给定数值的平均值
|
*
|
* @param val 数值列表,可包含任意个参数
|
* @returns 返回平均值,如果数值列表为空或包含非数值项,则返回null
|
*/
|
function AVERAGE(...val) {
|
try {
|
let num = null;
|
let arr = [];
|
if (val && val.length > 0) {
|
arr = val.filter((item) => item != null && item !== "");
|
arr.forEach((item) => {
|
num += item;
|
});
|
if (arr.length > 0) {
|
return num / arr.length;
|
} else {
|
return null;
|
}
|
} else {
|
return null;
|
}
|
} catch (error) {}
|
}
|
/**
|
* 计算一个数的绝对值
|
*
|
* @param val 任意数值
|
* @returns 返回该数值的绝对值
|
*/
|
function ABS(val) {
|
try {
|
return Math.abs(val);
|
} catch (error) {}
|
}
|
/**
|
* 计算一组数字的中位数
|
*
|
* @param val 任意个参数,需要计算中位数的数字
|
* @returns 如果参数中有有效的数字,则返回计算出的中位数;否则返回null
|
*/
|
function MEDIAN(...val) {
|
try {
|
let arr = [];
|
if (val && val.length > 0) {
|
arr = val.filter((item) => item != null && item !== "");
|
const sortedArr = arr.sort((a, b) => a - b);
|
// 计算中位数
|
const half = Math.floor(sortedArr.length / 2);
|
if (arr.length > 0) {
|
// 如果数组长度是奇数,直接取中间的元素
|
if (sortedArr.length % 2 === 1) {
|
return sortedArr[half];
|
} else {
|
// 如果数组长度是偶数,取中间两个元素的平均值
|
return (sortedArr[half - 1] + sortedArr[half]) / 2;
|
}
|
} else {
|
return null;
|
}
|
} else {
|
return null;
|
}
|
} catch (error) {}
|
}
|
|
/**
|
* 计算幂
|
*
|
* @param str 字符串形式的幂表达式,例如"2^3"
|
* @returns 返回计算后的幂值,如果表达式无效则返回null
|
*/
|
function CalculatePower(str) {
|
try {
|
if (str && str.includes("^")) {
|
let arr = str.split("^");
|
if (arr && arr.length > 1) {
|
return Math.pow(arr[0], arr[1]);
|
} else {
|
return null;
|
}
|
}
|
} catch (error) {}
|
}
|
|
/**
|
* 根据坐标获取列名
|
* @param {Object} cellId
|
*/
|
function getColumnNameFromId(cellId) {
|
try {
|
if (!Array.isArray(cellId)) {
|
cellId = cellId.split("-");
|
}
|
var i = cellId[0];
|
var letter = "";
|
if (i > 701) {
|
letter += String.fromCharCode(64 + parseInt(i / 676));
|
letter += String.fromCharCode(64 + parseInt((i % 676) / 26));
|
} else if (i > 25) {
|
letter += String.fromCharCode(64 + parseInt(i / 26));
|
}
|
letter += String.fromCharCode(65 + (i % 26));
|
return letter + (parseInt(cellId[1]) + 1);
|
} catch (e) {
|
console.log("error", cellId);
|
}
|
}
|
/**
|
* 根据列名获取坐标
|
* @param {Object} id
|
* @param {Object} arr
|
*/
|
function getIdFromColumnName(id, arr) {
|
try {
|
// Get the letters
|
var t = /^[a-zA-Z]+/.exec(id);
|
if (t) {
|
// Base 26 calculation
|
var code = 0;
|
for (var i = 0; i < t[0].length; i++) {
|
code +=
|
parseInt(t[0].charCodeAt(i) - 64) * Math.pow(26, t[0].length - 1 - i);
|
}
|
code--;
|
// Make sure jexcel starts on zero
|
if (code < 0) {
|
code = 0;
|
}
|
|
// Number
|
var number = parseInt(/[0-9]+$/.exec(id));
|
if (number > 0) {
|
number--;
|
}
|
|
if (arr == true) {
|
id = [code, number];
|
} else {
|
// id = code + '-' + number;
|
id = {
|
c: code,
|
r: number,
|
};
|
}
|
}
|
return id;
|
} catch (e) {
|
console.log("error", id);
|
}
|
}
|
|
/**
|
* 更改参数
|
*
|
* @param f 参数列表
|
* @returns 返回一个包含坐标信息的数组
|
*/
|
function changeParameter(f) {
|
try {
|
let arr = getABCList(f);
|
let arr2 = [];
|
arr.forEach((item) => {
|
if (item.includes(":")) {
|
let r0 = getIdFromColumnName(item.split(":")[0]).r;
|
let c0 = getIdFromColumnName(item.split(":")[0]).c;
|
let r1 = getIdFromColumnName(item.split(":")[1]).r;
|
let c1 = getIdFromColumnName(item.split(":")[1]).c;
|
for (let i = Number(r0); i <= Number(r1); i++) {
|
for (let u = Number(c0); u <= Number(c1); u++) {
|
arr2.push({
|
r: i,
|
c: u,
|
});
|
}
|
}
|
} else {
|
arr2.push(getIdFromColumnName(item));
|
}
|
});
|
return arr2;
|
} catch (error) {}
|
}
|
/**
|
* 获取包含 ABC 字符的列表
|
*
|
* @param f 字符串,包含需要解析的公式或表达式
|
* @returns 包含 ABC 字符的数组列表
|
*/
|
function getABCList(f) {
|
try {
|
let regex = /[=\+\-\*\%\(\)\/\^\s]/g;
|
let fouList = ["SUM", "MAX", "MIN", "AVERAGE", "ABS"];
|
f = f
|
.replace(regex, ",")
|
.replace(new RegExp('"&', "g"), "")
|
.replace(new RegExp('&"', "g"), "");
|
fouList.forEach((item) => {
|
f = f.replace(new RegExp(item, "g"), "");
|
});
|
let arr = f.split(",").filter((item) => {
|
return (
|
item && /[a-zA-Z]/.test(item) && item != "undefined" && item != "null"
|
);
|
});
|
return arr;
|
} catch (error) {}
|
}
|
/**
|
* 获取所有单元格
|
*
|
* @param f 表格数据或相关参数
|
* @returns 返回一个对象,其键为单元格的唯一标识符(由列和行ID拼接而成),值为null
|
*/
|
function getAllCell(f) {
|
try {
|
let arr = changeParameter(f);
|
let arr0 = {};
|
arr.forEach((item) => {
|
arr0[getColumnNameFromId(`${item.c}` + "-" + `${item.r}`)] = null;
|
});
|
return arr0;
|
} catch (error) {}
|
}
|
|
/**
|
* 计算函数
|
*
|
* @param f 字符串类型,表示待计算的公式
|
* @param comValue 对象类型,表示要替换的单元格值,键为单元格名称,值为替换后的值
|
* @returns 返回计算后的结果,如果计算失败则返回0
|
*/
|
function compute(f, comValue) {
|
try {
|
let str = f;
|
// 获取单元格对应值
|
let arr = getAllCell(f);
|
for (var a in comValue) {
|
if (
|
comValue[a] !== "undefined" &&
|
comValue[a] !== "null" &&
|
comValue[a] !== undefined
|
) {
|
if (typeof comValue[a] == "string" && comValue[a].includes("^")) {
|
// 计算幂次
|
arr[a] = CalculatePower(comValue[a]);
|
} else if (
|
typeof comValue[a] == "string" &&
|
comValue[a].includes("/")
|
) {
|
arr[a] = comValue[a];
|
} else {
|
arr[a] = comValue[a];
|
}
|
}
|
}
|
// 解析公式参数,特别是带:的
|
let arr0 = getABCList(f);
|
let obj = {};
|
arr0.forEach((item) => {
|
if (item.includes(":")) {
|
let arr1 = [];
|
let r0 = getIdFromColumnName(item.split(":")[0]).r;
|
let c0 = getIdFromColumnName(item.split(":")[0]).c;
|
let r1 = getIdFromColumnName(item.split(":")[1]).r;
|
let c1 = getIdFromColumnName(item.split(":")[1]).c;
|
for (let i = Number(r0); i <= Number(r1); i++) {
|
for (let u = Number(c0); u <= Number(c1); u++) {
|
arr1.push({
|
r: i,
|
c: u,
|
});
|
}
|
}
|
let arr2 = [];
|
arr1.forEach((m) => {
|
arr2.push(getColumnNameFromId(`${m.c}` + "-" + `${m.r}`));
|
});
|
obj[item.split(":").join("-")] = arr2.join(",");
|
} else {
|
obj[item] = item;
|
}
|
});
|
str = str.replace(new RegExp(":", "g"), "");
|
// 替换参数
|
for (var a in obj) {
|
str = str.replace(new RegExp(a, "g"), obj[a]);
|
}
|
// 计算
|
for (var a in arr) {
|
str = str.replace(new RegExp(a, "g"), arr[a]);
|
}
|
return eval(str);
|
} catch (error) {}
|
}
|
|
export default {
|
compute,
|
changeParameter,
|
};
|