如何在 Google Sheet 中计算总持续时间而不重叠期间?

问题描述 投票:0回答:4

我在这里创建了一个具有重叠时间段的样本表。我想计算没有重叠的总持续时间。我见过公式,但它不适用于较大的数据集或仅适用于 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, E2:E23,">"&MIN(D2:D23)+ 行(间接(“1:”&ROUND((MAX(E2:E23)-MIN(D2:D23))*1440,0)))/1440-1/2880,C2:C23,I2,B2:B23,I1 )>0)+0)/60

Enter image description here

google-sheets array-formulas overlap duration
4个回答
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)

Enter image description here


0
投票

像这样的脚本将使用“间隙和岛”原则给出任务的净时间(不幸的是所有参考文献似乎都与 SQL 相关)。另请参阅 VBA 版本,以下内容改编自:

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;
}

Enter image description here

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

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))

给出这个:

Enter image description here


0
投票

我的解决方案可以在这里找到:链接

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

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

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

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

I3
I4
然后通过仅对从选定日期开始的行进行求和来计算“有重叠的时间”和“无重叠的时间”(分别)。

此外,我还添加了一个名称下拉选择,由隐藏的

Column P
提供,它会自动生成
Column B
中唯一名称的列表。

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


0
投票

以下内容对我有用。允许根据某些指定的条件过滤列。我在 F1、G1、H1 和 I1 上使用了标准。可以根据需要更改。

=SUM(LET(startEndTimes, 过滤器(D$2:$E$22, (($B$2:$B$22=$F1) + ($B$2:$B$22=$G1) + ($B$2:$ B$22=$H1)) * (IFERROR(MONTH($C$2:$C$22)=MONTH(I$1),0))), 序列, MIN($D$2:$D$22) + SEQUENCE(ROUNDUP( (最大值($E$2:$E$22) - 最小值($D$2:$D$22)) * 24 * 60, 0), 1, 1)/1440, IFERROR(MAP(序列, LAMBDA(x, IF( OR(MMULT(IFERROR((x >= INDEX(startEndTimes, , 1)) * (x <= INDEX(startEndTimes, , 2)), 0), 1) > 0), 1, 0))), REPT(0, ROWS(序列)))))/60

© www.soinside.com 2019 - 2024. All rights reserved.