tags:

views:

1096

answers:

6

We have a few very large Excel workbooks (dozens of tabs, over a MB each, very complex calculations) with many dozens, perhaps hundreds of formulas that use the dreaded INDIRECT function. These formulas are spread out throughout the workbook, and target several tables of data to look-up for values.

Now I need to move the ranges of data that are targeted by these formulas to a different location in the same workbook.

(The reason is not particularly relevant, but interesting on its own. We need to run these things in Excel Calculation Services and the latency hit of loading each of the rather large tables one at a time proved to be unacceptably high. We are moving the tables in a contiguous range so we can load them all in one shot.)

Is there any way to locate all the INDIRECT formulas that currently refer to the tables we want to move?

I don't need to do this on-line. I'll happily take something that takes 4 hours to run as long as it is reliable.

Be aware that the .Precedent, .Dependent, etc methods only track direct formulas.

(Also, rewriting the spreadsheets in whatever is not an option for us).

Thanks!

+3  A: 

You could iterate over the entire Workbook using vba (i've included the code from @PabloG and @euro-micelli ):

Sub iterateOverWorkbook()
For Each i In ThisWorkbook.Worksheets
    Set rRng = i.UsedRange
    For Each j In rRng
        If (Not IsEmpty(j)) Then
            If (j.HasFormula) Then
                If InStr(oCell.Formula, "INDIRECT") Then
                    j.Value = Replace(j.Formula, "INDIRECT(D4)", "INDIRECT(C4)")
                End If
            End If
        End If
    Next j
Next i
End Sub

This example substitues every occurrence of "indirect(D4)" with "indirect(C4)". You can easily swap the replace-function with something more sophisticated, if you have more complicated indirect-functions. Performance is not that bad, even for bigger Workbooks.

sdfx
A: 

You can use something like this in VBA:

Sub ListIndirectRef()

Dim rRng As Range
Dim oSh As Worksheet
Dim oCell As Range

For Each oSh In ThisWorkbook.Worksheets
    Set rRng = oSh.UsedRange
    For Each oCell In rRng
        If InStr(oCell.Formula, "INDIRECT") Then
            Debug.Print oCell.Address, oCell.Formula
        End If
    Next
Next

End Sub

Instead of Debug.Print you can add code to suit your taste

PabloG
A: 
Euro Micelli
A: 

Unfortunately, the arguments of INDIRECT are usually more complex than that. Here's an actual formula from one of the sheets, not the most complex formula we have:

=IF(INDIRECT("'"&$B$5&"'!"&$O5&"1")="","",INDIRECT("'"&$B$5&"'!"&$O5&"1"))

hm, you could write a simple parser by ignoring most of the characters and just looking for the relevant parts (in this example: "A..Z", "0..9" and "!:" etc.) but you will run into troubles if the arguments in "indirect" are functions.

maybe the safer approach would be to print every occurence of "indirect" in a third sheet. you could then add the desired output and write a small search and replace program to write your changes back.

If you "get" every cell in a huge spreadsheet you might end up needing monstrous amounts of memory. I am still willing to try and take that risk.

PabloG's method of selecting the used range is the way to go (added it into my original code). The speed is pretty good, especially if you check whether the current cell contains a formula. Obviously, this all depends on the size of your workbook.

sdfx
A: 

Q: "Is there any way to locate all the INDIRECT formulas that currently refer to the tables we want to move?"

As I read it, you want to look inside the arguments of INDIRECT for references to areas of interest. OTTOMH I'd write VBA to use a regular expression parser, or even a simple INSTR to find INDIRECT( read forward to the matching ), then EVALUATE() the string inside to convert it to the actual address, repeat as required for multiple INDIRECT(...) calls and dump the formula and its translation to two columns in a sheet.

A: 

I'm not sure what the etiquette of SO is concerning mention of products with which the writer is connected, but OAK, the Operis Analysis Kit, an Excel add-in, can replace the INDIRECT functions by the cell references they resolve to. You can then use Excel's audit tools to determine what dependents each range has.

You would, of course, do this to a temporary copy of the workbook.

More at

  • http://www.operisanalysiskit.com/oakpruning.htm
  • http://www.operisanalysiskit.com/help/2007/index.html?oakconceptpruning.htm

Given the age of this question you may well have found an alternative solution or workaround.