# Working with Circular references in Excel

## Properly setting up circular references

Whereas I am no fan of using circular references, they can be beneficial to your model and really solve the problem you are trying to solve. So here is some advice on how to properly work with them.

### Breaking the circles and setting initial values

In order to prevent your model from running into trouble, make sure there is a quick way to break each circle. Circular reference chains are risky in that if any of the cells inside a circle inadvertently yields an error value (e.g. a #DIV/0!), your model might not be able to recover and keeps showing error values.

What you can do is have (at least) one cell within each circle which contains an IF function, which -in turn- tests the value of a switch cell. If the switch cell contains anything, the circle is broken and a default value from another cell is taken, instead of the cell that is part of the circular reference chain.

Suppose you created this hypothetic circle:

A simple circular chain

To get the behavior I just described, I replace the formula in cell C3 with:

=IF($B$1=1,$B$2,D4)

Your sheet should now look like this:

A simple circular chain which you can break

Now test your new breakable chain by entering a 1 in cell B1. Cell C3 now will get an initial value of 10 from cell B2. Clear cell B1 to restore the circle.

You can combine the breaker cell with the initial value cell by modifying the formula a bit:

=IF($B$1="",D4,$B$1)

This way, you can enter a starting value in cell B1. This breaks the circular chain and sets the starting value. Remove the starting value to start calculating. The disadvantage of combining the break cell and starting value cell is that you loose the starting value as soon as you start the iteration because you have to empty the starting value cell to do so.

### Does your model converge?

A big problem with circular references is that you have to pay attention whether or not your model yields stable results in all circumstances. Iterative calculations can be in these states:

- The calculation converges

A converging calculation reaches a stable end result, where the last result does not differ more than a fraction from the one-but-last result. Basically, this difference should be less than or equal to the "Maximum Change" setting in your calculation settings.

- The calculation diverges

When the calculation diverges, things get out of hand: your values keep increasing or decreasing, never to reach a stable end result. The "model" I showed above is an example of a diverging chain. A calculation with results that switch signs (alternating between positive and negative, but with an increasing absolute value) between iterations is also considered to be divergent.

- The calculation oscillates

The model keeps switching between two (or more) end results.

- The calculation results do not change, but are incorrect

This is the hardest situation to detect, as you may be under the impression you have reached a solution to your problem. I advise you to find a way to check your results; Are they correct?

So you want to have a converging calculation, I assure you.

One way to check for converging calculation is by setting the maximum iterations to 1. That way you can check the intermediate values by hitting F9, Excel will do one iteration for each press of the F9 key. Pay attention to the results and you'll see whether your calculation converges.

### An alternative approach: have VBA control the circles

An alternative approach to monitor circular reference calculations is by handing over control of the iteration to VBA.

The method I propose here is to break the circles and use intermediate cells which are controlled by VBA to pass on their results to the other cells which used to form the circular reference chain. VBA will perform the iteration and by using some additional cells, the code can closely monitor the results and act accordingly.

For this I took an example from John Walkenbach’s Excel 2010 Bible. A company donates a percentage of its profit after taxes to charity. But since donations to charity are tax-deductible, the donation depends on the tax, which in turn (partly) depends on the donation. A circular reference!

#### Worksheet setup

The figure below shows a spreadsheet with the formulas in place:

The basic principle of the VBA code is that it looks for named ranges in the file which match names like Iter000, Iter001, Iter002, ... The number is unlimited.

To set the model up for the VBA handled iteration these steps are needed.

General settings needed:

- Setup a cell to hold the maximum number of iterations. Name that cell 'Iterations'.
- Have a cell which contains the accuracy and name it Accuracy.
- Have a cell which contains the =NOW() function to make your model volatile so it responds to an F9 key press.

The model changes needed:

- Name any cell Iter### (### being any unique three digit number).
- Name the cell to its immediate right IterResult###.
- Copy a formula from any of the cells within the circular reference chain to this newly named cell. Note that I added 0*[the cell with NOW()] to make the model volatile.
- Change the formula in the cell from which you copied the formula to =IterResult### (### is the number you used when defining the name).
- Have a cell with this formula: =Iter###-IterResult### to get the current delta. Name that cell Delta###.
- Have another cell with a formula like =IFERROR(IF(ABS(Delta###)<Accuracy,1,0),0) and name it IterIsOK###
- Repeat these steps for each circular chain you have.

Now you have broken the circular reference chain. This is what my example looks like, with the formulas in place:

The VBA code (see below) takes the Value from the named range Iter### and copies it onto the cell to the immediate right of the named range. The code detects a calculation of Excel and automatically repeats that calculation after copying the Iter### results to their right. It does so the number of times set up in Iterations.

I have also set up a conditional format on range A8:E8:

The VBA code does not check whether the condition(s) is (are) met, this is handled by the conditional formatting. It is quite easy to update the VBA code to check whether all conditions are met at the end of an iteration and if not, display a warning message.

#### Download

Here is a sample file for you to download.

#### The VBA code

First I'll just list all code. Below you will find an explanation...

' Module : mIterate

' Company : JKP Application Development Services (c)

' Author : Jan Karel Pieterse

' Created : 10-02-2015

' Purpose : Handles iteration of a (set of) circular reference(s)

'-------------------------------------------------------------------------

Option Explicit

Dim mlIterations As Long

Dim mlMaxIterations As Long

Const APP_NAME As String = "VBA assisted iteration example"

Public Sub EnableIterations()

Application.OnCalculate = "HandleIterations"

End Sub

Public Sub DisableIterations()

Application.OnCalculate = ""

End Sub

Public Sub HandleIterations()

DisableIterations

mlMaxIterations = ThisWorkbook.Names("Iterations").RefersToRange.Value

If mlIterations >= mlMaxIterations Then

mlIterations = 0

Application.StatusBar = False

EnableIterations

Exit Sub

Else

mlIterations = mlIterations + 1

Application.StatusBar = "Calculating circular references. Iteration # " & mlIterations

CopyIterationValues

Application.Calculate

HandleIterations

End If

EnableIterations

End Sub

Private Function HasIterationFinished() As Boolean

Dim oName As Name

Dim oWs As Worksheet

HasIterationFinished = False

For Each oName In ThisWorkbook.Names

If LCase(oName.Name) Like "iter###" Then

With oName.RefersToRange

If CStr(ThisWorkbook.Names(Replace(oName.Name, "Iter", "IterIsOK")).RefersToRange.Value) = "1" Then

HasIterationFinished = True

Exit Function

End If

End With

End If

Next

End Function

Private Sub CopyIterationValues()

Dim oName As Name

For Each oName In ThisWorkbook.Names

If LCase(oName.Name) Like "iter###" Then

With oName.RefersToRange

On Error Resume Next

ThisWorkbook.Names(Replace(oName.Name, "Iter", "IterResult")).RefersToRange.Value = .Value

On Error GoTo 0

End With

End If

Next

End Sub

##### Entry point routines

The code has two so-called entry point routines, routines called directly by a user action:

EnableIterations and DisableIterations. These two routines are called by the two buttons on the worksheet. They do exactly what their names state.

EnableIterations tells Excel to call HandleIterations after each completion of a calculation.

##### Other routines

HandleIterations first turns off the OnCalculate event by calling DisableIterations. This is done because inside HandleIterations we are asking Excel to recalculate. At that point we do not want HandleIterations to be called again as we want to control when exactly that happens.

For as long as the current number of iterations is less than the maximum number of Iterations, the routine copies the iteration result to its adjacent cell using the routine called CopyIterationValues. If the maximum # of iterations has been reached, the number of iterations is reset to zero and the iteration chain is terminated.

Note that the code also contains a function HasIterationFinished. Currently this function is not used, but you could include the function in HandleIterations to show a message to the user when the iteration has not reached an end result matching your criteria.

## Comments

Showing last 8 comments of 21 in total (Show All Comments):Comment by: Ted Eggleton (16-6-2014 09:49:06)

This is a simple A=A+1 type of requirement that works in itself but screws up the rest of the workbook and by implication all other workbooks accessed by that particular Excel instance.

Essentially, what you are saying is don't use reiteration.

Comment by: Jan Karel Pieterse (16-6-2014 10:27:12)

Let me make that a bit more precise: Do not use circular references unless there is no other way.

Many calculations requiring circular references can be done using built-in worksheet functions that do the required iterations internally. Look in help at the financial functions (like PMT), I am quite sure there should be one there that does the calculation you require without needing to set up iterations.

Comment by: Ted (20-6-2014 10:26:42)

Comment by: Norman Hicks (25-9-2014 22:52:49)

Comment by: Jan Karel Pieterse (26-9-2014 11:46:41)

To be honest, it sort of disappeared under my radar :-)

My biggest problem is that I do not have a good example model to demonstrate the technique with. If anyone does have a model (perhaps not as complex as yours :-) ), please sahre it with me so I can have a look at it and perhaps use it as the basis for the article!

Comment by: Eric (11-2-2015 14:25:33)

Obviously, your example is not about calculating in itself, but to provide an example for the benefit of circular reference.

Based on this example, you can also calculate the amount of charity with a "simple" formula:

Charity = ((100% - Taxpercentage)* Revenu) -((100% - Taxpercentage)*Expenses) / ((100%/Charity-percentage)+(100%-Taxpercentage)

With regard to VBA would recursion may also be a method?

Have not tested it myself, just an idea, I have my iterative calculation (always) disabled

Anyways; Thanks for sharing!

Comment by: Eric (11-2-2015 14:35:47)

Comment by: Jan Karel Pieterse (11-2-2015 16:10:56)

Of course you are right. I just wanted to share this to show an alternative method to control the iteration. The method shown here makes it possible to do problem-specific things, like detecting instabilities in the iteration.

## Have a question, comment or suggestion? Then please use this form.

If your question is not directly related to this web page, but rather a more general "How do I do this" Excel question, then I advise you to ask your question here: www.eileenslounge.com.