Hello all and thanks for your help ahead of time,
I have an excel sheet that is solely to take the summation of multiple sheets. Best and most simply put, the formula is something like =sum(Sheet1!A1,Sheet2!A1,Sheet3!A1,Sheet4!A1)
. There are a few issues that complicate matters though. First off all, I do not know the number or order of the sheets to sum, nor do I know their name. This formula will be copied into ~150 other cells, so I need the summation to be dynamic instead of physically adding sheets to ~150 cells every time. (Also the configuration and naming of the sheet does not allow for easy dragging for formulas.)
So first of all, I thought I could write it using an indirect()
reference. I made a column to list all the sheets names that would be added into each cell. Unfortunately, concatenate()
cannot be used over arrays, so I had to resort to a UDF seen below:
Function CONCAT(Delimiter As Variant, ParamArray CellRanges() As Variant) As String
Dim Cell As Range, Area As Variant
If IsMissing(Delimiter) Then Delimiter = ""
For Each Area In CellRanges
If TypeName(Area) = "Range" Then
For Each Cell In Area
If Len(Cell.Value) Then CONCAT = CONCAT & Delimiter & Cell.Value
Next
Else
CONCAT = CONCAT & Delimiter & Area
End If
Next
CONCAT = Mid(CONCAT, Len(Delimiter) + 1)
End Function
Using the UDF, I could get a large string with the proper syntax such as =CONCAT("'!A"&(B1+1)&",'",Array_of_Sheets)&"'!A"&(B1+1)
. The CONCAT()
takes a separator as the first parameter and the array(s) as the second parameter. I then append the "separator" on the end of the string as well to output something such as Sheet1'!A1,'Sheet2'!A1
. I thought at this point, a simple =sum(indirect(STRING))
would be sufficient, but =sum(indirect("Sheet1!A1,Sheet2!A1,Sheet3!A1,Sheet4!A1"))
does not work since indirect()
cannot seemingly process the commas.
So to solve this, I switched the =CONCAT()
to =CONCAT("'!A"&(B1+1)&"+'",Array_of_Sheets)&"'!A"&(B1+1)
to output Sheet1'!A1+'Sheet2'!A1
. Now I wrote another UDF to force it to evaluate seen below:
Function EVAL(RefCell As String)
Application.Volatile
EVAL = Evaluate(RefCell)
End Function
This worked! Awesome, right? After some use and testing though, it seems to not be quite consistent. When we have other sheets open, it does not always evaluate (and we will have other sheets open). There is some other inconsistencies that I read about with using volatile
in the UDF, but I cannot find them.
So for my ideal, I would like to do this without any VBA at all, but I suspect that won't be possible. I would rather not depend on the user to manually recalculate worksheets (partly the reason for volatile
). Finally, I just want it to sum()
in a consistent manner so if a user opens the document and just hits print, the user does not need to confirm the functions are evaluating correctly (check for #REF errors or manually add up the values to make sure they are correct). I am hoping to find an alternative to using the eval()
equation.
EDIT for additional information below
I had experimented with using 3D arrays, but there was a few issues I ran into. Lets say the workbook has eight sheets. Of those eight sheets, only two may feed into this total sheet. There is a setup
sheet, the total
sheet, a data entry
sheet, and a data analysis
sheet. The total
sheet totals off of the data analysis
sheets. Typically a data entry
sheet coincides with a data analysis
sheet. So the user may make copies of both the data entry
and the data analysis
sheets. The most logical order of the sheets would begin with the setup
sheet, then each pairing of the data entry
and data analysis
sheets, and the total
sheet. Obviously, this setup will not work with a 3D array. We would have to reorder the sheets and make sure the user knows that the order of the sheets actually matters (an atypical configuration). There will also be instances where one or two data analysis
sheets will not be included in the total
sheet. So we may end up with a sheet configuration of setup \ data entry (1) \ data entry (2) \ START \ data anaylsis (1) \ data analysis (2) \ END \ totals \ data entry (3) \ data entry (4) \ data anaylsis (3) \ data analysis (4)
. My feeling was that a 3D array configuration would almost make the addition too dynamic. I would rather have an explicit list then depend on the user being confident in moving the sheets around to have the proper totals.
Good news! You can make your life much simpler - by using a 3D formula:
If you use this formula:
=SUM(Sheet1:Sheet3!$A$1:$B$2)
, all cells in A1:B2 will be summed - across all sheet from Sheet1 to Sheet3!Quite often, it is helpful to use two "helper" sheets to handle an open/changing number of worksheets:
Check out this link for further instructions.
Here's another approach:
Assuming that your user's data entry sheets are labelled according to some kind of system that has to be strictly adhered to (e.g. "Data entry 1", "Data entry 2", etc.), you could build a summary table using
INDIRECT
- and then total this table instead.In detail, you'd have a helper table in your 'Totals' sheet, looking something like this:
=ADDRESS(ROW(Template!C5);COLUMN(Template!C5))
to get the dynamic address.=NOT(ISERROR(INDIRECT(ADDRESS(1,1,,,A3))))
=IF(B3,INDIRECT("'"&A3&"'!"&C$1),0)
Now you only need to total the columns C and so forth.