【问题标题】:Finding the Date that matches the condition in a loop of another column?在另一列的循环中查找与条件匹配的日期?
【发布时间】:2020-09-30 10:00:49
【问题描述】:

我有一个包含多列的谷歌表,其中一列是日期(它是 F 列,从最旧到最新排序),另一列 (G) 是持续时间值。每当三个持续时间的组合超过 10 小时时,我就制定了一个条件,采用相应的组合并将组合中最早的日期作为对另一个程序的参考。这个组合应该是最新的(我的意思是日期)。我试过的代码是

function calculation(){
  var source = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = source.getSheetByName("10017135ASR");
  var lastRow = sheet.getLastRow();
  var time = sheet.getRange('G1:G'+lastRow).getValues();
  var cell = sheet.getRange('F1:F'+lastRow).getValues();
  var range1 = sheet.getRange('H1:H'+lastRow).setValues(time).setNumberFormat('[hh]:mm');
  var refer = sheet.getRange('N2').setValue("10:00").setNumberFormat("[hh]:mm");
  var refer1= refer.getValue();
  var range = range1.getValues();
  var time = sheet.getRange('H1:H');
  time.setNumberFormat('[hh]:mm'); 
  sheet.getRange('I2:I'+lastRow).setValue('0').setNumberFormat('[hh]:mm');
  var one= sheet.getRange('H'+(lastRow)).getValue();
  sheet.getRange('I'+lastRow).setValue(one).setNumberFormat('[hh]:mm');
  var two = sheet.getRange('H'+(lastRow-1)).getValue();
  sheet.getRange('I'+(lastRow-1)).setValue(two).setNumberFormat('[hh]:mm');
  loop1:
    for (var i = lastRow-3; i>0; i--){
     var value1 = range[i][0];
     var V2 = sheet.getRange('K'+lastRow).setValue(value1).setNumberFormat("[hh]:mm");
     var L2 = sheet.getRange('J'+lastRow).setFormula("=LARGE(I2:I,1)").setNumberFormat('[hh]:mm');
     var L3= sheet.getRange('J'+(lastRow-1)).setFormula("=LARGE(I2:I,2)").setNumberFormat('[hh]:mm');
     var sum = sheet.getRange('M2').setFormula("=SUM(J2:J)").setNumberFormat("[hh]:mm");
     var vB= sum.getValue();
     var V1 = V2.getValue(); 
     var sum2 = vB + V1;
       if((vB)>= refer1){
        sheet.getRange('L2').setValue(sum2).setNumberFormat('[hh]:mm');   
        var da=sheet.getRange('F'+(i+2)).getValue();
        sheet.getRange('N2').setValue(da).setNumberFormat('DD-mm-yyyy');
        break loop1;
        }   
       else {
         sheet.getRange('I'+(i+1)).setValue(value1).setNumberFormat('[hh]:mm');
       } 
     }
   }

这里我没有得到输出,循环在第一行结束,即使没有必要去第一行。因为所需的输出在第 30 行并且相应的日期是 2020 年 7 月 30 日。 工作表如下所示

得到的结果是

【问题讨论】:

  • 期望的输出是什么?您要检索持续时间大于 10 小时的 first 三单元组合的最早日期和总持续时间?你想把这些数据写到哪里?
  • @lamblichus 我需要 10 小时或更长时间的最新组合,并且在该组合中最旧的日期。在上面的示例中,组合是 3 30 ,3 ,4 小时,日期是 30/7/2020
  • 我了解您需要 10 小时或更长时间的最新组合。我的意思是问你需要什么数据。三个单元格的持续时间分别是最旧的日期?或者可能是总持续时间(三个单元格的总和?)。你想用这些数据做什么?将其写入其他单元格?
  • 或者您只是问如何检索这些数据,而无需将其写回电子表格?
  • @lamblichus 正是我需要这三个单元格分别在三个位置的持续时间以及在另一个位置和相应日期的总和。所有这些结果都在同一张纸上。我有近 120 张类似的工作表,我正在将所有这些结果用于另一个程序。

标签: google-apps-script google-sheets


【解决方案1】:

使用持续时间:

在 Apps 脚本中处理工作表持续时间有点混乱:请参阅 Working With Durations In Google Apps Script

当通过 Apps 脚本检索时,持续时间变为 JavaScript Date,基于 Google 表格中日期/时间的零标记 (12/30/1899 0:00:00)(请参阅 this answer)。

在JS中,为了比较日期,可以使用Date.getTime(),它返回自Unix Epoch以来的毫秒数,它指的是1 January 1970。因此,从工作表持续时间中检索到的日期将导致毫秒数为负数。为了避免这方面的问题,您可以在每次比较日期时使用参考日期。一种选择是将工作表单元格设置为00:00 持续时间并将该值用作参考。这就是我在下面的示例中所做的,在单元格 N3 中。

工作流程:

  • N3 设置为参考持续时间(00:00),将N2 设置为10:00
  • 循环遍历G2:G 中的所有持续时间,使用数组(comboData) 存储可能的持续时间组合。对于每个元素,(1)检查comboData是否少于3个元素,如果是则添加当前元素,(2)否则,在comboData中找到最小值,检查当前元素是否更高,如果是则替换就是这样,(3)计算当前组合的总持续时间,如果它高于10:00,则中断循环。
  • 将持续时间从毫秒转换为所需的持续时间格式(使用下面的函数msToHMS(ms),基于this answer by Serge insas),并将其写入工作表,使用setValue()作为总持续时间,以及setValues() 三个持续时间和日期。

代码示例:

function getCombinationRowIndex() {
  var source = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = source.getSheetByName("10017135ASR");
  var lastRow = sheet.getLastRow();  
  var reference = sheet.getRange('N3').setValue('00:00').setNumberFormat('[hh]:mm').getValue().getTime();
  var sourceData = sheet.getRange('F2:G' + lastRow).getValues().reverse().map(row => [row[1].getTime() - reference, row[0]]);
  var limit = sheet.getRange('N2').setValue("10:00").setNumberFormat("[hh]:mm").getValue().getTime() - reference;
  var comboData = []; // Array to store the combination
  var totalDuration = 0;
  for (var i = 0; i < sourceData.length; i++) {
    var row = sourceData[i];
    if (comboData.length < 3) comboData.push(row); // If combination has less than 3 elements, add current element
    else {
      var minimum = Math.min(...comboData.map(val => val[0])); // Find minimum in current combination
      var index = comboData.findIndex(val => val[0] == minimum); // Find index for minimum in current combination
      if (row[0] > minimum) comboData[index] = row; // Replace minimum if current element is higher
    }
    totalDuration = comboData.reduce(((acc, combo) => acc + combo[0]), 0); // Total duration in milliseconds
    if (totalDuration > limit && comboData.length === 3) break; // If total duration is higher than 10 hours, break loop
  }
  sheet.getRange("K2:L4").setValues(comboData.map(combo => [msToHMS(combo[0]), combo[1]])); // Write combo data to K2:L4
  var formattedDuration = msToHMS(totalDuration); // Total duration (formatted hh:mm:ss)
  sheet.getRange("J2").setValue(formattedDuration); // Write total duration to J2
}

function msToHMS(ms) {
  var seconds = ms / 1000;
  var hours = parseInt( seconds / 3600 ); // 3,600 seconds in 1 hour
  seconds = seconds % 3600; // seconds remaining after extracting hours
  var minutes = parseInt( seconds / 60 ); // 60 seconds in 1 minute
  seconds = seconds % 60;
  return Utilities.formatString("%02d",hours) + ':' + Utilities.formatString("%02d",minutes) + ':' + Utilities.formatString("%02d",seconds);
}

注意事项:

  • 此示例只需要FGN 列中的数据。不需要HIJKM等。

【讨论】:

  • @lamblichus 它说 val.getTime() 不是函数 {line 5}
  • @KumaraGuru 您在 G 列中的值是持续时间,对吗?我没有收到任何错误。您是否照原样复制了完整的代码?
  • @KumaraGuru 我建议您分享您正在处理的电子表格。
  • @lamblichus 我照原样复制了上面的代码但是运行的系统说 Typeerror val.getTime() is not a function
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-07
  • 2016-11-11
相关资源
最近更新 更多