【问题标题】:How can I calculate the total duration without overlapping periods in Google Sheet?如何在 Google 表格中计算不重叠期间的总持续时间?
【发布时间】:2021-06-23 05:56:26
【问题描述】:

我在这里创建了一个sample sheet,它有重叠的时间段。我想计算没有重叠的总持续时间。我见过公式,但它不适用于较大的数据集或仅适用于 Excel。

我在Stack Overflow 中也找到了一个示例公式,但它不适用于更大的数据集或更长的持续时间。

=SUMPRODUCT((COUNTIFS(D2:D23,""&MIN(D2:D23)+ ROW(INDIRECT("1:"&ROUND((MAX(E2:E23)-MIN(D2:D23))*1440,0)))/1440-1/2880,C2:C23,I2,B2:B23,I1 )>0)+0)/60

【问题讨论】:

  • 您的数据没有显示重叠时间?
  • 我已经更新了数据

标签: google-sheets array-formulas overlap duration


【解决方案1】:

首先,要计算时差,假设您是手动计算,您可以使用以下公式:

=(hour(D2)+ MINUTE(D2)/60)- (hour(C2)+ MINUTE(C2)/60)

要查找overlapping time,您可以使用if 函数:

=IF(and(D4<E3,B4=B3),((HOUR(E3)+MINUTE(E3)/60) - (HOUR(D4)+MINUTE(D4)/60)) ,0)

在您的示例中,不重叠的总时间应该是 5.5 hrs,减去 total time w overlapping minus total overlapping time。我说的对吗?

=SUM(E:E)-SUM(F:F)

【讨论】:

  • 有时开始和结束时间与超过 3 个活动重叠。此外,我添加了条件/过滤器,例如日期和名称。所以我认为这行不通。但是谢谢你!
  • 它总是可以计算的,虽然我不确定你的三个活动是否重叠,如果都涉及name and date,你可以在if statement上再加一个条件就可以了
【解决方案2】:

这样的脚本将使用“gap and island”原则为任务提供净时间(不幸的是,所有引用似乎都与 SQL 有关)。另见VBA version of this,以下内容改编自:

function myFunction(prange) {

    var p = sheet.getRange(prange);

    var array = p.getValues();

    // Sort on start time

    array.sort(function(a, b) {
        return a[0] - b[0];
    })

    // Initialise

    minStart = array[0][0];
    maxEnd = array[0][0];
    gap = 0

    // Loop over rows

    for (i = 0; i<array.length;i++)
    {
        // If there is a gap, increment total gap length

        if (array[i][0] > maxEnd )
            gap = gap + array[i][0].valueOf() - maxEnd;

        // Update latest end time

        if (array[i][1] > maxEnd)
            maxEnd = array[i][1];
    }

    TimeOnTask = (maxEnd - minStart - gap)/(60*60*1000);

    return TimeOnTask;
}

这是整个脚本,它能够传递一个数组(因此可以使用过滤器)并检查添加的非日期:

function myFunction(param) {
    var sheet = SpreadsheetApp.getActiveSpreadsheet();

    var r,array;
    if(typeof param =="string")
    {
      r = sheet.getRange(param);
      array = r.getValues();
    }
    else
      array=param;

    //Check for non-dates

    filteredArray = array.filter(function(value) {
      return Object.prototype.toString.call(value[0]) == "[object Date]" && Object.prototype.toString.call(value[1]) == "[object Date]";
    });

    // Sort the array

    filteredArray.sort(function(a, b) {
      return a[0] - b[0];
    })

    // Initialise

    minStart = filteredArray[0][0];
    maxEnd = filteredArray[0][0];
    gap = 0
    
    // Loop over rows

    for (i = 0; i<filteredArray.length;i++)
    {

      // If there is a gap, increment total gap length
    
      if (filteredArray[i][0] > maxEnd )
        gap = gap + filteredArray[i][0].valueOf() - maxEnd;

      // Update latest end time
        
      if (filteredArray[i][1] > maxEnd)
        maxEnd = filteredArray[i][1];
            
    }
    
    
    TimeOnTask = (maxEnd - minStart - gap)/(60*60*1000);


    return TimeOnTask;
}

所以你可以像这样将过滤后的数据传递给它:

=myfunction(filter(D2:E,B2:B=J1,C2:C=J2))

给这个:

【讨论】:

  • 我用员工姓名和日期等多个标准修改了数据集。我怎样才能在这个脚本中实现它?谢谢
  • 也许过滤脚本中的日期,或者可能比在将日期传递给脚本之前有很多版本的脚本来过滤日期更容易。会看看的。
  • 感谢@Peter Mortensen 的编辑-感谢缩进不是很好。我对程序进行了更新以添加一些基本检查,但会尝试保持您的布局更改。这对我很有帮助,因为虽然我有 Java 背景,但我仍然在寻找解决 Google 脚本的方法。
【解决方案3】:

我的解决方案在这里:Link

我在过滤数据的地方添加了隐藏列 K-M,以便仅列出所选名称,然后按开始日期时间对数据进行排序(降序)。

这使我可以检查每一行是否与其上方的行重叠(如果当前行在其上方的行开始之后结束,则存在重叠)。

  • Column N 计算重叠时间,因为您似乎也想要该信息。

  • Column O 通过计算有重叠的时间来计算无重叠的时间,如果上一行在下一行结束之前开始(存在重叠),则减去上一行的开始时间和较小的那一行之间的时间任一行的结束时间。

I3 & I4 然后通过仅对从所选日期开始的行求和来分别计算 Time w/ Overlap 和 Time w/o Overlap。

此外,我添加了名称的下拉选择,由隐藏的Column P 提供,它只是自动生成Column B 中唯一名称的列表。

我希望这会有所帮助。如果您需要任何其他帮助,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多