excel - 我在 excel 中有 3 个时间段 - 我需要知道最长连续时间段的持续时间

标签 excel date time continuous

请帮忙!

理想情况下,我真的很想只使用公式来解决这个问题——而不是 VBA 或我认为“花哨”的任何东西。

我为一个奖励持续参与的项目工作。我们有三个(有时更多)参与时间段,它们可以重叠和/或可以有不参与的空间。神奇的数字是 84 天的持续参与。我们一直在手动审查每一行(数百行),以查看时间段加起来是否连续参与了 84 天,没有不活动的时间。

在链接中有一张图片,其中包含我们使用的内容的摘要。例如第 3 行,3 个时间段中的任何一个都没有 84 天,但前 2 个时间段加起来包括连续 120 天。日期不会按日期顺序出现 - 例如早期参与可能会在第 3 期中列出。

enter image description here

非常期待您的建议。

安妮

最佳答案

@TomSharpe 向您展示了一种使用公式解决此问题的方法。如果您有三个以上的时间段,则必须修改它。

不确定您是否会认为 Power Query 解决方案“太花哨”,但它确实允许无限数量的时间段,如示例中所示。

有了 PQ,我们

  • 为每对开始/结束构造所有连续日期的列表
  • 合并每一行的列表,删除重复项
  • 对每一行的结果日期列表应用间隔和岛技术
  • 计算每个“岛”的条目数并返回最大值

请注意:我计算了开始日期和结束日期。在你的日子栏中,你没有(除了一个例子)。如果你想同时计算两者,请保持代码不变;如果您不这样做,我们可以进行小幅修改

使用 Power Query

  • 创建一个排除第一行合并单元格的表格
  • 按照我在屏幕截图中显示的格式重命名表格列,因为表格中的每个列标题必须具有不同的名称。
  • 选择该数据表中的一些单元格
  • Data => Get&Transform => from Table/Range
  • 当 PQ 编辑器打开时:Home => Advanced Editor
  • 记下第 2 行中的表名称
  • 粘贴下面的 M 代码代替您看到的内容
  • 将第 2 行中的表名称更改回最初生成的名称。
  • 阅读评论并探索应用步骤以更好地理解算法

M代码
代码已编辑为对日期列表进行排序以处理某些情况

let
    Source = Excel.CurrentWorkbook(){[Name="Table2"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Start P1", type datetime}, {"Comment1", type text}, {"End P1", type datetime}, {"Days 1", Int64.Type}, {"Start P2", type datetime}, {"Comment2", type text}, {"End P2", type datetime}, {"Days 2", Int64.Type}, {"Start P3", type datetime}, {"Comment3", type text}, {"End P3", type datetime}, {"Days 3", Int64.Type}}),

//set data types for columns 1/5/9... and 3/7/11/... as date
dtTypes = List.Transform(List.Alternate(Table.ColumnNames(#"Changed Type"),1,1,1), each {_,Date.Type}),
typed = Table.TransformColumnTypes(#"Changed Type",dtTypes),

//add Index column to define row numbers
rowNums = Table.AddIndexColumn(typed,"rowNum",0,1),

//Unpivot except for rowNum column
    #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(rowNums, {"rowNum"}, "Attribute", "Value"),

//split the attribute column to filter on Start/End => just the dates
//then filter and remove the attributes columns
    #"Split Column by Delimiter" = Table.SplitColumn(#"Unpivoted Other Columns", "Attribute", Splitter.SplitTextByEachDelimiter({" "}, QuoteStyle.Csv, false), {"Attribute.1", "Attribute.2"}),
    #"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Attribute.1", type text}, {"Attribute.2", type text}}),
    #"Removed Columns" = Table.RemoveColumns(#"Changed Type1",{"Attribute.2"}),
    #"Filtered Rows" = Table.SelectRows(#"Removed Columns", each ([Attribute.1] = "End" or [Attribute.1] = "Start")),
    #"Removed Columns1" = Table.RemoveColumns(#"Filtered Rows",{"Attribute.1"}),
    #"Changed Type2" = Table.TransformColumnTypes(#"Removed Columns1",{{"Value", type date}, {"rowNum", Int64.Type}}),

//group by row number
//generate date list from each pair of dates
//combine into a single list of dates with no overlapped date ranges for each row
    #"Grouped Rows" = Table.Group(#"Changed Type2", {"rowNum"}, {
        {"dateList", (t)=> List.Sort(
            List.Distinct(
                List.Combine(
                    List.Generate(
                        ()=>[dtList=List.Dates(
                                t[Value]{0},
                                Duration.TotalDays(t[Value]{1}-t[Value]{0})+1 ,
                                #duration(1,0,0,0)),idx=0],
                        each [idx] < Table.RowCount(t),
                        each [dtList=List.Dates(
                                    t[Value]{[idx]+2},
                                    Duration.TotalDays(t[Value]{[idx]+3}-t[Value]{[idx]+2})+1,
                                    #duration(1,0,0,0)),
                                idx=[idx]+2],
                        each [dtList]))))}
            }),

//determine Islands and Gaps
    #"Expanded dateList" = Table.ExpandListColumn(#"Grouped Rows", "dateList"),

//Duplicate the date column and turn it into integers
    #"Duplicated Column" = Table.DuplicateColumn(#"Expanded dateList", "dateList", "dateList - Copy"),
    #"Changed Type3" = Table.TransformColumnTypes(#"Duplicated Column",{{"dateList - Copy", Int64.Type}}),

//add an Index column
//Then subtract the index from the integer date
// if the dates are consecutive the resultant ID column will => the same value, else it will jump
    #"Added Index" = Table.AddIndexColumn(#"Changed Type3", "Index", 0, 1, Int64.Type),
    #"Added Custom" = Table.AddColumn(#"Added Index", "ID", each [#"dateList - Copy"]-[Index]),
    #"Removed Columns2" = Table.RemoveColumns(#"Added Custom",{"dateList - Copy", "Index"}),

//Group by the date ID column and a Count will => the consecutive days
    #"Grouped Rows1" = Table.Group(#"Removed Columns2", {"rowNum", "ID"}, {{"Count", each Table.RowCount(_), Int64.Type}}),
    #"Removed Columns3" = Table.RemoveColumns(#"Grouped Rows1",{"ID"}),

//Group by the Row number and return the Maximum Consecutive days
    #"Grouped Rows2" = Table.Group(#"Removed Columns3", {"rowNum"}, {{"Max Consecutive Days", each List.Max([Count]), type number}}),

//combine the Consecutive Days column with original table
    result = Table.Join(rowNums,"rowNum",#"Grouped Rows2","rowNum"),
    #"Removed Columns4" = Table.RemoveColumns(result,{"rowNum"})
in
    #"Removed Columns4"

enter image description here

关于excel - 我在 excel 中有 3 个时间段 - 我需要知道最长连续时间段的持续时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68525046/

相关文章:

Excel VBA 文件名更改

time - Google Colab 中的不同时区

excel - 以编程方式创建用户表单期间更改字体和字体大小

perl - 打印数组后不需要的空格。我正在使用 perl

java - 如果今天是星期日,则获取下周的日期

javascript - 获取随机日期为 "yyyy-mm-dd"格式的 Javascript

javascript - 用三个时间值计算时间差

cakephp - 如何在 Cakephp 中根据国家时区显示时间

vba - 下标超出范围 - 运行时错误 9

python - 如何判断一个日期是否在另外两个日期之间?