【问题标题】:Javascript Cleanup in Google SheetsGoogle 表格中的 Javascript 清理
【发布时间】:2021-12-14 22:33:46
【问题描述】:

我的以下代码按预期方式工作(总共 3 个函数)。我正在寻求如何编写更好的代码的帮助。我认为必须有一种更有效或更清洁的方式来编写此代码。特别是我编写日期代码的方式,我很困惑它是如何工作的,只知道它是。请并感谢您为我提供的任何帮助!

考虑到业务的季节性,我们的想法是开发一种功能,该功能可以确定收入时间延迟的情况。该函数提取月份值(原始结束日期 - 新结束日期)。然后该函数将根据当前结束月份之后的月份开始对百分比进行求和,直到达到日期的差异。然后取这个百分比值来得到延迟时间的影响。

IE 原定于 2021 年 1 月开始,但不得不移动到 2021 年 5 月。这导致延迟了 4 个月。从 2 月开始,将接下来 4 个月的百分比相加。

谷歌表格:Google Sheets Example

function rateChange(monthNum) {//main program to calculate the percent of lost revenue, based on delay in timing

  var sh = SpreadsheetApp.getActiveSpreadsheet()
  var sheet = SpreadsheetApp.getActiveSheet().getActiveCell()
  var sheet2 = sh.getSheetByName("Rate Change")
  var curRow = sheet.getRow()
  var endDate = new Date(sheet2.getRange("F" + curRow).getValue());
  var endMth = endDate.getMonth();
var newEndDate = new Date(endDate.setMonth(endDate.getMonth()+1))

  var curMth = new Date(endDate.setMonth(newEndDate.getMonth()))

  var mth10Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth10 = mth10Dt.getMonth()+1;

  var mth9Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth9 = mth9Dt.getMonth()+1;

  var mth8Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth8 = mth8Dt.getMonth()+1;

  var mth7Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth7 = mth7Dt.getMonth()+1;

  var mth6Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth6 = mth6Dt.getMonth()+1;

  var mth5Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth5 = mth5Dt.getMonth()+1;

  var mth4Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth4 = mth4Dt.getMonth()+1;

  var mth3Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth3 = mth3Dt.getMonth()+1;

  var mth2Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth2 = mth2Dt.getMonth()+1;

  var mth1Dt = new Date(curMth.setMonth(curMth.getMonth()+1))

  var mth1 = mth1Dt.getMonth()+1;

  if(monthNum >= 12){//if number of months delay is >=12, forces 100% of cost

    var negVal = 1
    return negVal;

  }

  else if (monthNum == 11){//begin summation of annual percentages, given the number of months between original planned date and new planned date

   var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue()+sh.getRange(mthCol(mth7) + curRow).getValue()+sh.getRange(mthCol(mth6) + curRow).getValue() + sh.getRange(mthCol(mth5) + curRow).getValue()+sh.getRange(mthCol(mth4) + curRow).getValue()+sh.getRange(mthCol(mth3) + curRow).getValue() + sh.getRange(mthCol(mth2) + curRow).getValue() + sh.getRange(mthCol(mth1) + curRow).getValue();

   return negVal;

  }

  else if(monthNum == 10){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue()+sh.getRange(mthCol(mth7) + curRow).getValue()+sh.getRange(mthCol(mth6) + curRow).getValue() + sh.getRange(mthCol(mth5) + curRow).getValue()+sh.getRange(mthCol(mth4) + curRow).getValue()+sh.getRange(mthCol(mth3) + curRow).getValue() + sh.getRange(mthCol(mth2) + curRow).getValue();

   return negVal;

  }

    else if(monthNum == 9){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue()+sh.getRange(mthCol(mth7) + curRow).getValue()+sh.getRange(mthCol(mth6) + curRow).getValue() + sh.getRange(mthCol(mth5) + curRow).getValue()+sh.getRange(mthCol(mth4) + curRow).getValue()+sh.getRange(mthCol(mth3) + curRow).getValue();

   return negVal;

  }

    else if(monthNum == 8){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue()+sh.getRange(mthCol(mth7) + curRow).getValue()+sh.getRange(mthCol(mth6) + curRow).getValue() + sh.getRange(mthCol(mth5) + curRow).getValue()+sh.getRange(mthCol(mth4) + curRow).getValue();

   return negVal;

  }

    else if(monthNum == 7){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue()+sh.getRange(mthCol(mth7) + curRow).getValue()+sh.getRange(mthCol(mth6) + curRow).getValue() + sh.getRange(mthCol(mth5) + curRow).getValue();

   return negVal;

  }

    else if(monthNum == 6){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue()+sh.getRange(mthCol(mth7) + curRow).getValue()+sh.getRange(mthCol(mth6) + curRow).getValue();

   return negVal;

  }

    else if(monthNum == 5){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue()+sh.getRange(mthCol(mth7) + curRow).getValue();

   return negVal;

  }

      else if(monthNum == 4){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue() + sh.getRange(mthCol(mth8) + curRow).getValue();

   return negVal;

  }

      else if(monthNum == 3){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue() + sh.getRange(mthCol(mth9) + curRow).getValue();

   return negVal;

  }

  else if(monthNum == 2){

    var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue() + sh.getRange(mthCol(mth10) + curRow).getValue();

   return negVal;

  }

  else if(monthNum == 1){

     var negVal = sh.getRange(mthCol(endDate.getMonth()+1) + curRow).getValue();

   return negVal;

  }

}

function mthCol(curMth) {//Determines start month of calculation and returns letter of the column
  var sh = SpreadsheetApp.getActiveSpreadsheet()
  var sheet = sh.getSheetByName("Rate Change")
  for(var i = 11; i<23; i++){
    if(sheet.getRange(1, i).getValue() == curMth){
      var colMth = columnToLetter(i);
      return colMth;
    }
  }
}


function columnToLetter(column){//Gets column letter
  var temp, letter = '';
  while (column >0){
    temp = (column - 1) % 26;
    letter = String.fromCharCode(temp + 65) + letter;
    column = (column - temp -1) / 26;
  }
  return letter;
}

【问题讨论】:

  • 我必须为我糟糕的英语水平道歉。不幸的是,我无法理解你的问题。我可以问你问题的细节吗?顺便说一句,我无法打开您的示例电子表格。你能确认一下吗?
  • 我更新了链接。两种方式都对我有用。我正在寻找一种改进代码的方法,以便它运行得更快,流动性更好。
  • 请将该文件提供给公共@GTL。我也无法访问该文件。
  • 抱歉,此链接现在对任何知道该链接的人开放
  • 感谢您的回复。现在我注意到已经发布了答案。我想尊重现有的答案。

标签: javascript google-apps-script google-sheets


【解决方案1】:

这仍然可以进一步优化。我只是使用循环和数组来缩短重复的行,因为这是在不更改您应用的算法的情况下实现目标(即使脚本更简洁/更短)的最快方法。

脚本:

function rateChange(monthNum) { //main program to calculate the percent of lost revenue, based on delay in timing

  var sh = SpreadsheetApp.getActiveSpreadsheet()
  var sheet = SpreadsheetApp.getActiveSheet().getActiveCell()
  var sheet2 = sh.getSheetByName("Rate Change")
  var curRow = sheet.getRow()
  var endDate = new Date(sheet2.getRange("F" + curRow).getValue());
  var newEndDate = new Date(endDate.setMonth(endDate.getMonth() + 1))
  var curMth = new Date(endDate.setMonth(newEndDate.getMonth()))

  // array to store your values;
  var mth = [];

  for (i = 10; i > 0; i--) {
    // imitated the your variable naming to the indexing of the array
    mth[i] = new Date(curMth.setMonth(curMth.getMonth() + 1)).getMonth() + 1;
  }

  if (monthNum >= 12) //if number of months delay is >=12, forces 100% of cost
    return 1;

  else if (monthNum >= 1) {
    var negVal = sh.getRange(mthCol(endDate.getMonth() + 1) + curRow).getValue();
    for (i = monthNum - 1; i >= 1; i--) {
      // always start at 10, then go down as loop deepens
      negVal += sh.getRange(mthCol(mth[11 - i]) + curRow).getValue();
    }
    return negVal;
  }
}

这产生了与示例文件中相同的输出。

输出:

更新:

  • 这是一次计算所有行的更优化的方法,并且显着减少了方法调用。这也使得不需要其他功能。该解决方案只调用一次getValues,然后处理所有数据。根据需要随意修改/调整脚本。

脚本:

function rateChange() { 
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName("Rate Change");

  var startRow = 3;
  var endDateStartCol = 6;
  var numRows = sheet.getLastRow() - startRow + 1;
  var data = sheet.getRange(startRow, endDateStartCol, numRows, 17).getValues();

  return data.map(function (row) {
    var [endMth, newEndMth, monthNum] = row.slice(0, 3);
    endMth = new Date(endMth).getMonth();
    newEndMth = endMth + monthNum;

    if (monthNum >= 12)
      return [1];
    else if (monthNum >= 1) {
      var mth = row.slice(5);
      var negVal = 0;
      for (i = newEndMth; i > endMth; i--)
        negVal += mth[i % 12];
      return [negVal];
    }
  });
}

输出:

注意:

  • 对于后一种自定义函数,您只需将其放在数据的第一行即可。然后它将填充它下面的所有行。
  • 我在最后一行添加了一个示例数据,该数据会延续到下一年,以检查函数是否正确计算了总值(它确实正确计算了明年,模 (%) 很容易处理这种情况)

【讨论】:

  • 谢谢!我将花时间更好地了解您是如何为我自己的学习做到这一点的。他们都工作,但第二个版本绝对是一个更好的选择。
  • 我还有一个问题。如果我稍后在工作表中添加新的结束日期值,它不会更新结果。我怎样才能让这个功能实时工作?
  • 嗨@GTL,这是一个完全不同的原因。这是因为 Sheets 如何优化其功能。该问题已正确记录here。你能试试这个workaround,它使用一个复选框来手动触发上述功能吗?
猜你喜欢
  • 1970-01-01
  • 2019-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 2017-05-27
  • 1970-01-01
相关资源
最近更新 更多