licp
2024-12-25 996e3e343760bcfa23b55138f85abd62d6ebfb22
src/util/excelFountion.js
@@ -1,47 +1,157 @@
/**
 * 计算多个数值的和
 *
 * @param val 数值型参数,可变长参数列表
 * @returns 返回所有参数的和,如果参数列表为空或参数类型非数值型,则返回null
 */
function SUM(...val){
  let num = 0;
  if(val&&val.length>0){
    val.forEach(item=>{
      num+=item;
    })
  try {
    let num = null;
    if(val&&val.length>0){
      val.forEach(item=>{
        num+=item;
      })
    }
    return num;
  } catch (error) {
  }
  return num;
}
/**
 * 计算传入参数中的最大值
 *
 * @param ...val 可变参数列表,用于计算最大值的数值或可转换为数值的类型
 * @returns 返回最大值,如果参数列表为空或为null/undefined/'',则返回null
 */
function MAX(...val){
  let max = 0;
  if(val&&val.length>0){
    val = val.filter(item=>item!=null&&item!=='')
    max = Math.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) {
  }
  return max;
}
/**
 * 计算传入参数中的最小值
 *
 * @param val 可变参数,用于计算最小值的数值数组
 * @returns 返回传入参数中的最小值,如果传入参数为空或所有值均为null或空字符串,则返回null
 */
function MIN(...val){
  let min = 0;
  if(val&&val.length>0){
    val = val.filter(item=>item!=null&&item!=='')
    min = Math.min(...val)
  }
  return min;
}
  try {
    let min = null;
    if(val&&val.length>0){
      val = val.filter(item=>item!=null&&item!=='')
      // console.log(val)
      if(val.length>0){
        min = Math.min(...val)
      }
    }
    return min;
  } catch (error) {
  }
}
/**
 * 计算给定数值的平均值
 *
 * @param val 数值列表,可包含任意个参数
 * @returns 返回平均值,如果数值列表为空或包含非数值项,则返回null
 */
function AVERAGE(...val){
  let num = 0;
  let arr = [];
  if(val&&val.length>0){
    arr = val.filter(item=>item!=null&&item!=='')
    arr.forEach(item=>{
      num+=item;
    })
    return num/arr.length;
  }else{
    return 0;
  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) {
  }
}
function APS(val){
  return Math.abs(val);
/**
 * 计算幂
 *
 * @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) {
  }
}
@@ -51,19 +161,23 @@
 * @param {Object} cellId
 */
function getColumnNameFromId(cellId){
   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);
  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)
  }
}
/**
 * 根据列名获取坐标
@@ -71,143 +185,187 @@
 * @param {Object} arr
 */
function getIdFromColumnName(id, arr) {
   // 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;
}
// 获取参数列表
function changeParameter(f){
  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;
}
function getABCList(f){
  let regex = /[=\+\-\*\%\(\)\/\^\s]/g;
  let fouList = [
    "SUM",
    'MAX',
    'MIN',
    'AVERAGE',
    'APS',
  ]
  f = f.replace(regex, ',')
  fouList.forEach(item=>{
    f = f.replaceAll(item,',')
  })
  let arr = f.split(',').filter(item=>{
    return item&& /[a-zA-Z]/.test(item)&&item!='undefined'&&item!='null'
  });
  return arr;
}
function getAllCell(f){
  let arr = changeParameter(f)
  let arr0 = {}
  arr.forEach(item=>{
    arr0[getColumnNameFromId(`${item.c}`+'-'+`${item.r}`)] = null
  })
  return arr0;
}
// 计算公式
function compute(f,comValue){
  let str = f
  // 获取单元格对应值
  let arr = getAllCell(f)
  for (var a in comValue) {
    if(comValue[a]!=='undefine'&&comValue[a]!=='null'&&comValue[a]!==undefined){
      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.replaceAll(':', '-')
  // 替换参数
  for (var a in obj) {
    str = str.replaceAll(a, obj[a])
  }
  // 计算
  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'),'')
    })
    // console.log('f',f)
    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.replaceAll(a, arr[a])
      str = str.replace(new RegExp(a, 'g'),arr[a])
    }
    return eval(str)
  }catch(e){
    console.log('e',e)
    return 0
  } catch (error) {
  }
}