You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于点火状态的叉车工作时长计算及边界条件处理技术需求

处理叉车点火状态边界条件的Power Query解决方案

我看你已经搞定了基础的工作时长计算,但碰到了跨天和当日未闭合ON记录的棘手情况——放心,咱们调整下Power Query代码就能完美解决:当设备当日最后一条是ON时,把时长算到当日午夜,后续的OFF记录则计入次日的工作时长。

完整修改后的代码

let
    Source = Excel.Workbook(File.Contents("C:\Users\avyas2\Desktop\DataToTest.xlsx"), null, true),
    Sheet1_Sheet = Source{[Item="Sheet1",Kind="Sheet"]}[Data],
    #"Promoted Headers" = Table.PromoteHeaders(Sheet1_Sheet, [PromoteAllScalars=true]),
    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"DEVICEID", Int64.Type}, {"DATETIME", type datetime}, {"IGNITIONSTATUS", type text}}),
    // 按设备+时间排序,保证记录顺序正确,配对不会出错
    #"Sorted Rows" = Table.Sort(#"Changed Type",{{"DEVICEID", Order.Ascending}, {"DATETIME", Order.Ascending}}),
    // 给每条ON记录找对应的下一条OFF(跨天也能匹配)
    #"Added Next Status" = Table.AddColumn(#"Sorted Rows", "NextStatus", (current) => 
        let
            sameDeviceLater = Table.SelectRows(#"Sorted Rows", each [DEVICEID] = current[DEVICEID] and [DATETIME] > current[DATETIME]),
            nextOffRecord = Table.SelectRows(sameDeviceLater, each [IGNITIONSTATUS] = "OFF"){0}?
        in nextOffRecord),
    // 只保留ON记录,因为我们要基于ON来计算时长
    #"Filter ON Rows" = Table.SelectRows(#"Added Next Status", each [IGNITIONSTATUS] = "ON"),
    // 处理无后续OFF的情况:用当日午夜作为结束时间
    #"Extend ON-OFF Pairs" = Table.TransformColumns(#"Filter ON Rows", {
        {"DATETIME", each _, type datetime},
        {"NextStatus", (next) => if next = null then 
            DateTime.From(DateTime.Date(_) + #duration(1,0,0,0)) // 当日午夜(次日0点)
        else next[DATETIME], type datetime}
    }),
    // 把跨天的时间区间拆分成单日记录
    #"Split Cross-Day Intervals" = Table.ExpandListColumn(Table.AddColumn(#"Extend ON-OFF Pairs", "DailyIntervals", (row) => 
        let
            startDt = row[DATETIME],
            endDt = row[NextStatus],
            startDate = DateTime.Date(startDt),
            endDate = DateTime.Date(endDt),
            sameDay = startDate = endDate,
            // 跨天就拆成两段:当天到午夜,次日从0点到OFF时间
            intervals = if sameDay then 
                {{startDt, endDt, startDate}}
            else 
                {{startDt, DateTime.From(startDate + #duration(1,0,0,0)), startDate},
                 {DateTime.From(endDate), endDt, endDate}}
        in intervals), "DailyIntervals"),
    // 拆分区间字段到单独列
    #"Split Interval Column" = Table.SplitColumn(#"Split Cross-Day Intervals", "DailyIntervals", (x) => {x{0}, x{1}, x{2}}, {"StartDateTime", "EndDateTime", "Date"}),
    // 计算当日工作时长
    #"Calculate Daily Hours" = Table.AddColumn(#"Split Interval Column", "WorkingHrs", each Duration.TotalHours([EndDateTime] - [StartDateTime]), type number),
    // 整理最终需要的列
    #"Final Cleanup" = Table.SelectColumns(#"Calculate Daily Hours", {"DEVICEID", "Date", "WorkingHrs"})
in
    #"Final Cleanup"

关键调整点解释

  1. 排序与配对逻辑:
    先按设备和时间排序,确保每条ON记录能精准找到后续的第一条OFF记录——哪怕这个OFF是第二天的。如果某条ON之后没有OFF(设备一直处于ON状态到当日结束),就自动用**当日午夜(次日0点)**作为临时结束时间。

  2. 跨天区间拆分:
    当ON-OFF区间跨天时,我们把它拆成两个独立的单日区间:

    • 第一段:从ON时间到当日午夜,归属到ON所在的日期
    • 第二段:从次日0点到OFF时间,归属到OFF所在的日期
      这样就完美实现了你要求的“跨天时长分日期统计”。
  3. 最终计算:
    对拆分后的每个单日区间计算时长,最后只保留设备ID、日期、工作时长三个核心字段,结果更清晰。

用你的测试数据集跑一遍,比如设备2在10/28的最后一条ON记录,会被计算为从14:01:44到24:00的时长;而10/29的OFF记录则对应10/29当天0:00到14:01:44的时长,完全符合需求。

内容的提问来源于stack exchange,提问作者Ashish Vyas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 06:55:37