Forum Discussion
Splitting period data into months
- 9 years ago
Hi lkarolak,
In your scenario, you can create a function use a blank query like below:
(startdate as date, enddate as date) as table => let //startdate=#date(2015,8,1), //enddate=#date(2016,1,31), Source = {Number.From(startdate)..Number.From(enddate)}, #"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error), #"Changed Type" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type date}}), #"Renamed Columns" = Table.RenameColumns(#"Changed Type",{{"Column1", "Date"}}), #"Calculated End of Month" = Table.TransformColumns(#"Renamed Columns",{{"Date", Date.EndOfMonth, type date}}), #"Removed Duplicates" = Table.Distinct(#"Calculated End of Month"), #"Inserted End of Year" = Table.AddColumn(#"Removed Duplicates", "EndOfYear", each Date.EndOfYear([Date]), type date), #"Grouped Rows" = Table.Group(#"Inserted End of Year", {}, {{"Original", each _, type table}, {"Months_Total", each Table.RowCount(_), type number}}) in #"Grouped Rows"Then rename the function as fnGetAllocationBase.
In the query which get the fact table, invoke this function like below:
let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUTIyMDTXNTTQRbCNdI1BHEsDpVidaCUjiLiZrqEusnKwEkMDA6CiWAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [ID = _t, BEGIN = _t, END = _t, VALUE = _t]), #"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"BEGIN", type date}, {"END", type date}, {"VALUE", Int64.Type}}), #"Added Custom" = Table.AddColumn(#"Changed Type", "Custom", each fnGetAllocationBase([BEGIN],[END])), #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"BEGIN", "END"}), #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns", "Custom", {"Original", "Months_Total"}, {"Custom.Original", "Custom.Months_Total"}), #"Expanded Custom.Original" = Table.ExpandTableColumn(#"Expanded Custom", "Custom.Original", {"Date", "EndOfYear"}, {"Custom.Original.Date", "Custom.Original.EndOfYear"}), #"Added Custom1" = Table.AddColumn(#"Expanded Custom.Original", "Value_update", each [VALUE]/[Custom.Months_Total]), #"Changed Type1" = Table.TransformColumnTypes(#"Added Custom1",{{"Custom.Original.Date", type date}, {"Custom.Original.EndOfYear", type date}}) in #"Changed Type1"Reference:
Allocate Units Based on Dates Using Power Query
Best Regards,
Qiuyun Yu
Hi lkarolak,
In your scenario, you can create a function use a blank query like below:
(startdate as date, enddate as date) as table =>
let
//startdate=#date(2015,8,1),
//enddate=#date(2016,1,31),
Source = {Number.From(startdate)..Number.From(enddate)},
#"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Changed Type" = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type date}}),
#"Renamed Columns" = Table.RenameColumns(#"Changed Type",{{"Column1", "Date"}}),
#"Calculated End of Month" = Table.TransformColumns(#"Renamed Columns",{{"Date", Date.EndOfMonth, type date}}),
#"Removed Duplicates" = Table.Distinct(#"Calculated End of Month"),
#"Inserted End of Year" = Table.AddColumn(#"Removed Duplicates", "EndOfYear", each Date.EndOfYear([Date]), type date),
#"Grouped Rows" = Table.Group(#"Inserted End of Year", {}, {{"Original", each _, type table}, {"Months_Total", each Table.RowCount(_), type number}})
in
#"Grouped Rows"
Then rename the function as fnGetAllocationBase.
In the query which get the fact table, invoke this function like below:
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMlTSUTIyMDTXNTTQRbCNdI1BHEsDpVidaCUjiLiZrqEusnKwEkMDA6CiWAA=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [ID = _t, BEGIN = _t, END = _t, VALUE = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"BEGIN", type date}, {"END", type date}, {"VALUE", Int64.Type}}),
#"Added Custom" = Table.AddColumn(#"Changed Type", "Custom", each fnGetAllocationBase([BEGIN],[END])),
#"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"BEGIN", "END"}),
#"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns", "Custom", {"Original", "Months_Total"}, {"Custom.Original", "Custom.Months_Total"}),
#"Expanded Custom.Original" = Table.ExpandTableColumn(#"Expanded Custom", "Custom.Original", {"Date", "EndOfYear"}, {"Custom.Original.Date", "Custom.Original.EndOfYear"}),
#"Added Custom1" = Table.AddColumn(#"Expanded Custom.Original", "Value_update", each [VALUE]/[Custom.Months_Total]),
#"Changed Type1" = Table.TransformColumnTypes(#"Added Custom1",{{"Custom.Original.Date", type date}, {"Custom.Original.EndOfYear", type date}})
in
#"Changed Type1"
Reference:
Allocate Units Based on Dates Using Power Query
Best Regards,
Qiuyun Yu
- lkarolak9 years agoFrequent Visitor
Thanks Qiuyun Yu, that seems to do the trick!
- Anonymous9 years agoNot applicable
Wow, this is an AWESOME solution!
It helped me very much, thank you Qiuyun!
Please tell me, where can I learn more of those tricks and advanced scenarios working with Power Query.
I mean manipulating tables / using functions, etc.
Would you recommend some site / book / youtube?
Thanks
Michael
- Anonymous9 years agoNot applicable
awesome! exactly what I needed! thanks so much
- WojtekP6 years agoFrequent Visitor
Great solution!
I tried to use your solution to split total contract value (TCV) into annual contract value (ACV) but with no luck.
My data has a mixture of contracts duration between 1 day to 5years+
All contracts =< 1 year require no attention but if a contract is eg 4 year long, it should be split into 4 rows as follows. Here is the example:
Source:
Index Amount Start Date End Date Year Days 1 261,600.00 01/06/2016 31/12/2019 2016 1308 Result:
Index Amount Start Date End Date Year Days 1 72,800.00 01/06/2016 31/05/2017 2016 364 1 72,800.00 01/06/2017 31/05/2018 2017 364 1 72,800.00 01/06/2018 31/05/2019 2018 364 1 42,600.00 01/06/2019 31/12/2019 2019 213 So i need to include full 12 months (72,800 USD) into 2016 as ACV (as opposed to revenue recognition method where i would include only 7 months) ..
Hope it is clear and someone can help! 🙂