cellMatrix.net
Spreadsheet Modeling and Related Topics

About

Formulas, Charts, and Models Created with Microsoft Excel.
More . . .

Statistics

  • Total Entries - 102
  • Current Viewers - 13

Categories

Recent Comments

Syndicate

Validate

Comparing Revenue Growth - Gross vs. Net

Gross revenue can be simply defined as charges billed. Net revenue, on the other hand, is more reflective of the revenue you expect to actually receive. In a healthcare environment, the spread between gross and net revenue can be fairly significant depending on who pays the bill.

A bar chart provides a simple visual comparison of gross vs. net revenue. Although the stacked bar chart initially seemed like the best choice to me, over time I've found that a regular bar chart with the bar overlap set to 100% works well too.

In this example, the goal is to chart the change in gross and net revenue in the Commercial / Contract and Government areas for the annual periods 2006 and 2007. Below is how I've set up the data:

image

The Chart Wizard produces the following:

image

The next task is to overlay the bars by setting the overlap to 100%. To do so, go to the Format Data Series dialog box - Options tab and change the overlap to 100%.

image

Finally, with a series of minor formatting changes the chart looks like this:

image

The chart shows the following:

  • The Government area is above the blue line and the Commercial / Contract area is below the blue line.
  • The Commercial / Contract revenue grew while the Government gross revenue showed no increase and reimbursement decreased.
  • The Commerical / Contract reimbursement is significantly higher than the Government reimbursement. As a result, the Commercial / Contract area looks much more attractive from a financial perspective.

A Study of Pie Chart Rounding

Pie charts, as well as many other charts, can be built to show percentages of a whole. Unfortunately, many times the pie chart percentages do not tie in total to the total of the source document percentages. Microsoft acknowledges the problem via this knowledge base article titled Pie Chart Shows Incorrect Percentage Value in Excel.

As a potential work-around, I attempted to create a source document formula that works similar to the logic described in the knowledge base article. The purpose of the formula is to force the rounded percentages in the source report to always tie to the pie chart percentages.

Refer to the screenshot below:

image

A source range, named "Data", covers the range C4:C10. Column D reflects the rounded source document percentages. When added together, the percentages equal 101%.

Column E contains the alternative percentages that tie to the pie chart. The formula, entered as a multicell-array into the range E4:E10, is as follows:

{=IF((Data-ROW()/10^10)=LARGE((Data-ROW()/10^10),1),
1-SUMPRODUCT(((Data-ROW()/10^10)<>LARGE((Data-ROW()/10^10),1))
*(ROUND(Data/$C$11,2))),ROUND(Data/$C$11,2))}

The formula works essentially as the knowledge base article describes. It:

  • Uses the ROW function to first break any ties that may occur when the same number appears two or more times.
  • Using the numbers calculated by the ROW function, it then uses the LARGE function to determain which percentage is the maximum.
  • If the percentage is the maximum, it subtracts the total of all of the the percentages excluding the maximum from 100%. All other percentages are calculated and rounded as normal.

In the example, the formula recognizes the rounded value for Gamma as the maximum. Because the data does not add to 100%, the formula subtracts one from the Gamma value to force the percentages to round to 100%. Likewise, the percentages in the pie chart show the same values.

To test the formula, I used the RANDBETWEEN function and a macro to quickly test 10,000 random scenarios. The formula appeared to work well with values that round in total to 99% or 101%. However, when values round to 98% or 102%, I did find occurances where the formula returns values that differ from the pie chart. In those cases Excel does not seem to assign the difference to one single value. Rather, Excel appears to pick two of the same values and distribute the difference evenly. Given the logic as described in the knowledge base article, I'm at a loss to explain why.

Below is an example where the pie chart percentages differ from the formula:

image

The formula calculates Beta to be the maximum and subtracts two from it to force the total to equal 100%. However, Excel subtracts one from Beta and Delta to get to 100%.

Healthcare Waterfall

Jon Peltier provides an excellent example of how to create waterfall charts that cross the x axis on his Peltier Technical Services site. These charts are especially useful for illustrating the components of variance.

Adapting Jon's waterfall charting examples to show the components of variance in a healthcare environment (for Hospitals, Clinics, etc.) requires an extra step. Normally, a positive variance would be shown with a green bar moving up and a negative variance would be shown with a red bar moving down. In a healthcare setting there's an extra twist. A positive variance can be shown with a green bar moving up or down. Likewise, a negative variance can be shown with a red bar moving up or down. Given these additional requirements, the formulas that drive the variance bars must be modified to reflect these types of changes.

To further explain, revenue provided by commercial and contract payers allows a greater reimbursement than revenue provided by government payers. As a result, an increase in the revenue provided by a commerical and contract payer would be favorable. A decrease in the revenue provided by a government payer is also favorable. Conversely, a decrease in revenue provided by commercial and contract payers may be viewed as unfavorable while an increase in revenue provided by government payers would also be viewed as unfavorable.

Below is an example of how a healthcare waterfall chart might look:

image

To allow for the changes in color if the variance is positive or negative, I've added a "Yes" or "No" color switch to the range C29:C33. Rather than the values determining if the color of the bar is positive or negative, the Yes-No switch allows the user to determine whether a change in a bar is positive or negative.

The example shows an overall decrease in volume. However, although the decrease in volume is normally viewed as negative, the reimbursement associated with the decrease may actually increase. The increase in reimbursement is a result of the positive commerical and contract variance combined with a negative government variance. To summarize, even though the volumes are decreasing the net revenue per unit of volume increases which allows for the possibility of greater profitability.

Since the example is somewhat complex, rather than explaining how each of the formulas work I've provided a link to the example file below.





Get Chart Data Points With VBA

Recently a project required that I perform calculations on the point values of an Excel chart using VBA. Upon researching how to do so, I found that writing the code is not as easy as I originally thought. The task becomes difficult because the point object does not have a values property.

Fortunately I found a solution that was posted by Andy Pope in response to a question posted to the Ozgrid.com forum. Below is Andy's example:

x=activechart.SeriesCollection(1).values 
For i=LBound(x) To UBound(x) 
    Debug.Print "Point ";i;"=";x(i) 
Next i 

In the solution above, "x" is a single-dimension array that hold the point values of "SeriesCollection(1)". A loop is used to increment through the array and return the point values.

Using this solution as a start, I needed to expand it to cover all of the series in a chart. The example below is the result:

Option Explicit

Sub PointValues1()

   Dim arrValues() As Variant
   Dim Srs() As Variant
   Dim Cnt As Integer
   Dim Sr As Integer
   Dim Pt As Integer
   Dim i As Integer
     
   Cnt = 0

    For Sr = 1 To ActiveChart.SeriesCollection.Count
        Srs = ActiveChart.SeriesCollection(Sr).Values
        For Pt = 1 To ActiveChart.SeriesCollection(Sr).Points.Count
             Cnt = Cnt + 1
             ReDim Preserve arrValues(1 To Cnt)
             arrValues(Cnt) = Srs(Pt)
        Next Pt
    Next Sr

    For i = 1 To UBound(arrValues)
        Debug.Print arrValues(i)
    Next i

 End Sub

In PointValues1, the first loop is used to increment through each series on the chart. Like Andy's example, the statement

Srs = ActiveChart.SeriesCollection(Sr).Values

is used to extract the point values from the active series. Because the array needs to hold all of the point values of the chart, a simple counter is used to record the placement of each point value within the array where that value should fall.

I created the following chart in which to test the macro above:

image

The macro returns the following point values in the immediate window from the "arrValues" array:

image

Next, I modified the macro above to perform several calculations using the point values stored in the array. The modified code below returns a maximum, minimum, total, and average value for all of the data points in the chart:

Option Explicit

Sub PointValues2()

   Dim arrValues() As Variant
   Dim Srs() As Variant
   Dim Cnt As Integer
   Dim Sr As Integer
   Dim Pt As Integer
   Dim i As Integer
   Dim MaxVal As Double
   Dim MinVal As Double
   Dim TotVal As Double
   
   Cnt = 0

    For Sr = 1 To ActiveChart.SeriesCollection.Count
        Srs = ActiveChart.SeriesCollection(Sr).Values
        For Pt = 1 To ActiveChart.SeriesCollection(Sr).Points.Count
             Cnt = Cnt + 1
             ReDim Preserve arrValues(1 To Cnt)
             arrValues(Cnt) = Srs(Pt)
        Next Pt
    Next Sr

    MaxVal = arrValues(1)
    MinVal = arrValues(1)
    
    For i = 1 To UBound(arrValues)
        If arrValues(i) > MaxVal Then MaxVal = arrValues(i)
        If arrValues(i) < MinVal Then MinVal = arrValues(i)
        TotVal = arrValues(i) + TotVal
    Next i

 Debug.Print "Maximum Value = " & MaxVal
 Debug.Print "Minimum Value = " & MinVal
 Debug.Print "Range Total = " & TotVal
 Debug.Print "Range Average = " & TotVal / UBound(arrValues)

End Sub

The macro returns the following point values in the immediate window from the "arrValues" array:

image

Finally, I thought to experiment with creating a two-dimension array to store the point values and a one-dimension array to store the values from the X-Axis. In this example, a counter like those used in examples 1 and 2 is replaced with two loops. The outer loop is based on the number of series on the chart and the inner loop is based on the number of points within each series. The code below is the result:

Option Explicit

Sub PointValues3()

    Dim arrValues() As Variant
    Dim Srs() As Variant
    Dim xVal() As Variant
    Dim SrCnt As Variant
    Dim PtCnt As Variant
    Dim Sr As Integer
    Dim Pt As Integer
    Dim i As Integer
    Dim j As Integer
    
    SrCnt = ActiveChart.SeriesCollection.Count
    PtCnt = ActiveChart.SeriesCollection(1).Points.Count
        
    For Sr = 1 To ActiveChart.SeriesCollection.Count
        Srs = ActiveChart.SeriesCollection(Sr).Values
        xVal = ActiveChart.SeriesCollection(Sr).xValues
        For Pt = 1 To ActiveChart.SeriesCollection(Sr).Points.Count
            ReDim Preserve arrValues(1 To SrCnt, 1 To PtCnt)
            arrValues(Sr, Pt) = Srs(Pt)
        Next Pt
    Next Sr

    For i = 1 To SrCnt
        For j = 1 To PtCnt
            Debug.Print "Series " & i & " " & "Point " & xVal(j) & " Value: " & arrValues(i, j)
        Next j
    Next i

End Sub

The macro returns the following point values in the immediate window from the "arrValues" array:

image

Align Charts to Worksheet Grid Post 2

As a follow-up to Align Charts to Worksheet Grid Post 1, the following procedure assigns a name, sizes, and aligns all of the embedded charts on a single worksheet. The key to the procedure is the location (range address) of the cell at the top left side of the chart.

Sub AlignCharts()

    Dim Cht As ChartObject

    For Each Cht In ActiveSheet.ChartObjects
        'Note: Naming the chart is optional.
        Cht.Parent.Name = Cht.TopLeftCell.Offset(-1, 0).Value
        Cht.Top = Cht.TopLeftCell.Top
        Cht.Left = Cht.TopLeftCell.Left
        Cht.Height = 114.75
        Cht.Width = 192
    Next Cht

End Sub

Given four embedded charts on a single sheet, the output looks like this:

image

Each chart is assigned the name of the value in the cell just above the top left cell. Each chart is aligned to the top-left cell and sized as per the height and width assignments.

With this procedure you don't have to worry about naming the charts first or building loops to place them. Just create a new chart, move it to the top-left cell location of your choice, add a name for the chart above the top-left cell, and run the macro.


Add Labels to Chart Data Points

In Excel there is no way to automatically attach text labels to data points within a chart. However, Microsoft has provided a VBA procedure to do so via it's Knowledge Base Article 213750.

The macro can be shortened to the following. To run the macro, first copy it to a standard module. Next, activate the chart and run it.

Sub AddLabels()
    Application.ScreenUpdating = False
    Dim Rng As Range
    Dim Cht As Chart
    Dim i As Integer
    Set Cht = ActiveChart
    Set Rng = ActiveSheet.Range("A1:A10")
    Cht.SeriesCollection(1).ApplyDataLabels Type:=xlDataLabelsShowLabel
    Pts = Cht.SeriesCollection(1).Points.Count
    For i = 1 To Pts
        Cht.SeriesCollection(1).Points(i).DataLabel.Text = Rng(i)
    Next i
    Application.ScreenUpdating = True
End Sub

To add the functionality of automatically updating the data labels whenever the cells are changed, the macro can be slightly modified to the following:

Replace

Cht.SeriesCollection(1).Points(i).DataLabel.Text = Rng(i)

with

Cht.SeriesCollection(1).Points(i).DataLabel.Text = "=" & Rng(i).Address(, , xlR1C1, True)

Finally, if you don't feel like fooling around with code, there are two free utilities available that allow you to attach text labels to data points within a chart: