Forum Discussion
Shadow61
6 months agoNew Member
Error in Power Query combining overlapping start end datetime fields
Sorry , new to Power Query. I have a table of records where for a given ID, I want to merge then if the Startdatetime and Enddatetime overlap. Copilot gave me some sample code, but it gives me a To...
- 6 months ago
You can try this Power Query code, which seems to be a bit faster:
let //Change next line to reflect actual data source Source = Sheet1, // Sort by StartDate, then EndDate Sorted = Table.Sort(Source,{{"Start", Order.Ascending}, {"End", Order.Ascending}}), // Add index Indexed = Table.AddIndexColumn(Sorted, "Index", 0, 1), // Group and merge overlapping ranges Grouped = Table.Group(Indexed, {"ID"}, {{"Merged", (t) => List.Accumulate( Table.ToRecords(t), {}, (state, current) => if List.IsEmpty(state) then {[Start = current[Start], End = current[End]]} else let last = List.Last(state), remaining = List.RemoveLastN(state, 1) in if current[Start] <= last[End] then remaining & {[Start = last[Start], End = List.Max({last[End], current[End]})]} else state & {[Start = current[Start], End = current[End]]} ) , type table[Start=datetime, End=datetime]}} ), Expanded = Table.ExpandTableColumn(Grouped, "Merged", {"Start", "End"}) in ExpandedIn VBA, Application.ScreenUpdating = False will disable writing while the macro is being executed. But if you do the entire logic within VBA, that wouldn't be necessary. But for large data sets, I would think Power Query would be faster for a number of reasons.
AlienSx
6 months agoSuper User
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
types = Table.TransformColumnTypes(Source,{{"Start", type datetime}, {"End", type datetime}}),
sort = Table.Sort(types, {"ID", "Start"}),
rows = List.Buffer(Table.ToList(sort, each _)),
gnr = List.Generate(
() => [i = 0, r = rows{0}, min = r{1}, max = r{2}],
(x) => x[i] < List.Count(rows),
(x) => [
i = x[i] + 1,
r = rows{i},
next = r{0} <> x[r]{0} or r{1} > x[max],
min = if next then r{1} else x[min],
max = if next then r{2} else List.Max({r{2}, x[max]})
],
(x) => {x[r]{0}, x[min], x[max]}
),
result = Table.Group(
Table.FromList(gnr, each _, {"ID", "Start", "End"}),
{"ID", "Start"},
{"End", (x) => Table.Last(x)[End]},
GroupKind.Local
)
in
result