skip to main content
Power BI
    • What is Power BI
    • Why Power BI
    • Customer stories
    • Data visuals
    • Security
    • Power BI Desktop
    • Power BI Pro
    • Power BI Premium
    • Power BI Mobile
    • Power BI Embedded
    • Power BI Report Server
  • Pricing
    • Azure + Power BI
    • Microsoft 365 + Power BI
    • Dynamics 365 + Power BI
      • Energy
      • Healthcare
      • Manufacturing
      • Media
      • Retail
    • For analysts
    • For IT
      • Overview
      • Embedded analytics
      • Power BI visuals
      • Automation
      • Documentation
      • Community
    • Overview
    • Find consulting services
    • Partner showcase
    • Find a partner
    • Become a partner
    • Instructor-led training
    • Getting started
      • Overview
      • Online workshops
      • Self-guided learning
      • Webinars
      • Documentation
      • Roadmap
      • Overview
      • Issues
      • Give feedback
    • Blog
    • Business intelligence topics
    • Overview
    • Forums
    • Galleries
    • Submit ideas
    • Events
    • User groups
    • Community blog
    • Register
    • ·
    • Sign in
    • ·
    • Help
    Go To
    • Galleries
    • Community Connections & How-To Videos
    • COVID-19 Data Stories Gallery
    • Themes Gallery
    • Data Stories Gallery
    • R Script Showcase
    • Webinars and Video Gallery
    • Quick Measures Gallery
    • 2021 MSBizAppsSummit Gallery
    • 2020 MSBizAppsSummit Gallery
    • 2019 MSBizAppsSummit Gallery
    • Events
    cancel
    Turn on suggestions
    Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.
    Showing results for 
    Search instead for 
    Did you mean: 
    • Microsoft Power BI Community
    • Galleries
    • Quick Measures Gallery
    • Re: Days of Supply

    Re: Days of Supply

    07-03-2019 09:33 AM

    Sergii24
    Helper I
    11526 Views
    LinkedIn LinkedIn Facebook Facebook Twitter Twitter
    Greg_Deckler
    Super User Greg_Deckler
    Super User
    • Mark as New
    • Bookmark
    • Subscribe
    • Mute
    • Subscribe to RSS Feed
    • Permalink
    • Print
    • Report Inappropriate Content

    Days of Supply

    ‎03-03-2019 09:29 AM

    Suppose you have a weekly forecast of inventory and demand and you wish to know for each week the number of days of supply that you have on hand. That is the purpose of this Quick Measure. Inputs are the current week and inventory as well as the demand column.

     

     

    Days of Supply = 
    // Get the current week and inventory for the current row
    VAR __week = MAX([Week])
    VAR __inventory = MAX([Ending on hand Inventory])
    // Create a table of all weeks greater than the current week
    VAR __table = FILTER(ALL(Inventory),[Week]>__week)
    // Add our current inventory from above to each row
    VAR __table1 = ADDCOLUMNS(__table,"__start",__inventory)
    // Add a running total of demand to each row
    VAR __table2 = ADDCOLUMNS(__table1,"__demand",SUMX(FILTER(__table1,[Week]<=EARLIER([Week])),[Demand]))
    // Add the difference in start versus the running total of demand to each row
    VAR __table3 = ADDCOLUMNS(__table2,"__left",[__start] - [__demand])
    // Create a table that only has the positive rows
    VAR __table4 = FILTER(__table3,[__left]>=0)
    // With only the positive rows, the MIN is the last row before demand runs out
    VAR __min = MINX(__table4,[__left])
    // Therefore, our base days is the number of rows in this table * 7
    VAR __baseDays = COUNTROWS(__table4)*7
    // Grab the MAX value of the negative rows, this is the row right after our inventory runs out
    VAR __max = MAXX(FILTER(__table3,[__left]<0),[__left])
    // Divide the row right before the invetory ran out by the sum of the absolute values of right before and after 
    // the inventory ran out. This is the percentage of days in that week before inventory ran out. multiply this by 7
    // and this is the number of days in that week before inventory ran out
    VAR __extraDays = __min / (__min + ABS(__max)) * 7
    RETURN
    __baseDays + __extraDays

     

     

    Interestingly, this Quick Measure exhibits a form of "looping" in DAX, or at least a work-a-round. Consider that a primary task of this measure is to determin the week in which inventory "runs out". In traditional programming, one would determine this with something like a for or while loop, checking for a boundary condition of the inventory on hand becoming negative with respect to demand. However, in DAX, there are no for or while looping constructs. Thus, instead we create a temporary table where each row in the table represents one pass or iteration through a traditional programming "loop". We can then use our boundary condition to filter down to the specific rows where that boundary condition occurs in order to perform our calculation. As demonstrated in the DAX code above, we can determine the values on either side of our boundary condition as well as how many "interations" were required in order to hit that boundary condition.

     

    eyJrIjoiZDcxY2U3ZjAtM2ZiMy00ZjJhLWE0N2YtZTM5YjFiNDJlMTJlIiwidCI6IjRhMDQyNzQzLTM3M2EtNDNkMi04MjdiLTAwM2Y0YzdiYTFlNSIsImMiOjN9


    @ me in replies or I'll lose your thread!!!
    Instead of a Kudo, please vote for this idea
    Become an expert!: Enterprise DNA
    External Tools: MSHGQM
    YouTube Channel!: Microsoft Hates Greg
    Latest book!:
    Mastering Power BI 2nd Edition

    DAX is easy, CALCULATE makes DAX hard...
    Preview file
    23 KB
    DaysOfSupply.pbix
    Labels:
    • Labels:
    • Mathematical
    • Other
    • Time Intelligence
    Message 1 of 5
    12,699 Views
    6
    Reply
    • All forum topics
    • Previous Topic
    • Next Topic
    Anonymous
    Not applicable
    • Mark as New
    • Bookmark
    • Subscribe
    • Mute
    • Subscribe to RSS Feed
    • Permalink
    • Print
    • Report Inappropriate Content

    ‎04-23-2020 01:23 AM

    Hi @Greg_Deckler 

    I tried your solution and unfortunately the measure I created returned as blank.

     

    My data table is structured:

    Product Name Product Brand Product Category Date Forecast Inventory

     

    The date column is just weeks like in your example. I'm thinking maybe the difference is that mine has a product hierarchy?

     

    The code I entered was therefore:

     

    Days of Supply:=VAR __week = MAX('Stock Movements'[Date])
    VAR __inventory = MAX('Stock Movements'[Inventory])
    VAR __table = FILTER(ALL('Stock Movements'),'Stock Movements'[Date]>__week)
    VAR __table1 = ADDCOLUMNS(__table,"__start",__inventory)
    VAR __table2 = ADDCOLUMNS(__table1,"__demand",SUMX(FILTER(__table1,'Stock Movements'[Date]<=EARLIER('Stock Movements'[Date])),'Stock Movements'[Forecast]))
    VAR __table3 = ADDCOLUMNS(__table2,"__left",[__start] - [__demand])
    VAR __table4 = FILTER(__table3,[__left]>=0)
    VAR __min = MINX(__table4,[__left])
    VAR __baseDays = COUNTROWS(__table4)*7
    VAR __max = MAXX(FILTER(__table3,[__left]<0),[__left])
    VAR __extraDays = __min / (__min + ABS(__max)) * 7
    RETURN
    __baseDays + __extraDays

     

    Unfortunately when entering this it returns blank for everything.

     

    Do you have any idea why this would be the case and what I could do?

     

    Many thanks,

    Paddy

    Message 5 of 5
    7,795 Views
    1
    Reply
    Sergii24
    Sergii24 Helper I
    Helper I
    • Mark as New
    • Bookmark
    • Subscribe
    • Mute
    • Subscribe to RSS Feed
    • Permalink
    • Print
    • Report Inappropriate Content

    ‎07-03-2019 09:33 AM

    Hi @Greg_Deckler ! Thank you very much for the great idea!

    Currently I'm trying to expand it to the case, when there is a product hierachy: Brand->Prod Group->Product (SKU). In addition the same product have stock, production and forecst on different location (such as plants and distribution centers). The aim is to have a dynamic access to the Days of Supply based on the current selection.

     

    The problem arises when I try to create _Table2

    // Add a running total of demand to each row
    VAR __table2 = ADDCOLUMNS(__table1,"__demand",SUMX(FILTER(__table1,[Week]<=EARLIER([Week])),[Demand]))

    The point is to correctly filter _table1 and use SUMX for the forecast but what happens is that depending on the situation I might filter or not filter some of the parameters (let's say, the location). Meaning that one time I can have 2 filters (week<Earlier[week] and SKU=Earlier[SKU]) in another case 3 filters (week<Earlier[week] and SKU=Earlier[SKU] and location=Earlier[Location]) and so on. What creates additional complexity is the situation when I select multiple locations (each has a string name), therefore I don't know how to "put them together" to a variable "Location".

     

    Attached you can find a data sample: I want Days of Supply change dynamically depending on the level of hierarchy selected, including the situation, when only some wahrehouse is selected meaning only allocated part of inventory, forecast and production should be considered.

     

    So the problem is to arrive to the following structure (depending on the hierarchy selected) described in your post as _table2.

     Level 3     Level 2     Level 1 
     Inventory   FrcstCummul     Inventory   FrcstCummul     Inventory   FrcstCummul 
         12.694,5                 886,0        24.788,1             4.294,0        24.425,4             4.447,0
         12.694,5             1.734,0        24.788,1             7.948,0        24.425,4             8.247,0
         12.694,5             2.278,0        24.788,1           10.629,0        24.425,4           11.067,0
         12.694,5             2.818,0        24.788,1           13.014,0        24.425,4           13.601,0
         12.694,5             3.304,0        24.788,1           16.165,0        24.425,4           16.915,0
         12.694,5             5.416,0        24.788,1           21.259,0        24.425,4           22.205,0
         12.694,5             7.929,0        24.788,1           28.964,0        24.425,4           30.159,0
         12.694,5             9.684,0        24.788,1           33.069,0        24.425,4           34.404,0
         12.694,5           11.268,0        24.788,1           38.012,0        24.425,4           39.490,0
         12.694,5           12.992,0        24.788,1           42.336,0        24.425,4           43.939,0
         12.694,5           14.704,0        24.788,1           45.967,0        24.425,4           47.680,0

     

     

    Would be grateful if you can help to find the solution!

    Thanks!

    Preview file
    371 KB
    Message 4 of 5
    11,526 Views
    0
    Reply
    Anonymous
    Not applicable
    • Mark as New
    • Bookmark
    • Subscribe
    • Mute
    • Subscribe to RSS Feed
    • Permalink
    • Print
    • Report Inappropriate Content

    ‎05-27-2019 10:46 AM

    @Greg_Deckler Thanks for sharing! I've been using this Days of Supply calculation for an Inventory BI, but edited it to calculate on a monthly basis. Database is set up the same as yours. It’s been working great, but there is one more step. We forecast demand 6 months ahead, so the demand values for future months change each forecast. When the forecast data is updated, the Days of Supply of past months change because the calculation is using the most recent forcast data. I need to display a historical record of the days of supply calculated each month based on the forcast data we had at the time. How can I freeze the Days of Supply calculated for past months? I have added a column [Source] to identify in which month the data was forecast. I want to change this measure so it only uses the data from each individual forecast month to calculate Days for that forcast period. I've tried to do so by integrating calculate/filter functions into the measure, but keep running into errors. Here is my modified Measure:

     

    Days = 
    // Get the current Month and inventory for the current row
    VAR __week = MAX(Inventory[Month])
    VAR __inventory = MAX(Inventory[Ending on hand Inventory])
    // Create a table of all weeks greater than the current Month
    VAR __table = FILTER(ALL(Inventory),[Month]>__week)
    // Add our current inventory from above to each row
    VAR __table1 = ADDCOLUMNS(__table,"__start",__inventory)
    // Add a running total of demand to each row
    VAR __table2 = ADDCOLUMNS(__table1,"__demand",SUMX(FILTER(__table1,[Month]<=EARLIER([Month])),[Demand]))
    // Add the difference in start versus the running total of demand to each row
    VAR __table3 = ADDCOLUMNS(__table2,"__left",[__start] - [__demand])
    // Create a table that only has the positive rows
    VAR __table4 = FILTER(__table3,[__left]>=0)
    // With only the positive rows, the MIN is the last row before demand runs out
    VAR __min = MINX(__table4,[__left])
    // Therefore, our base days is the number of rows in this table * 30
    VAR __baseDays = COUNTROWS(__table4)*30
    // Grab the MAX value of the negative rows, this is the row right after our inventory runs out
    VAR __max = MAXX(FILTER(__table3,[__left]<0),[__left])
    // Divide the row right before the invetory ran out by the sum of the absolute values of right before and after 
    // the inventory ran out. This is the percentage of days in that week before inventory ran out. multiply this by 30
    // and this is the number of days in that Month before inventory ran out
    VAR __extraDays = __min / (__min + ABS(__max)) * 30
    RETURN
    __baseDays + __extraDays

    Let me know if you have any ideas. Thanks!

     

    Message 2 of 5
    12,029 Views
    0
    Reply
    JHOLT
    JHOLT
    New Member
    In response to Anonymous
    • Mark as New
    • Bookmark
    • Subscribe
    • Mute
    • Subscribe to RSS Feed
    • Permalink
    • Print
    • Report Inappropriate Content

    ‎03-30-2020 08:58 AM

    Hi @Anonymous, I am having problems to do exactly what you detailed - fixing the forecast 'version' to specific months so that the historical months are not modified by new forecast data. Were you able to find a solution?

    Message 3 of 5
    8,227 Views
    0
    Reply

    Power Platform

    • Overview
    • Power BI
    • Power Apps
    • Power Pages
    • Power Automate
    • Power Virtual Agents

    • Sign in
    • Sign up

    Browse

    • Solutions
    • Partners
    • Consulting Services

    Downloads

    • Power BI Desktop
    • Power BI Mobile
    • Power BI Report Server
    • See all downloads

    Learn

    • Guided learning
    • Documentation
    • Support
    • Community
    • Give feedback
    • Webinars
    • Developers
    • Blog
    • Newsletter

    © 2023 Microsoft

    Follow Power BI

    • Privacy & cookies
    • Manage cookies
    • Terms of use
    • Trademarks
    California Consumer Privacy Act (CCPA) Opt-Out Icon Your California Privacy Choices