// fnCostScaledQuantities (Table, Qty) => let RelevantQty = Table.AddColumn(Table, "RelevantQty", each if List.NonNullCount({[ToQty],[FromQty]})=0 then Qty else List.Min({[ToQty],Qty})-List.Min({[FromQty]-1,Qty})), Total = Table.AddColumn(RelevantQty, "Total", each if [FixOrQty]="Qty" then [RelevantQty]*[Amount] else [Amount]) in Total // fnBreakEvenQty (CostTable, Price, optional Lowest, optional Highest) => let Lowest = if Lowest = null then 0 else Lowest, Highest = if Highest = null then 10000000000 else Highest, Result= List.Generate( ()=> [Lowest=Lowest, Highest=Highest, Result=1, Counter=0, Value=Highest, DiffToPrevious=0.1], // Conditions determining if the next execution of the loop shall be performed each Number.Abs([Result])>=0.000000000001 and [Counter]<1000 and [DiffToPrevious]<>0, // loop command each [ // Binary-search procedure Lowest = if [Result]<0 then [Value] else [Lowest], Highest= if [Result]>0 then [Value] else [Highest], Value= (Lowest+ Highest)/2, // Call helper-function Costs = fnCostScaledQuantities(CostTable, Value), // Goal (formulated in a way that it should be null): Result= Price*Value-List.Sum(Costs[Total]), // Check if the result is still improving/changing DiffToPrevious = Result-[Result], Counter=[Counter]+1 ] ), Custom3 = List.Last(Result)[Value] in Custom3 // CostTable let Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcsusSE1RcM4vLilW0lEyNAACIA0UhfKAFAjF6kQrhSUWZSYm5aRCVCsYAsWNICoCSypBHNxqQVLGyGotQMZDrCBKvRFYrSEO442B4ibIys1hxptiNR5DvSlYLUiHKXYHYegwAquFOCgWAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type text) meta [Serialized.Text = true]) in type table [What = _t, Code = _t, FixOrQty = _t, Amount = _t, FromQty = _t, ToQty = _t]), #"Changed Type" = Table.TransformColumnTypes(Source,{{"What", type text}, {"Code", Int64.Type}, {"FixOrQty", type text}, {"Amount", type number}, {"FromQty", Int64.Type}, {"ToQty", Int64.Type}}) in #"Changed Type" // Price 20 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // Quantity 200 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // QuantitiesStartValue 0 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // QuantitiesNumberOfIntervals 10 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // QuantitiesIncrementIntervall 50 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // PricesStartValue 15 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // PricesNumberOfIntervals 10 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // PricesIncrementIntervall 5 meta [IsParameterQuery=true, Type="Number", IsParameterQueryRequired=true] // BreakEvenQuantity let Source = fnBreakEvenQty(CostTable, Price, null, null) in Source // fnBreakEvenPrice (CostTable, Qty, optional Lowest, optional Highest) => let Lowest = if Lowest = null then 0 else Lowest, Highest = if Highest = null then 10000000000 else Highest, Result= List.Generate( ()=> [Lowest=Lowest, Highest=Highest, Result=1, Counter=0, Value=Highest, DiffToPrevious=0.1], // Conditions determining if the next execution of the loop shall be performed each Number.Abs([Result])>=0.000000000001 and [Counter]<1000 and [DiffToPrevious]<>0, // loop command each [ // Binary-search procedure Lowest = if [Result]<0 then [Value] else [Lowest], Highest= if [Result]>0 then [Value] else [Highest], Value= (Lowest+ Highest)/2, // Call helper-function Costs = fnCostScaledQuantities(CostTable, Qty), // Goal (formulated in a way that it should be null): Result= Qty*Value-List.Sum(Costs[Total]), // Check if the result is still improving/changing DiffToPrevious = Result-[Result], Counter=[Counter]+1 ] ), Custom3 = List.Last(Result)[Value] in Custom3 // BreakEvenPrice let Source = fnBreakEvenPrice(CostTable, Quantity, null, null) in Source // QtyScenarios let Table = Table.FromColumns({{0..QuantitiesNumberOfIntervals}}), AddColumns = Table.AddColumn(Table, "Columns", each [ Qty = QuantitiesStartValue+QuantitiesIncrementIntervall*[Column1], Costs = List.Sum(fnCostScaledQuantities(CostTable,Qty)[Total]), Turnover = Price*Qty, FixCosts = List.Sum(Table.SelectRows(CostTable, each [FixOrQty]="Fix")[Amount]), Result = Turnover-Costs, BreakEvenPrice = if Qty>0 then fnBreakEvenPrice(CostTable, Qty) else null ]), ExpandColumns = Table.ExpandRecordColumn(AddColumns, "Columns", {"Qty", "Costs", "Turnover", "FixCosts", "Result", "BreakEvenPrice"}), ChgTypes = Table.TransformColumnTypes(ExpandColumns,{{"Result", type number}, {"Costs", type number}, {"Qty", type number}, {"BreakEvenPrice", type number}, {"Turnover", type number}, {"FixCosts", type number}}) in ChgTypes // PriceScenarios let Source = Table.FromColumns({{0..PricesNumberOfIntervals}}), AddColumns = Table.AddColumn(Source, "Columns", each [ Price = PricesStartValue+PricesIncrementIntervall*[Column1], Costs= List.Sum(fnCostScaledQuantities(CostTable,Quantity)[Total]), Turnover = Price*Quantity, Result = Turnover - Costs, BreakEvenQty = fnBreakEvenQty(CostTable, Price) ]), ExpandCols = Table.ExpandRecordColumn(AddColumns, "Columns", {"Price", "Costs", "Turnover", "Result", "BreakEvenQty"}), ChgTypes = Table.TransformColumnTypes(ExpandCols,{{"Result", type number}, {"Price", type number}, {"Costs", type number}, {"BreakEvenQty", type number}, {"Turnover", type number}}) in ChgTypes