Google apps script 在另一列的循环中查找与条件匹配的日期?

Google apps script 在另一列的循环中查找与条件匹配的日期?,google-apps-script,google-sheets,Google Apps Script,Google Sheets,我有一个包含多个列的google工作表,其中一列是date(它是F列,从最早到最晚排序),另一列(G)是time duration值。我提出了一个条件,每当三个持续时间的组合被采用时,如果它大于10小时,则采用相应的组合,并将组合中最早的日期作为另一个程序的参考。这个组合应该是最新的(我指的是日期)。我试过的代码是 function calculation(){ var source = SpreadsheetApp.getActiveSpreadsheet(); var sheet =

我有一个包含多个列的google工作表,其中一列是date(它是F列,从最早到最晚排序),另一列(G)是time duration值。我提出了一个条件,每当三个持续时间的组合被采用时,如果它大于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日。 工作表如下所示

所得结果是令人满意的

使用持续时间: 在应用程序脚本中使用工作表持续时间有点混乱:请参阅

通过应用程序脚本检索时,持续时间将变成JavaScript,基于Google表单中日期/时间的零标记(
12/30/1899 0:00:00
)(请参阅)

在JS中,为了比较日期,您可以使用,它返回自1970年1月1日以来的毫秒数,它指的是
1
。因此,从工作表持续时间检索的日期将导致毫秒数为负数。为了避免出现问题,您可以在每次比较日期时使用参考日期。一个选项是将sheets单元格设置为
00:00
duration,并将该值用作参考。这就是我在下面的示例中所做的,在cell
N3

工作流程:
  • N3
    设置为参考持续时间(
    00:00
    ),将
    N2
    设置为
    10:00
  • 使用一个数组(
    comboData
    )来存储可能的持续时间组合,循环遍历
    G2:G
    中的所有持续时间。对于每个元素,(1)检查
    comboData
    是否少于3个元素,如果是,则添加当前元素,(2)否则,在
    comboData
    中找到最小值,检查当前元素是否更高,如果是,则替换,(3)计算当前组合的总持续时间,如果高于
    10:00
    ,则断开循环
  • 将持续时间从毫秒转换为所需的持续时间格式(使用下面的函数
    msToHMS(ms)
    ,基于by),并将其写入工作表,总持续时间使用
    setValue()
    ,三个持续时间和日期使用
    setValues()
代码示例: 函数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[1].getTime()-reference,row[0]]); var limit=sheet.getRange('N2').setValue(“10:00”).setNumberFormat(“[hh]:mm”).getValue().getTime()-reference; var comboData=[];//存储组合的数组 var totalDuration=0; 对于(var i=0;ival[0]);//在当前组合中查找最小值 var index=comboData.findIndex(val=>val[0]==minimum);//在当前组合中查找最小值的索引 if(行[0]>最小值)comboData[index]=row;//如果当前元素更高,则替换最小值 } totalDuration=comboData.reduce((acc,combo)=>acc+combo[0]),0);//总持续时间(毫秒) 如果(totalDuration>limit&&comboData.length==3)中断;//如果总持续时间大于10小时,则中断循环 } sheet.getRange(“K2:L4”).setValues(comboData.map(combo=>[msToHMS(combo[0]),combo[1]);//将combo数据写入K2:L4 var formattedDuration=msToHMS(totalDuration);//总持续时间(格式化为hh:mm:ss) sheet.getRange(“J2”).setValue(formattedDuration);//将总持续时间写入J2 } 功能msToHMS(ms){ var秒=毫秒/1000; var hours=parseInt(秒/3600);//1小时内3600秒 秒=秒%3600;//提取小时后剩余的秒数 var minutes=parseInt(秒/60);//1分钟内60秒 秒=秒%60; 返回Utilities.formatString(“%02d”,小时)+:”+Utilities.formatString(“%02d”,分钟)+:“+Utilities.formatString(“%02d”,秒); }

笔记:
  • 此示例只需要
    F
    G
    N
    列中的数据。不需要
    H
    I
    J
    K
    M

所需的输出是什么?是否要检索持续时间大于10小时的前三个单元格组合的最早日期和总持续时间?您想将这些数据写入何处?@lamblichus我需要10小时或以上的最新组合以及最早的日期。在上面的示例中,组合为3 30、3、4小时,日期为30/7/2020我知道您需要10小时或以上的最新组合。我想问你到底需要什么数据。三个单元格的持续时间分别是多少,最早的日期是多少?或者可能是总持续时间(三个单元格的总和?)。你想用这些数据做什么?将其写入其他单元格?或者您只是问如何检索此数据,而无需将其写入电子表格?@lamblichus确切地说,我需要这三个单元格在三个位置的持续时间,以及在另一个位置的持续时间和各自的日期。所有这些结果应在同一张表中。我有将近120张类似的表格,我正在将所有这些结果用于另一个程序。@lamblich
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);
}