Gantt Reworked with ADDCOLUMNS, FILTER, GENERATE and SUMMARIZE

September 5, 2012

Guest post by David Churchward [Twitter]

DAX Studio, ADDCOLUMNS, FILTER, GENERATE and SUMMARIZE

Gantt Hours measure debugging with DAX Studio – isn’t it pretty!

At the end of my last post in the Gantt Chart series, GANTT CHART WITH RESOURCE LOADING, I said that I would return to explain how the Hours measure worked.  I took a brief diversion, almost foray, into the world of CRM PIPELINE FUNNEL CHARTS but I’m now back to explain the workings of that Hours measure.  You can revisit PART1 and PART2 of this series to recap.

In the interim, I’ve been working on some “fine tuning” of that Hours measure.  I’ll come onto the final solution in due course, but I’ll work through the workings of the Hours measure as we left it initially to explain why it needed tuning up!

For those amongst you with an appreciation of SQL, you might think of this like creating a DAX Equivalent LEFT JOIN between tables with a BETWEEN thrown in for good measure.

Read the rest of this entry »


CRM Pipeline Funnel Chart (and something on Themes)

September 3, 2012

Guest post by David Churchward [Twitter]

Pipeline Funnel Chart in Excel PowerPivot

Pipeline Funnel Chart

For those of you waiting on the explanation of the SUMX / SUMMARIZE measure in GANTT POST 2, I have to put you on hold for a while longer.  Sorry.  In truth, I’m working through some performance aspects with that measure.

For now, I thought I would take the opportunity to expose the Pipeline Funnel Chart.  It’s really quite straight forward but it’s incredible how few people know that it’s available to everyone, doesn’t require any real manipulation and YES it’s a standard PowerPivot chart!

For those of you that want to dig straight in, YOU CAN DOWNLOAD THE WORKBOOK HERE

Read the rest of this entry »


Gantt Chart with Resource Loading

August 29, 2012

Guest post by David Churchward [Twitter]

Gantt Chart with Resource Loading Report

Gantt Chart with Resource Loading Report

The response to POST 1 of this Gantt Chart mini series was swift and it didn’t take long for Vegard to contact me with a query regarding resource loading.  Vegard had quickly taken the template and adapted it to include resource hours.  The issue existed with getting the total hours for each resource to behave the way he wanted.  Naturally, individuals will normally work for a set expected amount of time per day and if tasks are planned which exceed that expectation, it’s obvious that they might not get the work done!

In this post, I’ll start to explain how to adapt the model from the previous post to include resource loading and associated subtotals per individual resource.

Read the rest of this entry »


Gantt Chart in PowerPivot

August 28, 2012

Guest post by David Churchward [Twitter]

Gantt Chart in PowerPivot

Gantt Chart in PowerPivot, fully dynamic and sliceable!

It’s a rare diversion from the normal Financial stuff that I subject you to!  Having run numerous projects and found myself writing endless task lists in Excel so that I can distribute to other people, it suddenly occurred to me that PowerPivot can do this.

Not only can PowerPivot do Gantt Charts, I think it destroys other software in this game.  Sure, MS Project is always going to be there and I’m very fond of it, but, anyone familiar with this:

“Thanks for sending that through, but I don’t have MS Project.  Can you give me an Excel version or PDF”?”

Maybe you haven’t, but I find myself continuously confronted with distributing Excel task lists and producing my own Gantt charts in Excel to grab screenshots for presentations.  PowerPivot gives me (and you) the means to monitor and update tasks quickly and easily, but it also gives you the means to distribute via Sharepoint – awesome!

If you want to just get on with it, GRAB THE FILE HERE and start using it.  There’s some brief instructions on how to use it in the file.  Otherwise, read on …

Read the rest of this entry »


Tiered Commissions, Income Taxes, and other “Tiered Rate” Calculations in PowerPivot

July 23, 2012

Guest post by David Churchward [Twitter]

Commissions Part 3 Report

I mentioned in my LAST POST that I would return with a variation on that commission calculation.  Two months later and very much overdue, here it is!  Apologies to those of you who have been waiting on me for this.

I left off with a calculation that applied a commission rate based on a rates table.  That rate was applied to the total value.

But what about a scheme where one rate applies to the first N dollars (or pounds, euros, etc.), then another rate applies for the next M dollars, and so on?  Income taxes are calculated this way, for instance.  And being able to solve this sort of thing in Excel very efficiently (using PowerPivot) will be generally quite useful.

In this post, I’ll explain how to do this in a model that I refer to as Base Plus.  And while I will discuss this purely in the context of tiered commissions, keep in mind that it applies to taxes and many other things as well.

Read the rest of this entry »


Commission Calculations in PowerPivot Part 2

May 15, 2012

Guest post by David Churchward [Twitter]

Team and Manager Commissions Report

You may recall in my last post, COMMISSION CALCULATIONS IN POWERPIVOT, we got to the point where we could dynamically calculate the sales value and attributable commission rate that should be applied based on time, value and team parameters, reading from a Rates table.

In this post, we’ll complete the commission calculation, providing a different value for individuals and the team manager.

Where are we?

Just to recap, we got to the point in my last post where we had calculated [Sales_Value] and [Comm_Rate] as below:

Read the rest of this entry »


Commission Calculations in PowerPivot

May 9, 2012

Guest post by David Churchward [Twitter]

Commissions Report

Firstly, I have to be clear that I’m not presenting a “one-size-fits-all” approach to sales commission calculations here.  That wouldn’t be possible because commission schemes vary extensively and, in my experience, some schemes aren’t even based on a logic that can derive a mathematical answer!  However, I’m presenting an approach here that will hopefully provide a template approach that can be modified to a number of different scenarios.

The Target Outcome

The scheme that I’m using in this example operates as follows:

  1. Commission is paid monthly based on the achievement in that month
  2. As a salesperson sells more, then accelerators trigger.  That is to say, for example, a salesperson may receive 1% of sales up to £10,000 and 2% of sales between £10,000 and £20,000.  The 2% is payable on the whole value.  Therefore, if a salesperson sells £11,000 then they would receive 2% of the full £11,000
  3. Percentages and bands can change monthly at management discretion
  4. This is a monthly threshold so each salesperson is reset to zero at the start of each month.
  5. Each product group carries a separate set of bands and rates
  6. Managers receive commission at a different rate to the sales team based on the total sales for their team.

Read the rest of this entry »


Aged Debtors–Dynamic Banding in DAX

April 17, 2012

Guest post by David Churchward [Twitter]

Aged Debtors Report

Having hit the P&L and Cash Flow in previous posts, it seems only reasonable to move on to Balance Sheet aspects.  The die-hard “non-accountant” Excel Pros and programmers amongst you are probably experiencing a sudden bout of Narcolepsy, but let me assure you that this gives us the perfect opportunity to explore dynamic banding in DAX so please prop those matchsticks in place for the minute!

In this post, I’ll construct a dynamic Aged Debtors report.  This will calculate debt ageing values, showing outstanding debts by customer at user defined points in time.

The Accounting Terminology Bit

Let’s get this done quickly.  Debtors are those customers (normally) who owe the company money.  This is often legitimate as it is normal to offer a customer a period of time to process your invoice and pay.  However, it’s not unusual for this period to extend for a number of reasons.  I won’t go into this now because I could waffle on too long with experiences in this area and I’ve never even worked in Credit Control!

In short, an aged debtor report details all outstanding debts, by customer, categorised into timeframe buckets to show how old the debt is.

Historically, it wasn’t unusual for an aged debtor report to be something that could only be run as at “now”.  This means that accountants everywhere had a tiny window of opportunity to capture this information and preserve it in their archives with a wealth of information lost in hidden folders everywhere.  PowerPivot gives us the opportunity to derive a report that holds all of this information with historical ageing available based on user selection and the ability to profile customers to see who tends to take their time to pay and maybe highlight some reasons why.

The Dataset

The transaction process probably looks something like this:

  1. Invoice is created at a point in time
  2. Payment is received from the customer and a payment transaction is created
  3. Payment is “allocated” to the invoice

Allocations Fact Table

Aged Debtors Allocations Fact Table

My core table here is an Allocations table.  This table details all relevant transactions including invoices (and credit notes), payments and allocations.  These transactions might look like this:

Aged Debtors Invoice

An invoice is raised for £10k on 15th March 2012 with an invoice reference (or invoice number if you like) of 1100.

Aged Debtors Payment

Payment is received one month later with a reference of PAY1

Aged Debtors Allocation

The invoice and payment are allocated against each other meaning that the system has linked the payment PAY1 with the invoice 1100 and the outstanding debt is therefore zero and the payment is fully cleared down.

Customers Table

My customers table simply holds customer code and name, but it might hold other information about the customer such as customer contact and credit limit information.  Unfortunately, I can’t display this table here as it holds real customer information and a scrambled name that I ultimately show on this report…sorry! (it sort of defeats the object if I give that away in a screenshot!!)

Bands Table

Outstanding debts need to be categorised into distinct bands.  This is normally representative of months, but it can be anything.  I’ve created a linked table in Excel which provides a Name together with From and To parameters.  For example, 0-30 represents debts that are 0 (From) to 30 (To) days old.

Aged Debtors Bands Table

Dates Tables

I use 2 dates tables.  One is to link the allocation date to and the other is linked to the invoice date.  I’m using V1 for this so I need both tables, but in V2 you can hold one dates table and then use the V2 function USERELATIONSHIP to determine which field to link through to the Dates table on.

These tables are simply a list of sequential dates covering the timeframe of my analysis.  The invoice dates table holds an additional column called Month_End_Date simply to use as a logical slicer to put on my report.

Table Relationships

My relationships look like this:

Aged Debtors Relationships

You’ll notice that the Alloc_Fact table links through to Customers and both of the Dates tables but there is NO relationship to Bands.  Bands is a stand alone table that is used for report headings and parameters without any defined relationship.

Onto the DAX

My report is going to hold a slicer for Month_End_Date.  This is an “effective” run date.  That is to say that the user is going to select a time point up to which transactions and allocations will be included, but any transactions after those dates should be ignored.

Therefore, I create a measure called Debtor_Value which aggregates underlying transactions and allocations up to that date.

Debtor_Value

=CALCULATE(

SUM(Alloc_Fact[Value]),

FILTER(ALL(Alloc_Dates),

COUNTROWS

(

FILTER(Alloc_Dates,

EARLIER(Alloc_Dates[Month_End_Date])<=MAX(Alloc_Dates[Month_End_Date]))

)>0

  )

)

This measure uses a FILTER() on the Alloc_Dates table using COUNTROWS() to specify those dates that fit a criteria of being prior to the date selected on the slicer.

Why use FILTER() and COUNTROWS()?

It’s a reasonable question to ask why I can’t use a simple Month_End_Date filter as opposed to using FILTER() and COUNTROWS().  I have to hold my hands up and put a call out to Rob and The Italians for a technical reason, but in my mind, I know that I’m using the same field (Month_End_Date) in the evaluation, once from the slicer and once from my row set.  To define between the two, I need to use EARLIER() to reference my row set and MAX to call the value from my slicer.  To do so, I have to use a filter context that creates a table expression to identify all of the dates that ARE to be used in my measure.

Incidentally, if you want more on EARLIER(), Rob’s Rat Analytics sums it up.

Thanks to Alberto Ferrari here as this filter expression is something I picked up from him on the Mr Excel forum.

Aged Debtors UnAged

Irrespective of the technical explanation, I know that these values are correct, but the allocations to specific ageing buckets is obviously NOT.

Ageing Debtors

In order to allocate invoices to the correct ageing buckets, we need to calculate how old the invoice is and then calculate which bucket this relates to.  The age of the invoice has to reference the selected Month_End_Date.

Aged_Debtor

=IF(COUNTROWS(Bands)=1,

CALCULATE([Debtor_Value],

FILTER(Inv_Dates,

MAXX(Inv_Dates,

MAX(Alloc_Dates[Month_End_Date])-EARLIER(Inv_Dates[Date])

)>=MAX(Bands[From])

&&MAXX(Inv_Dates,

MAX(Alloc_Dates[Month_End_Date])-EARLIER(Inv_Dates[Date])

)<=MAX(Bands[To])

)

),

[Debtor_Value]

    )

The COUNTROWS() evaluation determines that we have one band to work with.  This eliminates any confusion over the aggregation level that we’re working at and ensures that we will get one result for the FROM and TO elements of the band.

CALCULATE() then takes over to use our previous measure [Debtor_Value] within a filter context that determines the invoices (or rather invoice dates) to use.

The FILTER() element of this expression is where things get tricky.  If I’m honest, in the first iteration of this measure, I tried to filter invoices.  My rationale was that each invoice carried a specific date.  From this date, I could determine how old the invoice was at any given point in time.  And, you’ll be pleased to know that it worked.  But there was a problem!  Because I’m carrying over 300,000 invoices in my dataset (which isn’t actually that many), any SUMX or MAXX is going to iterate over 300,000 records and therefore may not be very quick.  In addition, as my invoice count increases, so my performance is going to continue to degrade.

In an enlightened moment, I realised that I only had roughly 1,500 dates and the number of dates increases at a much slower rate than the number of invoices.  Could I use the same approach purely on dates and ignore the invoice number?  Ehhh………YES!

Essentially, MAXX is iterating over the table Inv_Dates and working out if the difference, in days, between the selected Month_End_Date on the slicer and Inv_Dates[Date] is greater than or equal to the Bands[From] AND also less than or equal to the Bands[To].  Where this is the case, this measure uses the value from [Debtor_Value] subject to the FILTER().  Where this is NOT the case, the measure uses the value from [Debtor_Value] but DOESN’T apply the FILTER() expression.

And, there you have it!

Aged Debtors Report

What’s Next

With these measures in place, wouldn’t it be great to mash this up with an invoicing profile and maybe even a dissection by product or industry sector to give a true profile on a customer?  I’ll be back with a load of mashups on this as soon as I can.

Incidentally, as I alluded to earlier, this analysis is a real dataset so I unfortunately can’t release the Excel.  Sorry.


My Experiences with Hosted PowerPivot, Part One

February 21, 2012

Guest post by David Churchward

Pivotstream Dashboard Application

One of Azzurri Communications Ltd’s PowerPivot
Applications Running in the Browser

Six Months Ago:  The “Lightbulb” Moment

Almost exactly six months ago, after being a long time reader of this blog, I emailed Rob and asked him a question regarding something that I just couldn’t get my head around in DAX – Banding!  He kindly responded, and his answer solved my problem, so I asked him if I could return the favour somehow.  He asked if I’d mind writing it up as a guest post, which I did.

Now, double-digit guest posts later, I’m amazed at how far I’ve come in short order.  Something definitely “clicked” for me that day, and my grasp of PowerPivot’s capabilities expanded rapidly.  It felt like that moment that I imagine Pianists reach where they can suddenly play by ear, because whilst I could conquer most things in DAX, it didn’t seem to quite “flow” – until that day!

Up until that point I had viewed PowerPivot as a “private” tool – something that was useful for me in my work, a supplement to other tools and methods.  But starting six months ago, I started to understand that PowerPivot could, and SHOULD, be used to improve or replace most of our existing Business Intelligence and Analytics tools.

Step One:  Azzurri Deploys its First “On Premise” SharePoint Server

At Azzurri, I am fortunate to enjoy two critical flavours of support:

  1. Our executive team is open-minded to progressive ways of doing things (so long as there is a solid value proposition).
  2. My tech team is a crack outfit who will bring me the moon if I ask for it, but tend to make reasonable alternative suggestions such as building data warehouses.

In other words, Azzurri is the perfect sort of place to deploy PowerPivot for SharePoint, bordering on a textbook example.  There aren’t many companies of Azzurri’s size where I could explain the benefits of a PowerPivot server, win people over, and have a server deployed two weeks later.  But that is precisely what happened Smile

Step Two:  Start Emailing Rob Again Smile

We didn’t just deploy the server, we immediately began USING it for serious work.  And that led to questions – questions about performance.  Questions about hardware.  Questions about customisation.  Questions about refresh.  Questions about “core and thin” workbooks.

Rob and I had a friendly correspondence going at that point, so I started sending those questions over.  I even looped him into email chains with our tech team, and we talked through a number of issues and optimisations.

Step Three:  Try Out Hosted PowerPivot in Parallel

Everything I do in Systems Development, especially with my Finance background, is about Cost V Benefit, ROI, IRR and payback.  With this in mind, I started wondering whether it made sense for us to develop PowerPivot for SharePoint expertise of our own.

We had originally decided to go with our own SharePoint deployment because we had the required licences and a particularly clever team who I had every faith could deliver.  This seemed obvious as SharePoint was already in operation at Azzurri.  My initial view was that it must be relatively straight forward to bring all of the BI tools into the equation.

Two weeks into the process, however, I was already seeing that things might not be as straight forward as I had first hoped.  Performance was the first major barrier that I hit and I couldn’t be entirely sure what kind of investment in hardware might be required to alleviate this.  Out of nowhere, PowerPivot gallery started playing games which turned out to be an IE9 issue and then I was introduced to Kerberos which, it turns out, isn’t a breakfast cereal that I was yet to encounter!

I knew about the Pivotstream Hosted Solution of course, and I still wasn’t ready to commit to hosting, but I decided that running a trial in parallel made a lot of sense, especially since I was particularly aware that my tech team needed to be doing other things.

I’m very glad that we decided on a trial, because step four was to switch over full-time.

Goodbye “Do it Yourself”, Hello SaaS

The journey I’ve been on as a customer of Pivotstream has validated for me that the SaaS model together with the capability of PowerPivot makes for a more compelling business solution for reporting and BI than any alternative that I can find.

I’ve been particularly conscious of making sure that my tech team spend their time where they can really drive business value – building Data Warehouses, ETL and efficient business processes.  It was clear that time spent developing SharePoint Server was time not spent adding value elsewhere.  There’s no doubt in my mind that they would have delivered, but I knew that they could deliver more value elsewhere to more than offset any cost of hosting.

Summary of Our Experience

Once I had taken the decision to try out Pivotstream’s hosted solution, it became clear that “elapsed time” taken was no longer going to be a constraint to the project.  On that same day, Azzurri had it’s own Pivotstream site in full working order with admin and consumer accounts setup for the trial.  It was now down to me to start making this a fully functional dashboard.

Naturally, I had workbooks at the ready and I loaded a few up immediately.  I started sniffing some of the additional features that I could now start playing with.  Before I knew it, I was canvassing Pivotstream for direction on Query String URL filtering (an awesome attribute to drill across to other dashboards).  A handy guidance document found it’s way into my inbox and I was away.

I was supplied with a program to split core and thin workbooks, another gem that just saves time and aggravation.  I served up a query with web part layouts and, next day, I get a new page layout deployed straight to our site.

Immediately, the focus of what I was delivering was about end user usability as opposed to finding ways around potential (and in some cases very evident) performance issues.  Performance was immediately apparent on the Pivotstream solution, as could be immediately seen by some of my more “chunky” analysis that didn’t even make it flinch.  My in-house SharePoint Server could take upwards of a minute to open these workbooks whereas the hosted solution barely registers seconds.

Within a matter of days, I realised that the limits of this solution only existed to the extent of the limits of my imagination in creating dashboards.  All of a sudden, my focus was turned on making sure that full value was derived and, to that end, I started spreading the word within Azzurri.  Some initial training took place and I immediately recognised that these clever individuals that I was working with had even more insight bursting to get out and the fact that we were playing in Excel meant that they could immediately relate to what they were being shown.  I had hit that fantastic point in the project where momentum starts taking over and this is probably less than two weeks after starting the trial.

Speed (both of implementation and application), elimination of complexity and additional value adding applications delivered in a scalable data-centre model with an OPEX cost model sums it up for me.  Now, it’s just about making the dashboards deliver the real benefit to the business – insight!

As I’ve been writing this, Rob’s reminded me of a comment I made back towards when this whole thing started:

“My key driver is laziness so I’m always looking for quicker and better ways to do things. In doing so, I find myself working non-stop so I may have my driver wrong or I’m failing miserably!”

The reality is that Hosted PowerPivot does do it quicker and better.  I’m working non-stop because the results speak for themselves and I fundamentally “get it”.  The reality is that my driver was wrong!


Prepayments & Deferred Revenue

January 24, 2012

 

Guest Post by David Churchward 

Prepayments & Deferred Revenue Layout Example

You’ll often hear us Accountants referring to things like adjusting for timing differences or prepaying costs or deferring revenue.  This is often interpreted as “massaging the numbers”, but, believe me, there is a very reasonable theory behind it.  These sort of adjustments can be made for a number of reasons, but the main underlying concept is that adjustments have to be made to ensure that the transaction is reflected in the period to which it relates.

In this post, I’ll explain how prepayments and revenue deferrals work together with the DAX measures that drive these calculations.

What are Timing Differences?

It’s worthwhile just taking the time to understand what we’re trying to do here.  Take, for example, a support contract that you bill to your customer in advance for 12 months.  You invoice the customer in advance and the customer duly pays.  However, as per accounting principles, you have to reflect the fact that the invoice relates to 12 months worth of support.  In it’s simplest sense, your Profit and Loss should therefore see 1/12th of that revenue in each reporting month.  Since the invoice is for a full 12 months, we have to create transactions to defer the element that relates to future periods, entering the balance onto the Balance Sheet.

As a quick example of the calculation, at the end of the first month to which the support contract relates, you would defer 11/12ths of the invoice value:

Deferral Value = Invoice Value * (Number of Future Months / Total Months on Invoice)

We would therefore see 1/12th of the invoice value on our Profit & Loss and the remaining 11/12ths would be sat on our balance sheet.

Referring to Prepayments separately from Deferred Revenue (or Deferred Costs) for that matter is simply a matter of terminology.  The underlying concept of the calculation is the same.  I consider everything to be a Prepayment in this sense.  The only difference is where the transactions sit in the Profit & Loss and Balance Sheet statements.

Note – Accountants may defer revenue or costs for other reasons.  This post is simply a calculation to reflect the timing difference adjustment.

Days or Months

In the simplified example above, I’ve used a monthly concept that allows for a simple allocation of the transaction value to the Profit & Loss in equal monthly values.  However, as we know, the number of days in each month can differ.  For this calculation to be more accurate, we should pro-rata the calculation based on the number of days in that month.

The DAX measures that I show in this post will allow for selection of Monthly Deferral / Prepay or Daily Deferral / Prepay.  Which you use depends on your accounting policy.

Data Structure

My data structure is as follows:

Fact Table (Prepayments)

I have a core fact table which contains all transactions that require a prepayment or deferred revenue adjustment.  I have called this table Prepayments.

Prepayments Fact Table

The key elements to this table are as follows:

Date – This is the transaction date of the invoice posting

Nominal_PandL – This is the Profit & Loss Nominal Ledger account that the invoice was posted to

Nominal_Prepay_BS – This is the Balance Sheet Nominal Ledger account where the prepayment or deferral will be posted to.

Start / End – These are the start and end dates of the transaction.  If the invoice relates to a period from 1st Jan 2012 to 31st Dec 2012 then these dates would be 01/01/2012 and 31/12/2012 respectively.

Method – This is either MONTH or DAY depending on the level of granularity that you want your calculation to be calculated at.

PandL_Values – This is the total value of the invoice charge.

Prepay_Start / Prepay_End – I’ll come onto these alternative dates shortly.  In brief, these exist because your prepayment timeframe may differ from the strict dates to which the invoice relates.

Days Table

Prepayments Days Table

This table holds a sequential, unbroken list of dates (Date) together with associated attributes including Month End Date, Previous Month End Date, Month Start Date and Next Month Start Date.  These attributes become relevant in our measures and, whilst these can be calculated at run time, it’s easier to take care of them this way.  The purest would be correct in suggesting that there’s a potential performance impact, but dealing with these aspects in our measure may confuse the issue for now!

Months Table

Prepayments Months Table

Similar to the Days table, this table holds a collection of attributes relevant at the month level including Month End Date, Previous Month End Date, Month Start Date and Next Month Start Date.

Start Dates Table

Prepayments Start Dates Table

This is another sequential list of dates which is joined to the Start field on the Prepayments table.  I’ll come on to the PrepayStartdate field shortly.

End Dates Table

Prepayments End Dates Table

This is another sequential list of dates which is joined to the End field on the Prepayments table.  You’ll notice the absence of a third field which, again, I’ll come on to.

Table Relationships

Prepayments Table Relationships

The only relationships that exist are between the Prepayments table and the Start_Dates and End_Dates tables.

Dates That Span Periods

A charge period can be anything.  In it’s simplest form, it would be for complete months starting on the first day of a month and ending on the last day of a month.  However, things are never that simple.  Unfortunately, you could get a charge that is for 3 months from 14th Jan 2012 to 13th Apr 2012 as an example.  The time between these two dates is indeed 3 months, but the charge covers 4 discrete calendar months.

If you’re using a Days method of apportionment, this isn’t a problem.  However, if you’re apportioning on the basis of months, you have 3 options in this example:

  1. Take the 3 equal months charges as Feb, Mar and Apr
  2. Take the 3 equal months charges as Jan, Feb and Mar
  3. Take equal monthly charges for Feb and Mar with a pro-rata charge for Jan and Apr.

In truth, if you’re going to even attempt option 3, you would probably be better off jumping straight for the Days apportionment and circumvent the problem!  Options 1 and 2 depend on accounting policy and president.  The prudent option would probably be to go for option 2 for costs (taking them as early as possible) and option 1 for Revenue (taking later rather than earlier).  On the basis of consistency, I feel it’s best to prescribe this in your accounting policies and then use the same method for everything.  Having said that, the best option is almost certainly to take a Days approach.

For the purpose of this post, I’m going to use option 1.  This means that I’ll translate any start date that isn’t the first day of the month to the first day of next month.  I create two calculated fields on my Prepayments table as follows:

Prepay_Start

=IF(Prepayments[Method]=”MONTH”,RELATED(Start_Dates[PrepayStartdate]),Prepayments[Start])

 

Prepay_End

=IF(Prepayments[Method]=”MONTH”,RELATED(End_Dates[MonthEndDate]),Prepayments[End])

These measures retrieve an alternative date from the Start_Dates and End_Dates table.  For any mid-month dates, this table holds a PrepayStartdate of the first of the next month.

The Months Approach

Firstly, let’s just remember our simplified equation to give us the deferral value:

Deferral Value = Invoice Value * (Number of Future Months / Total Months on Invoice)

And now we’ll jump straight into the DAX

Month_Prepayment

=IF(COUNTROWS(VALUES(Months[MonthEndDate]))=1,

IF(LASTDATE(VALUES(Prepayments[Prepay_Start]))<LASTDATE(VALUES(Months[MonthEndDate]))

&&LASTDATE(VALUES(Prepayments[Prepay_End]))>LASTDATE(VALUES(Months[MonthEndDate])),

CALCULATE(

SUMX(Prepayments,

Prepayments[PandL_Value]

*(

(CALCULATE(COUNTROWS(Months),

DATESBETWEEN(

Months[MonthEndDate],

LASTDATE(VALUES(Months[MonthEndDate])),

LASTDATE(End_Dates[MonthEndDate])

         )

       )-1

     )/

CALCULATE(COUNTROWS(Months),

DATESBETWEEN(

Months[MonthEndDate],

LASTDATE(Start_Dates[PrepayStartdate]),

LASTDATE(End_Dates[MonthEndDate])

         )

   )

  )

),

Prepayments[Method]=”Month”

    )

)

)

The first two IF statements in this measure calculate when we want the rest of the measure to evaluate.  We want this measure to evaluate when:

  1. The number of month end dates on our report is 1 (because anything else is likely to return an error)
  2. The prepayment start and end dates fit within the range of our report.  This, essentially, tells the report which month end dates to display and the rest of the measure uses these dates to evaluate the correct result to display.

We then use a CALCULATE statement to calculate our basic equation:

Deferral Value = Invoice Value * (Number of Future Months / Total Months on Invoice)

Invoice Value = SUMX(Prepayments,Prepayments[PandL_Value]

Number of Future Months =

*(

(CALCULATE(COUNTROWS(Months),

DATESBETWEEN(

Months[MonthEndDate],

LASTDATE(VALUES(Months[MonthEndDate])),

LASTDATE(End_Dates[MonthEndDate])

         )

       )-1

    )

 

This calculates the number of month values in the Months table using the COUNTROWS function that sit between the MonthEndDate on our report and the MonthEndDate of the end date of our transaction.  I then subtract 1 to reflect that the MonthEndDate of the report is not included as it is the current reporting month.

Total Months on Invoice =

/

CALCULATE(COUNTROWS(Months),

DATESBETWEEN(

Months[MonthEndDate],

LASTDATE(Start_Dates[PrepayStartdate]),

LASTDATE(End_Dates[MonthEndDate])

         )

   )

Once again, I’m counting the number of entries in the Months table that sit between the start and end dates of our prepayment timeframe.

I then apply a filter to the CALCULATE statement to ensure that this measure is only applied to transactions where the Method is set to “MONTH”.

So why do we have to use SUMX for the Invoice Value?

The simple answer is that we need to conduct this equation at the transaction level of granularity and then SUM the results.  The main reason for this is that we’re using a division calculation which is only relevant at that level and becomes confused and meaningless when aggregated.

In order to show this, I’ll explain a simple example of converting USD to GBP with some theoretical exchange rates:

SUMX Example

What are the values for X and Y?  We obviously know that Y needs to be 150, being the sum of the two GBP values.  However, if we use SUM, we wouldn’t get that answer.  The answer that you would get depends on how you condition your measure but you wouldn’t get an answer of 150, it’s more likely to be 150/2=75 (where MAX is used in the equation) or 250/3.5=71.42 (where SUM is used) or 250/1.75=142.86 (where SUM and AVERAGE is used).  The correct value only comes about when you use SUMX which sums the underlying outcomes of the equation and evaluates at the granularity level of the table that you specify (in our case the base level fact table – Prepayments).

This is a very brief outline of a very complex and clever function.  In short, if you want to simply add the outcome of underlying equations, SUMX is the way to go.

It’s worth checking out one of my favourite ever posts to start getting to grips with SUMX – SUMX() – The 5 point palm exploding fxn technique.

The Days Approach

This uses the same methods and concepts as the Month approach.  The only difference is that we’re evaluating to the number of days in the relevant periods of time.

Days_Prepayment

=IF(COUNTROWS(VALUES(Months[MonthEndDate]))=1,

IF(LASTDATE(VALUES(Prepayments[Prepay_Start]))<LASTDATE(VALUES(Months[MonthEndDate]))

&&LASTDATE(VALUES(Prepayments[Prepay_End]))>LASTDATE(VALUES(Months[MonthEndDate])),

CALCULATE(

SUMX(Prepayments,

Prepayments[PandL_Value]

*(

(CALCULATE(COUNTROWS(Days),

DATESBETWEEN(

Days[Date],

LASTDATE(VALUES(Months[MonthEndDate])),

Prepayments[Prepay_End])

                    )-1

  )/

CALCULATE(COUNTROWS(Days),

DATESBETWEEN(

Days[Date],

Prepayments[Prepay_Start],

Prepayments[Prepay_End]

      )

             )

         )

      )

,Prepayments[Method]=”Day”

  )

       )

  )

Prepayments Total

We now have two measures to evaluate our Days Prepayments and our Months Prepayments.  We can bring these together in one measure as follows:

Prepayments_Total

=SUMX(Prepayments,[Month_Prepayment]+[Days_Prepayment])

Once again, I have to use SUMX to ensure that this measure sums the total of the underlying calculations.

Prepayments Without Values Not Prepaying

The “Values Not Prepaying”

So we’ve dealt with the reducing balances associated with Monthly and Daily Prepayments and Deferred Revenues.  However, what about a situation where the invoice charge relates to future months that haven’t yet been reached?  For example, we receive an invoice in January that relates to April and beyond, as in the screen shot above where the last entry has a transaction date of 10th Jan but relates to a period April to October.  In this instance, we have to prepay (or defer) the full amount of the invoice for January, February, March and April.

Value_Not_Prepaying

=CALCULATE

(

SUMX(Prepayments,

Prepayments[PandL_Value]

),

FILTER(Prepayments,

Prepayments[Date]<LASTDATE(VALUES(Months[MonthEndDate]))

            ),

FILTER(Prepayments,

Prepayments[Prepay_Start]>LASTDATE(VALUES(Months[MonthEndDate]))

  )

   )

In this measure, we once again use SUMX to ensure that we SUM the outcome of the underlying evaluations.  However, we apply two filters to limit the selection to situations where certain criteria hold.  This is an alternative to preceding the CALCULATE with an IF statement to conduct this evaluation first.

  1. The first filter evaluates when transaction date is less than the MonthEndDate of the report column
  2. The second filter evaluates when the Prepay_Start date is greater than the MonthEndDate of the report column.

We then add this into our Prepayments_Total measure as:

Prepayments_Total

=SUMX(Prepayments,[Month_Prepayment]+[Days_Prepayment]+[Value_Not_Prepaying])

 

Prepayments Balance Sheet Layout

And there you have it.  Our Balance Sheet layout above shows the total value of each transaction that needs to be prepaid or deferred in each month.

What This Means to Accountants

For those Accountants amongst you, you’ll no doubt have cottoned onto the fact that, if you’re careful, this could be your prepayments and deferred revenue reconciliations conquered.  The process that I’ve always implemented is as follows:

  1. Ensure that all transactions are posted to the Profit and Loss in full, as if the P&L was going to take the whole value in one period.
  2. Capture prepayment start and end dates on each transaction
  3. Extract the data into a PowerPivot application such as this.
  4. Refresh to give you the values that need to be prepaid (as per the above screenshot)
  5. Journal the appropriate values between the Profit and Loss and Balance Sheet on a reversing journal.
  6. Next month the previous transaction will reverse and you do the same again.

By doing this, you’ve got a self reconciling Balance Sheet for Prepayments and Revenue Deferrals (and all transactions for that matter that have a straight line release – for example, you could use this for elements of Fixed Asset Depreciation but that’s a whole other post).

And One More Thing

You may have noticed in the first graphic that there was also a Profit & Loss impact section to the report.  I’ll come onto this in a future post but it uses similar concepts to the measures in this post.  With this in place, you’ve got elements of a forecast P&L, you’re on course for Recurring Revenue Assurance analysis and you’re putting in place the building blocks of a full Finance Business Intelligence Application that’s just dying to be exposed in SharePoint as per Rob’s post In the Browser Aesthetics Yield a Greater Return.


Switching Subtotals On & Off Dynamically Using DAX in PowerPivot

January 5, 2012

Guest Post by David Churchward

Cash Flow Statement With and Without Subtotals

Subtotals on or off for a field - They’re the options that you get.  That’s probably great for a lot of situations, but I would put money on the majority of readers of this post having had a situation where they’ve asked “where’s the option to not display a subtotal when there’s only one record being shown?”.  Frustrating isn’t it?  You end up with a load of subtotals simply repeating the same value as it’s own one subset member because one of your other report elements has a subset of data that does need subtotalling.  You can, of course, toggle the show and hide for each member, but wouldn’t it be better if it was dynamic?

Fortunately, DAX has the answer.  It’s not the answer that I would have hoped for because this one feels like it should be an option setting somewhere.  However, we can deliver the same functionality by writing it into our measures.

In this post, I’ll explain how to create a dynamic measure that works out whether a subtotal is needed and displays that subtotal accordingly.  I’ll be using the report that was created as part of the Cash Flow Statement post.

The Subtotal Issue

Let’s refer back to the final report that I created for the Cash Flow Statement.

Cash Flow Statement With Totals2

In the column CF3_Name, the only subtotal that I want to see is the one on Working Capital as this is the only one that has any lower level detail.  You’ll notice that all other areas are carrying subtotals  which only serves to repeat the number above it.

COUNTROWS and COUNTX

In order to solve this problem, you obviously need to know how many subset elements there are that would make up your subtotal.  It would be reasonable to jump straight for COUNTROWS.  Let’s examine that quickly with a measure that we’ll call CF4_Headings_No in the hope that it will tell us how many headings are in our subset.

CF4_Headings_No

= COUNTROWS(VALUES(CF4[CF4]))

COUNTROWS Separate Tables

On the face of it, that doesn’t appear to give us what we want.  We have the same results for all headings and CF4_Name repeats all of the same headings.  The reason that this happens is because CF3_Name and CF4_Name are held on separate tables.  Although they hold relationships to the same table, PowerPivot doesn’t pre-determine which combinations of these fields exist, even at run-time.

So let’s look at what happens when these headings are held on the same table with the same COUNTROWS formula (but obviously changing table name etc!).

COUNTROWS Same Table

That looks better right?  We can see all of the correct combinations of CF3_Name and CF4_Name.  On the one hand, this is good because we can distinguish the fact that Working Capital is the only element that has more than 1 subset item and therefore the only element that requires a subtotal.

However, there’s one big downside here.  For all other sections, we can’t distinguish between a subtotal line and a detail line.  There’s a couple more downsides here too:

  1. I have to create a table that holds all of the combinations of these headings.  This isn’t the biggest issue as I have a table called GL_Headings that holds the codes associated to these headings.  I can create a RELATED()measure in my PowerPivot dataset to return the heading name.  However, why bother if we don’t have to?
  2. Don’t underestimate the power of the function COUNTROWS(VALUES(TABLE[FIELD])) returning a value of 1 which happens when headings are held as a separate table.  This opens up a whole host of functionality and it’s probably one of the most important aspects of PowerPivot in my opinion.

So, what’s the final analysis of COUNTROWS

  1. Using COUNTROWS against a separate table with unique values for each heading gives us the means to distinguish between subtotal sections and detail sections of our report.
  2. Using COUNTROWS against a combined table with heading combinations tells us the CF3 headings that carry detail where we do want to see a subtotal.

I’m sure you’ve probably deduced where I’m going with this as the combination of these two elements probably tells us what we need to know to figure out whether a subtotal is required.  Unfortunately, this is not entirely true.  The problem is that the combination of these elements won’t operate in context unless the context is directly applied against the heading table (ie you put a slicer on the report for the cash flow heading elements).  What about a date slicer?  If you apply a date slicer which is a separate table, these measures won’t react.

Bring on COUNTX

Let’s jump straight into the DAX on this one and see what it’s doing by creating a measure called CF3_Total_Reqd.

CF3_Total_Reqd

=COUNTX(CF4,[Cash_Flow_Statement])

COUNTX is analysing our CF4 table in the context of our measure [Cash_Flow_Statement] (as calculated in the Cash Flow Statement post).  The context applied to [Cash_Flow_Statement] is carried across to our COUNTX formula.  We run this against our CF4 table because we want to get the number of detail heading names that carry a value in our [Cash_Flow_Statement] measure.

So what do we get:

COUNTX

Our CF3_Total_Reqd measure using COUNTX is telling us how many headings are used in our dataset for the MonthEndDate shown on our report.  This is exactly what we want.  What’s even more special is that if, in a particular month, our [Cash_Flow_Statement] measure only has one heading in the Working Capital section, the Working Capital Total would return a value of 1, which is a scenario when we want to switch our subtotal off.

But there’s a problem

Our COUNTX measure, as it stands, is returning a count where we have a heading, but it isn’t telling us when we have a valid blank entry at the CF4_Name level.  As a result, any CF3 category that doesn’t carry CF4 heading detail, isn’t telling us anything.  I know we have Operating Profit elements, but we’re not getting any counts returned.

But what if we specify the column that we’re analysing in our CF4 table?  We can do this by adding in VALUES and specifying the column in our CF4 table.

CF3_Total_Reqd

=COUNTX(VALUES(CF4[CF4_Name]),[Cash_Flow_Statement])

COUNTX With VALUES()

We have a result!  And our Working Capital section is behaving itself too!

And now for the Subtotal Switch On / Off Measure

Consider our two measures:

  1. CF3_Total_Reqd this tells us when a total is required ie CF3_Total_Reqd > 1
  2. CF3_Total_Reqd also tells us where detailed elements exist, ie returns a value of 1, but this measure does the same for those associated subtotals.  CF4_Headings_No, at the same time, helps us distinguish, generally and irrespective of context, between detail and subtotal levels on our report ie CF3_Total_Reqd = 1 AND CF4_Headings_No = 1

If we combine these elements, we get a measure that we’ll call Cash_Flow_Heading_Tidy

Cash_Flow_Heading_Tidy

=IF(

[CF3_Total_Reqd]>1||

([CF3_Total_Reqd]=1&&[CF4_Headings_No]=1),

[Cash_Flow_Statement],

BLANK()

)

Cash Flow Statement Major Subtotals

That gives us what we want, right?  Well not quite.  The Cash Flow From Operations section is now right.  However, the other sections in my CF2_Name column have reached the criteria for their totals to be eliminated.  If I don’t want this effect (and I don’t because this is a major total), I have to specify for my Cash_Flow_Heading_Tidy to directly include those totals.

Cash_Flow_Heading_Tidy

=IF([CF3_Total_Reqd]>1||

([CF3_Total_Reqd]=1&&[CF4_Headings_No]=1)||

COUNTROWS(VALUES(CF3[CF3_Name]))>1,

[Cash_Flow_Statement],

BLANK()

)

Cash Flow Statement Complete

There you have it.  All subtotals behaving properly.


Cash Flow Statement in PowerPivot

December 15, 2011

 

Guest Post by David Churchward

Cash Flow Statement

There’s few, if any, reports that I consider to be more important than the Cash Flow Statement.  Every business needs one, probably above any other report.  There’s numerous different versions of Cash Flow reports and, in reality, it can become a very personal thing to a company so I’m not going to propose to provide a one size fits all report.  In addition, I’m not going to proclaim to provide an IAS7 – Cash Flow Statement (that’s International Accounting Standards) textbook report because this isn’t designed as an accountancy lesson (but, if you’re interested, the method I’ll show here relates to the Indirect Method in IAS7).

With that said, if you consider this post alongside Kasper’s excellent post Building a cash flow statement in PowerPivot using Dynamic Measures in DAX, you should have all the tools you need to produce any Cash Flow Statement that you require.

The Accountancy Bit (very quickly!)

Just before we start, a quick accountancy point to consider.  Kasper’s approach considers cash payment and receipt transactions.  My model uses all transactions in the general ledger with the exception of Bank transactions.  On the basis that double entry exists (ie every transaction has an equal and opposite effect), all transactions that aren’t the bank transactions must equate to the same value.  The reason we use the “other” side of the account is because this side of the transaction tells us what the cash transaction was for.  As a result, we should simply be able to aggregate transactions into Cash Flow categories.

This seems quite straight forward.  Unfortunately, there are a few exceptions that need to be handled.  I’m only going to explain one which should give you the means to adjust for others.

Depreciation is purely an accounting adjustment.  This has the effect of crediting the balance sheet and debiting the P&L.  The effect of crediting the balance sheet has the effect of reducing the value that will be shown as Fixed Asset additions.  We therefore net off the depreciation transaction as if it never happened and I’ll show this later in this post.

The Dataset

My dataset (FACT table) contains 3 columns:

  1. GL_Account– this is my general ledger code.  Every transaction that forms the trial balance will carry a general ledger code and this tells us what the transaction was for.
  2. Month_End_Date – this date tells us the financial period to which the transaction relates.  I would advise using the month end date of the financial period in which the transaction will be reported as I’m doing in this example. (or a period number as in Rob’s Greatest Formula In The World posts).  It should be noted that a transaction date may not be in the same calendar period as the reporting date so care should be taken.
  3. Amount– this is the transaction value.  Using normal accounting signage, this will be a positive value for debits and a negative value for credits.

My dataset contains all transactions processed on the system – this is PowerPivot, it can handle it – and this essentially forms the basis of the trial balance.  If you have a lot of old data and don’t want to include it all, you could substitute historic data with opening balance values for each general ledger code.  This simply aggregates a lot of old transactions into one balance (per general ledger code) for an opening balance date, whilst maintaining the overall integrity of a balanced trial balance and the associated values.

You may have a dataset that holds monthly values for each general ledger code as opposed to each individual transaction.  This will work equally well although you won’t have the means to dissect the Cash Flow Statement by subset records such as customer or project.

If your data is held as monthly columns, it’s worth running an UNPIVOT.  Whilst we could condition PowerPivot to work with individual values for each period, it’s more efficient to work with one value column with associated period dates held in another column.

Related Tables

I link my my FACT table to a GL_ACCOUNTS table on the GL_Account code.  The GL_Accounts table provides details relating to the GL_Code such as account name and  report heading codes.  These heading codes, in turn, link through to a further GL_Headings table which holds cash flow report heading codes.  This, in turn, links through to cash flow heading tables.  It’s these headings that we will use on our Cash Flow Statement report.

Cash Flow Statement Dataset Schema

image

You’ll notice that CF1 doesn’t link to any other tables.  I’ll come onto that shortly.

General Ledger Account Mappings

The GL_Headings mapping is the critical element to this dataset.  This provides all of the key relationships between a general ledger code and the Cash Flow Statement report heading that you want the account to be represented under.

GL_Headings Table

image

My GL_Accounts map through to my Heading_Code on this GL_Headings table.  This table holds all of my key report headings and provides a useful grouping of accounts.  For instance, all general ledger codes that relate to Sales will carry a Heading_Code of 1010.

These definitions are important.  This is a one-off setup and you’ve probably done this indirectly in some way or another to drive any reports or Excel analysis that you’re currently doing (probably with VLOOKUP).  This process simply affirms that mapping.  Ideally, you would code these heading codes into your General Ledger account code setup and formulate the code allocation as part of the process to set up new general ledger accounts.

You’ll recall that I mentioned Depreciation earlier in this post.  Whilst this is a P&L account (heading code 1045 in this example), I’m coding this to exactly the same place as Fixed Assets on the Balance Sheet (heading code 2010).  This effectively eliminates the deprecation transactions.  An alternative would be to filter out the accounts in question.  You can do this, but be careful to ensure that those accounts net to zero.

Each of these codes map through to Cash Flow Statement heading tables.  These heading tables can be whatever you need them to be, with headings and ordering assigned however you want your final report to be represented.  The one’s I’m using are shown below.

CF2 – Cash Flow Statement Heading 2

image

This is my first grouping of headings.  These align with the IAS7 headings for CF2 codes 1, 2 and 3 and basically split my Cash Flow Statement between Operations Activities, Investing Activities and Financing Activities.

There’s a fourth section called Bank.  The Bank general ledger codes map through to this code and we eliminate them for the Cash Flow element of this report.  However, we bring them back into action when we display the Bank Balances at the end of the report.

CF3 – Cash Flow Statement Heading 3

image

This is the next level of granularity on my report.  The Bank general ledger codes don’t have any CF3 mapping and yet I’m carrying Opening and Closing Bank Balance codes on this heading set.  I’ll come onto why that is a bit later.  You’ll also notice that I’ve coded these headings with an Open_Bank  and Close_Bank flag.  We’ll use dynamic DAX measures later on to utilise these.

Note – there should NOT be any mapping of accounts to the CF3 codes 10 and 11 in this table (ie Open and Close Bank Balance).  We’ll use these simply to drive a DAX measure later.

CF4 – Cash Flow Statement Heading 4

image

One element of my Cash Flow Statement will carry a further breakdown – Working Capital (although you can have more if you want).  I’ve done this simply to provide an extra level of granularity, but you could decide to replace the Working Capital heading in CF3 with these headings and map accordingly.

I’ve got a few reasons for doing this:

  1. I like to show my Working Capital elements specifically – this targets the key operational balance sheet items that generally need to be tracked
  2. This helps to line up a future post!

CF1 – Cash Flow Statement Heading 1

You might, quite rightly, question why my ordering has gone to pot and I’m explaining CF1 last!  Quite simply, this table sits out on it’s own because it simply drives report sections as opposed to being a mapped heading code.  I’m going to show a Cash Flow section and then, below that, I’m going to show the effect on the bank balance.  No relationships required.

image

And Now for the DAX – Cash Flow

I’ve got to be honest, this measure isn’t going to set the world alight.  However, this goes to show how easy PowerPivot can be, especially if you condition your data properly.  I’m creating a measure aptly called Cash_Flow

Cash_Flow

=CALCULATE(

SUM(FACT[Amount]),

CF2[CF2_Name]<>”BANK”

       )*-1

This is a simple CALCULATE function which sums the [Amount] field on the FACT table with a simple filter set to ignore any GL_Accounts that have a CF2 category mapping of “BANK”.

You’ll notice that I multiply this by –1 to reverse the signage.  In simple terms this is because of the double entry effect.  We’re using the “other” side of the transaction which means that the sign convention is going to be back to front.  This simply reverses that effect.

When I pull this measure onto my report together with the CF1,2,3,4 heading names, I get the following.

Cash Flow in Excel - PowerPivot Turns Complex into Simple

You might say that this is job done (especially if you remove CF1 heading from the report). This does give us a Cash Flow Statement. However, this doesn’t give my bank balances and, if I include my CF1 heading, my report is repeating the same data for both of the CF1_Name headings. This is understandable as CF1 is not linked to my FACT table in anyway.  This is intentional (believe it or not!).

Bank Balances

I want to show opening and closing bank balances for the Bank section of my report and this is where it gets a bit more interesting.  Let’s create a measure that calculates these balances and let’s call this measure Bank…

Bank

=IF(COUNTROWS(VALUES(CF3[CF3]))=1,

IF(VALUES(CF3[Close_Bank])=1,

CALCULATE(

SUM(FACT[Amount]),

ALL(CF3),

CF2[CF2_Name]=”BANK”,

FILTER(

ALL(Month_End_Dates[MonthEndDate]),

Month_End_Dates[MonthEndDate]<=

MAX(Month_End_Dates[MonthEndDate])

            )

          ),

IF(VALUES(CF3[Open_Bank])=1,

CALCULATE(

SUM(FACT[Amount]),

ALL(CF3),

CF2[CF2_Name]=”BANK”,

FILTER(

ALL(Month_End_Dates[MonthEndDate]),

Month_End_Dates[MonthEndDate]<=

EOMONTH(MAX(Month_End_Dates[MonthEndDate]),-1)

  )

),

BLANK()

   )

    )

      )

We should be offering prizes for those of you would can instantly spot the GFITW elements!!  Anyone would think that this had somehow been contrived!  Believe me – it hasn’t.  This is a concept that I use regularly and it’s a joy to see Rob explain it so well so I don’t have to!

So what is this doing?  I’ll explain as clearly as I can, but it’s worth paying very close attention to Rob’s Greatest Formula In The World posts.  I won’t re-iterate too much here.

  1. The first IF statement simply serves to provide an answer as to where I want the measure to be evaluated.  I want an answer when my CF3_Heading is flagged as Open_Bank or Close_Bank.
  2. The second IF statement creates a value when my CF3_Heading [Close_Bank] is flagged.  Where this is the case, the following happens:
    1. Sum the [Amount] Field
    2. Expand my dataset to all CF3 headings in order to release the dependency on the current CF3 heading being evaluated – ALL(CF3)
    3. Apply a filter to include all of my Bank general ledger codes – CF2[CF3_Name]=”BANK”
    4. Apply a further filter (FILTER) that:
      1. Removes the dependency on the MonthEndDate – ALL(Month_End_Dates[MonthEndDate])
      2. Apply a filter that includes all months that pre-date and include the reporting month – Month_End_Dates[MonthEndDate]<=MAX(Month_End_Dates[MonthEndDate]) – this is important because the transaction base for the month won’t give us the balance.  We need to include ALL transactions that pre-date and include the reporting date.
  3. The third IF statement has a similar effect to the second IF statement, but it produces an opening balance and therefore the current reporting month has to be ignored.  As a result, I want to sum all transactions where the date is less than or equal to my prior month date – Month_End_Dates[MonthEndDate]<=EOMONTH(MAX(Month_End_Dates[MonthEndDate]) ,-1)

Cash Flow in Excel with Bank Balances Thanks to PowerPivot

Once again, we have the correct results but we’re getting values repeated for both CF1 headings.

Sorting Those CF1 Headings

We now have our two base measures.  All we now need to do is evaluate when to use each one.  Let’s create another measure called Cash_Flow_Statement.

Cash_Flow_Statement

=IF(COUNTROWS(VALUES(CF1[CF1]))=1,

IF(VALUES(CF1[CF1])=1,

[Cash_Flow],

[Bank]

   )

)

This measure simply evaluates for CF1 headings and determines that if my CF1 Heading Code is 1 (ie Cash Flow) then use my [Cash_Flow] measure.  Otherwise, use my [BANK] measure.

Cash Flow Finished

A bit of formatting and there you have it.  You’re just about done.  Or rather, you’re done if you think that’s enough.  I, however, don’t like some of these totals and duplication of values in certain areas.  There’s a way to deal with those totals but that’s a topic for a future post.

So what else can we do with this?

Just as a taster, here’s something that I like to call a Cash Flow Bridge.  This could be a topic for a future post, but just to whet your appetite……

Cash Flow Statement Bridge

If there’s enough call for this, I’ll get this scheduled in for a future post.  Neat eh!