如何使用数据提取月份并在 Excel Power Query 中找到第 n 个值作为起点和第 n 个值作为终点,也许 VBA

How to extract months with data and find n-th value as starting point and n-th value as ending point in Excel Power Query, maybe VBA

我有一个数据集,其中包含 Date/Time、压力和自定义列。这代表随时间推移的压力数据,我想知道我的起点(5 分钟后)和一个月内最后一个值(行)之前的终点。为了帮助您解决问题,通常测量大约需要 30-40 分钟,您可以在这个示例中看到。所以这意味着数据量可以变化。

时间列使用以下方法计算:

=([@[Date/Time]]-I5)*1440+L5

此数据集代表整个数据和所有带值的月份,我需要使用这些 starting/ending 点分隔(过滤)月份,如屏幕截图所示。我经常使用 Power Query 来处理数据,但也许还有另一种方法来获取这些值...并在可能的情况下为将来的数据使它们动态化。

我还将上传包含整个数据集(所有月份)的虚拟工作簿,如果您的信息和测试需要的话,用月份过滤 table。

https://docs.google.com/spreadsheets/d/1LGl-eri6ewCni2NJ2wGeoYIf-40KO2Lr/edit?usp=sharing&ouid=101738555398870704584&rtpof=true&sd=true

在 Power Query 中:

根据您共享的工作簿和您所写的内容,似乎在任何给定月份,您


编辑: 算法中的小改动

  • 在排除当月的第一个条目后开始计时。
    • 如果那是 typo/error,只需删除删除第一行的函数
  • 第二个条目 = 0 分钟,return 第一个条目在 分钟 5 之后,以及table.
  • 中最后一个条目的旁边
  • 请注意,我从 日期压力 列开始

算法

  • 增加一列monthYear
  • 分组monthYear
    • 自定义聚合到
      • 删除table
      • 的第一行和最后一行
      • 创建一个列表,列出每次与一个月中第一次相比的持续时间(以分钟为单位)。 这将是一分钟+一分钟的一小部分
      • 将该列表作为一列添加到原始 table
      • 确定第一个条目在第五分钟后
      • 确定最后一个条目
      • 过滤月份 subtable 到 return 这两个条目。

如果您只想查看给定月份的结果,可以在结果 Excel table.

中过滤结果

M码
请阅读评论并检查应用步骤以更好地理解算法

let
    Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Date/Time", type datetime}, {"P7 [mbar]", Int64.Type}}),

//add month/year column for grouping
    #"Added Custom" = Table.AddColumn(#"Changed Type", "month Year", 
        each Number.ToText(Date.Month([#"Date/Time"]),"00") & Number.ToText(Date.Year([#"Date/Time"]),"0000")),
    #"Grouped Rows" = Table.Group(#"Added Custom", {"month Year"}, {
        //elapsed minutes column
        {"Elapsed Minutes", (x)=> let

        //remove first and last rows from table  
            t=Table.RemoveColumns(Table.RemoveFirstN(Table.RemoveLastN(x)),"month Year"),

        //add a column with the elapsed minutes
            TableToFilter = Table.FromColumns(
                Table.ToColumns(t) 
                & {List.Generate(
                    ()=>[em=null, idx=0],
                    each [idx]< Table.RowCount(t),
                    each [em=Duration.TotalMinutes(t[#"Date/Time"]{[idx]+1} - t[#"Date/Time"]{0}), idx=[idx]+1],
                    each [em])}, type table[#"Date/Time"=datetime, #"P7 [mbar]"=number, elapsed=number]),

        //filter for last entry (which would be next to last in the month
            maxMinute = List.Max(TableToFilter[elapsed]),

        //filter for first entry in the 5th minute
            fifthMinute = List.Select(TableToFilter[elapsed], each Number.IntegerDivide(_,1)>=5){0},

        //select the 5th minute and the last row
            FilteredTable = Table.SelectRows(TableToFilter, each [elapsed]=fifthMinute or [elapsed]=maxMinute)
            in FilteredTable,type table[#"Date/Time"=datetime, #"P7 [mbar]"=number, elapsed=number]}
            }),

    //remove uneeded column and expand the others
    #"Removed Columns" = Table.RemoveColumns(#"Grouped Rows",{"month Year"}),
    #"Expanded Elapsed Minutes" = Table.ExpandTableColumn(#"Removed Columns", "Elapsed Minutes", {"Date/Time", "P7 [mbar]"}, {"Date/Time", "P7 [mbar]"})
in
    #"Expanded Elapsed Minutes"

来自您共享的工作簿数据的结果

中Office/Excel365

过滤列(例如 2020 年 1 月)

E4: 1/1/2020
E5: 1/1/2020

结果

F4 (date/time 5th minute): =IF(COUNTIFS(Table1[Date/Time],">="&E4,Table1[Date/Time],"<" & EDATE(E4,1))=0,"",
LET(x,FILTER(Table1[Date/Time],(Table1[Date/Time]>=E4)*(Table1[Date/Time]<EDATE(E4,1))),
          y, (x-INDEX(x,2))*1440,
          z, XMATCH(5,y,1),
          INDEX(x,z,1)))

G4: (Pressure 5th minute): =IF(F4="","",
LET(x,FILTER(Table1,(Table1[Date/Time]>=E4)*(Table1[Date/Time]<EDATE(E4,1))),
          y, (INDEX(x,0,1)-INDEX(x,2,1))*1440,
          z, XMATCH(5,y,1),
          INDEX(x,z,2)))

F5: (Date next to last): =IF(COUNTIFS(Table1[Date/Time],">="&E5,Table1[Date/Time],"<" & EDATE(E5,1))=0,"",
LET(x,FILTER(Table1[Date/Time],(Table1[Date/Time]>=E5)*(Table1[Date/Time]<EDATE(E5,1))),
          INDEX(x,COUNT(x)-1)))

G5: (Pressure next to last):=IF(F5="","",
LET(x,FILTER(Table1,(Table1[Date/Time]>=E5)*(Table1[Date/Time]<EDATE(E5,1))),
          INDEX(x,COUNT(INDEX(x,0,1))-1,2)))