Reputation: 13
I'm pretty new to VBA and love to challenge myself, but am at a loss on this project however.
I have a workbook that has quite a few tabs used for various calculations and summations. The "PDP Base" main tab takes all "PDP BaseX" tabs and adds all values for the same cell across all "PDP BaseX" tabs into the main one. This is easy to handle manually when there are only 5 or so "PDP BaseX" tabs, but if there are potentially many tabs to add together (10+), combing through each is a pain. This is made worse if there are multiple cases to add formulas to (PNP;PBP;PUD;PBL - with each having a Base and Sens modifier).
Each new "PDP BaseX" tab is copy pasted from a template ran by other code (not yet finished) with a new "X+1" value, and so I don't want to just copy paste a formula adding the new tab into the main tab.
The end result will have code for all the main tabs of each category, but if I can get one main tab to do what I want, I can go from there.
Below is some code that I feel is close, but it loops to infinity somewhere in there and won't move pass initial cell B29 (getting overflow into PDP Base B29 when result should be lets say 10 for example; PDP Base1 B29 = 2; PDP Base2 B29 = 6; PDP Base3 B29 = 4)
Private Sub Worksheet_Calculate()
Dim ws As Worksheet, mainws As Worksheet
Dim rng As Range, mainrng As Range
Dim x As Single, y As Single
Dim tVar As Double
Set mainws = ActiveWorkbook.Worksheets("PDP Base")
With mainws
For y = 2 To 4
For x = 29 To 43
For Each ws In ActiveWorkbook.Worksheets
If ws.Name Like "PDP Base*" And ws.CodeName <> "PDPBase" Then
'the main tab has a codename assigned to it to not add itself
With ws
With .Range(Cells(x, y))
tVar = tVar + .Range(Cells(x, y)).Value
End With
End With
End If
Next ws
Set mainrng = Cells(x, y)
mainrng.Value = tVar
tVar = 0
Next x
Next y
End With
End Sub
Would someone be able to shed some insight into this? Thank you!
Upvotes: 1
Views: 102
Reputation: 13
Its been a bit since I posted the original question, but I've gotten much further since then and just wanted to post my progress for others to use incase they need something similar.
There is still a lot of cleaning that could be done, and its not finished, but the basic idea works really really well. The code takes several codenamed (not tab names; allows users to change the tab name to something different) main sheets and loops through each, adding formulas that dynamically add cells from similarly named subsheets into the main sheet across multiple blocks of cells.
Also wanted to thank the original answer again provided by Tim Williams as that helped me tremendously to get going in the right direction and is the foundation to the code below.
Use at your own risk. I hear CodeNames and using VBProject type of codes can give you a bad day if they break.
Main Code Below
Public Sub Sheet_Initilization()
Dim ws As Worksheet, mainws As Worksheet, wb As Workbook
Dim codename As String
Dim mainwsname As String
Set wb = ActiveWorkbook
'block code to run code smoother
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.EnableEvents = False
'PLACEHOLDER FOR LATER USE CaseNames = Array("PDPBase", "PDPSens", "PBPBase", "PBPSens", "PNPBase", "PNPSens", "PUDBase", "PUDSens")
CaseNames = Array("PDPBase", "PBPBase", "PNPBase", "PUDBase") 'main 4 cases, more to come
For Each c In CaseNames 'cycle through each "Main" case sheet
codename = c
Set mainws = wb.Sheets(CN(wb, codename)) 'calls function to retrieve code name of the main case sheet
'allows users to change main case tab names without messing up the codes
'must change security settings to use, looking into alternatives
mainwsname = mainws.Name 'probably could do without with some optimization
For Each b In Range("InputAdditionCells").Cells 'uses named range of multiple blocks of cells, B29:D34 M29:O43 I53:J68 for example
'cycles through each cell in every block
mainws.Range(b.Address).Formula = "=" 'initial formula
For Each ws In wb.Worksheets 'cycles through each sheet
If ws.Name Like mainwsname & "*" And ws.Name <> mainwsname Then 'finds similarily named sub sheets (PDP Base 1, PDP Base 2...etc)
', but won't use the main sheet (PDP Base)
If b.Address Like "$Y*" Then 'special column to use different offset formula
mainws.Range(b.Address).Formula = mainws.Range(b.Address).Formula & "+'" & ws.Name & "'!" & b.Offset(0, 4).Address
Else
mainws.Range(b.Address).Formula = mainws.Range(b.Address).Formula & "+'" & ws.Name & "'!" & b.Address
End If
End If
Next ws
Next b
For Each d In Range("InputWeightedCells").Cells 'same idea as before, different main formula (weighted average)
mainws.Range(d.Address).Formula = "="
For Each ws In wb.Worksheets
If ws.Name Like mainwsname & "*" And ws.Name <> mainwsname Then
If d.Address Like "*$68" Then 'special row to use different offset formula
mainws.Range(d.Address).Formula = mainws.Range(d.Address).Formula & "+('" & ws.Name & "'!" & d.Address _
& "*'" & ws.Name & "'!" & d.Offset(-21, 23).Address & ")"
Else
mainws.Range(d.Address).Formula = mainws.Range(d.Address).Formula & "+('" & ws.Name & "'!" & d.Address _
& "*'" & ws.Name & "'!" & d.Offset(-24, 23).Address & ")"
End If
End If
Next ws
Next d
MsgBox (mainwsname) 'DELETE; makes sure code is running properly/codebreak without using the break feature
Next c
'reactivate original block code
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
Application.EnableEvents = True
End Sub 'cool beans
Function that's called (need to change the Macro settings in the trust center settings from excel options to run). Once again use at your own risk.
Function CN(wb As Workbook, codename As String) As String
CN = wb.VBProject.VBComponents(codename).Properties("Name").Value
End Function
Upvotes: 0
Reputation: 166391
Untested but should do what you want:
Private Sub Worksheet_Calculate()
Const MAIN_WS_NAME As String = "PDP Base" 'use a constant for fixed values
Dim ws As Worksheet, mainws As Worksheet, wb As Workbook
Dim x As Long, y As Long 'Long not Single
Dim tVar As Double
Set wb = ActiveWorkbook
Set mainws = wb.Worksheets(MAIN_WS_NAME)
For y = 2 To 4
For x = 29 To 43
tVar = 0
For Each ws In wb.Worksheets
If ws.Name Like MAIN_WS_NAME & "*" And ws.Name <> MAIN_WS_NAME Then
tVar = tVar + ws.Cells(x, y).Value
End If
Next ws
mainws.Cells(x, y).Value = tVar
Next x
Next y
End Sub
Upvotes: 1