Timmy241
Timmy241

Reputation: 13

VBA - Main worksheet to add values across other new not yet created worksheets across multilpe ranges

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

Answers (2)

Timmy241
Timmy241

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

Tim Williams
Tim Williams

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

Related Questions