Dax Calculation for forecast and resetting for batch sizes

I have a sales forecast by units and I am trying to take those quantity and accumulate them until I get to what a batch size is and then keep the remaining for the month and apply to the next forecast until we get to the batch size again. Each product could have a different batch size. Each Forecast is done based on a single day each month. We put all the forecast on Day 1 of each month. Example and Screen shot of what I am going for below. The forecast I want to go up to the b

batch size for Product 1 is 2,000 units
Month 1 Foreacst = 953
Month2 Forecast = 1,398
Month 3 Forecast = 837

Month 2 accumulated forecast is 953+1,398 = 2,351.
Since the batch size is 2,000 I want to group the amount at 2,000 and then the remaining 351 over the 2,000 unit batch size would be added to the 837 of Month 3 Forecast giving me an accumulated forecast of 1,188.

Is there a way with measures to accomplish this?

forecast test.xlsx (9.5 KB)

@andersenjeff5 ,

Welcome to the forum – great to have you here!

One question for you – does this need to be a DAX solution (i.e., dynamic within the context of a given reporting session) or would a Power Query Solution be acceptable?

Good one! – really interesting conceptual problem. This has already got my wheels spinning …

  • Brian
1 Like

Hi Brian,

I would prefer it to be a DAX solution, but at this point I will honestly take whatever solution I can that works. I originally tried to use the MROUND Function and round it to batch sizes, but I then noticed that any quantity that was less than 1/2 the batch size, rounded to 0 and then I got stuck in not being able to full get this figured out.

I have also tried where I am converting the quantity into fractional batches and then round up tot he nearest whole number, my problem then is I get the running total of batches and when I get there, It may say in month 3 I need 2 batches, but it reality it is 1 batch in month 2 and 1 batch in month 3, and I have not been able to figure out a good way to then subtract those extra batches out in the following months.

@andersenjeff5 ,

OK, got it. Super fun problem to work through. I worked it through in PQ/M, but now that I’ve got the algorithm, should be straightforward to replicate in DAX if you’d like. Here’s what I did:

Here’s the result:

And here’s the full M code:

let
  Source = Table.FromRows(
    Json.Document(
      Binary.Decompress(
        Binary.FromText(
          "Tc4xDsAgDAPAr1SZGQghkDyiL0Dsndql/1chUiWvJ1v2GHQ+93sdTIlchWb6pSxhcQOSRSYdpEatgujOOEqLTAPpIQXE9lhhB/LYtwzEeRsrfuJ43hbNDw==", 
          BinaryEncoding.Base64
        ), 
        Compression.Deflate
      )
    ), 
    let
      _t = ((type nullable text) meta [Serialized.Text = true])
    in
      type table [#"Month Num" = _t, Forecast = _t]
  ), 
  #"Changed Type" = Table.TransformColumnTypes(Source, {{"Forecast", Int64.Type}}), 
  #"Add Index1" = Table.AddIndexColumn(#"Changed Type", "Index", 0, 1, Int64.Type), 
  #"Renamed Columns" = Table.RenameColumns(#"Add Index1", {{"Index", "Index0"}}), 
  #"Add Index0" = Table.AddIndexColumn(#"Renamed Columns", "Index", 1, 1, Int64.Type), 
  #"Renamed Columns1" = Table.RenameColumns(#"Add Index0", {{"Index", "Index1"}}), 
  #"Add Cumul Fcast" = Table.AddColumn(
    #"Renamed Columns1", 
    "Cumul Fcast", 
    each List.Sum(List.Range(#"Renamed Columns1"[Forecast], 0, [Index1]))
  ), 
  #"Changed Type1" = Table.TransformColumnTypes(#"Add Cumul Fcast", {{"Cumul Fcast", Int64.Type}}), 
  #"Add Modulo CF Batchsize" = Table.AddColumn(
    #"Changed Type1", 
    "CF Modulo", 
    each Number.Mod([Cumul Fcast], #"Batch Size")
  ), 
  #"Add IntDiv CF Batchsize" = Table.AddColumn(
    #"Add Modulo CF Batchsize", 
    "CF IntDiv", 
    each Number.IntegerDivide([Cumul Fcast], #"Batch Size")
  ), 
  #"Feldmann Shift" = Table.NestedJoin(
    #"Add IntDiv CF Batchsize", 
    {"Index0"}, 
    #"Add IntDiv CF Batchsize", 
    {"Index1"}, 
    "Add IntDiv CF Batchsize", 
    JoinKind.LeftOuter
  ), 
  #"Expanded for Prev CF IntDiv" = Table.ExpandTableColumn(
    #"Feldmann Shift", 
    "Add IntDiv CF Batchsize", 
    {"CF IntDiv"}, 
    {"CF IntDiv.1"}
  ), 
  #"Sorted Rows" = Table.Sort(#"Expanded for Prev CF IntDiv", {{"Index1", Order.Ascending}}), 
  #"Renamed Columns2" = Table.RenameColumns(#"Sorted Rows", {{"CF IntDiv.1", "CF IntDiv Prev"}}), 
  #"Add 1st Occur Int Div" = Table.AddColumn(
    #"Renamed Columns2", 
    "1st Occur IntDiv", 
    each if [CF IntDiv Prev] = null then 0 else if [CF IntDiv] <> [CF IntDiv Prev] then 1 else 0
  ), 
  #"Add Accumulated Forecast" = Table.AddColumn(
    #"Add 1st Occur Int Div", 
    "Accumulated Forecast", 
    each [CF Modulo] + (#"Batch Size" * [1st Occur IntDiv])
  ), 
  #"Changed Type2" = Table.TransformColumnTypes(
    #"Add Accumulated Forecast", 
    {
      {"CF Modulo", Int64.Type}, 
      {"CF IntDiv", Int64.Type}, 
      {"CF IntDiv Prev", Int64.Type}, 
      {"1st Occur IntDiv", Int64.Type}, 
      {"Accumulated Forecast", Int64.Type}
    }
  )
in
  #"Changed Type2"

I hope this is helpful. Full solution attached.

  • Brian

eDNA Forum - Batch Size Forecast Solution.pbix (23.1 KB)

2 Likes

Hi @BrianJ,
With the idea of learning I was trying to solve this problem with DAX. Once I had seen that it worked with the example, I modified the excel values to see if I got the same result but there were some differences, so I thought that the problem was not solved.
After seeing your solution, I realized that the problem was in the excel of the example, which does not work for any initial value of the forecast.
I send the solution in DAX in case it can be useful to @andersenjeff5. Any comment from you will be welcome.
Thank you very much

Batch Size Forecast_JAFP.pbix (26.5 KB)
forecast test.xlsx (9.2 KB)

1 Like

@jafernandezpuga ,

Nice work. I also had implemented a DAX solution today (just a literal translation of every column in my PQ/M solution into a DAX measure) using the original forecast data, and adding a what-if parameter for batch size. I will run my model with your revised data just to confirm that we’re getting the same results.

Solution file attached.

  • Brian

eDNA Forum - Batch Size Forecast Solution.pbix (29.9 KB)

1 Like

@jafernandezpuga ,

Bingo! Our results match exactly with the revised forecast data.

office

  • Brian

@BrianJ & @jafernandezpuga

Thank you for your responses, I will work on putting this to my data and let you know the results. I appreciate your quick turn around on these!

3 Likes

Hello @andersenjeff5 , a gentle follow up if you were able to solve your query?

Hi @BrianJ,
I’m glad the results match. You were very successful with the use of the What If parameter.
Thank you very much.

2 Likes

It’s great to know that you are making progress with your query @andersenjeff5.

Please don’t forget if your question has been answered within the forum it is important to mark your thread as ‘solved’. We request you to kindly take time to answer the Enterprise DNA Forum User Experience Survey, We hope you’ll give your insights on how we can further improve the Support forum.

We’ve also noticed that no response has been received from you since a few days ago. In case there won’t be any activity on it in the next few days, we’ll be tagging this post as Solved.

@BrianJ ,

I have been asked a follow up on this question as well and wondering if you could offer some more help. For when the batch size is removed from the forecast by the MOD formula, could there be a result of the count. Example from above, in month 2 the cumulative forecast above was 3399 and it removed the 2000 batch size, is there a way to give a result of ‘1’ since that is the number of batches it removed for the forecast and also in month 5 where it removed 4000 it would give me a result of ‘2’. For all other month where it did not have to remove the batch size from a month it would give me ‘0’

Hi @andersenjeff5 and @BrianJ,
In the solution I shared is the measurement you need:

Quotient Cumulative Forecast = QUOTIENT( [Cumulative Forecast] , [Batch Size] )

Regards,

Hi @jafernandezpuga,

This is close, I got to this point as well a different way but what I would want to see is the following
Month 1 = 1
Month 2 = 0
Month 3= 1
Month 4 = 0
Month 5 = 1
Month 6=0
Month 7=0
Month 8=1
Month 9=1
Month 10=0
Month 11=1

Just where the number goes to the next integer saying, 1 batch needs to plotted here and the months where there is no batch needed it would be a 0

Hello @andersenjeff5 ,
We can calculate it by subtracting the current value of [Quotient Cumulative Forecast] minus the value of the previous row:

.# Batch = [Quotient Cumulative Forecast] - [Quotient Cumulative Forecast Before]

And this other one so that it correctly calculates the totals:

Total #Batch =
IF(
HASONEVALUE( Data[Index] ),
[#Batch],
SUMX(
ADDCOLUMNS(
VALUES( Data[Index] ),
“@#Batch”, [#Batch]
),
[@#Batch]
)
)

Regards,

Batch Size Forecast_JAFP.pbix (28.7 KB)