Home > database >  Change range based on sum of cell - why does my loop not work?
Change range based on sum of cell - why does my loop not work?

Time:06-28

i'm trying to write a macro to automatically resize a range to cells that have a greater than 0 value in a row - i have 12 columns for each month, and i want to make a range from only the cells that contain data.

The code i have so far seems to work, but it loops only once and stops on month 11.

Sub Charts_Update()

Dim TotFTE As Range, CellIndex As Range
Dim ColIndex As Long, i As Long

Set TotFTE = Sheets("FTE Detail").Range("E19:P19")

i = 12
    
With TotFTE
    For ColIndex = .Cells(0, 16).End(xlToLeft).Column To 5 Step -1
        With Columns(ColIndex)
            If Application.Sum(.Cells) = 0 Then
                i = i - 1
                Set TotFTE = TotFTE.Offset(0, 0).Resize(1, i)
            End If
        End With
    Next ColIndex
End With

End Sub

Any ideas to get it to go correctly through all columns? Any help much appreciated. Thanks

CodePudding user response:

I have multiple possible codes depending on what you want to achieve. In any case if no cell with numeric value is found (i maintained your way to formulate the condition via Application.Sum) or the appropriate range can't be determined in any other way, nothing is returned.

The first one is a modified version of your own code:

Sub Charts_Update1()
    
    'Declarations.
    Dim TotFTE As Range, CellIndex As Range
    Dim ColIndex As Long, i As Long
    
    'Settings
    Set TotFTE = Sheets("FTE Detail").Range("E19:P19")
    i = TotFTE.Columns.Count
    
    'Focusing TotFTE.
    With TotFTE
        
        'Covering the cells from the most right cell with data to the left of cell(0, 16) to the firt column of TotFTE.
        For ColIndex = .Cells(0, 16).End(xlToLeft).Column To TotFTE.Column Step -1
            
            'Focusing the entire column with ColIndex index.
            With Columns(ColIndex)
                
                'Checking if the sum of the cell of TotFTE within the column with ColIndex index is 0.
                If Application.Sum(Intersect(.Cells, TotFTE)) = 0 Then
                    
                    'Setting i for the previous column.
                    i = i - 1
                    
                    'If i is equal to 0, no result with a sum different from 0 has been found.
                    If i = 0 Then
                        
                        'Setting TotFTE to nothing and terminating the macro.
                        Set TotFTE = Nothing
                        Exit Sub
                        
                    End If
                    
                    'Resizing TotFte.
                    Set TotFTE = TotFTE.Resize(1, i)
                Else
                    
                    'The first cell with a sum different than 0 most to the right in TotFTE has been found. The macro is terminated.
                    Exit Sub
                    
                End If
                
            End With
            
        Next ColIndex
        
    End With

End Sub

It will return the range:

  • from the cell on the left edge of the original TotFTE (even if empty or with text)
  • to the first most right non-empty with non-text value to the left of the right edge of the original TotFTE

I wanted to have at least one code to be a modified version of your own. I will therefore maintain some criticality (like the using of the header to determine ColIndex).


The second one is a brand new code:

Sub Charts_Update2()
    
    'Declarations.
    Dim TotFTE As Range
    Dim RngTarget As Range
    
    'Settings.
    Set TotFTE = Sheets("FTE Detail").Range("E19:P19")
    Set RngTarget = TotFTE.Cells(1, 1)
    
    'If the sum of RngTarget is zero, TotFTE is set to nothing and the macro is terminated.
    If Application.Sum(RngTarget) = 0 Then
        Set TotFTE = Nothing
        Exit Sub
    End If
    
    'RngTarget is resized until its sum doesn't change anymore or it reaches the TotFTE range limit.
    Do Until Application.Sum(RngTarget) = Application.Sum(RngTarget.Resize(, RngTarget.Columns.Count   1)) Or _
             RngTarget.Columns.Count   1 > TotFTE.Columns.Count
        Set RngTarget = RngTarget.Resize(, RngTarget.Columns.Count   1)
    Loop
    
    'Setting TotFTE.
    Set TotFTE = RngTarget
    
End Sub

It will return the range:

  • from the left edge of the original TotFTE only if non-empty with non-text value
  • to the cell within the original TotFTE on the right edge of the first chunk of continuously satisfactory (non-empty with non-text value) data.

The third one is also a brand new code:

Sub Charts_Update3()
    
    'Declarations.
    Dim TotFTE As Range
    Dim RngLeft As Range
    Dim RngRight As Range
    
    'Settings.
    Set TotFTE = Sheets("FTE Detail").Range("E19:P19")
    Set RngLeft = TotFTE.Cells(1, 1)
    Set RngRight = TotFTE.Cells(1, TotFTE.Columns.Count)
    
    'Checking if RngLeft sum is zero.
    If Application.Sum(RngLeft.Value) = 0 Then
        
        'Setting RngLeft as the firt cell with value to the right of RngLeft.
        Set RngLeft = RngLeft.End(xlToRight)
        
        'Checking if RngLeft has reached beyond the TotFTE limits or has a sum total of 0.
        If RngLeft.Column > TotFTE.Column   TotFTE.Columns.Count - 1 Or Application.Sum(RngLeft.Value) = 0 Then
            
            'Setting TotFTE to nothing end terminating the sub.
            Set TotFTE = Nothing
            Exit Sub
        End If
    End If
    
    'Checking if RngLeft sum is zero.
    If Application.Sum(RngRight.Value) = 0 Then
        'Setting RngRight as the firt cell with value to the left of Rngright.
        Set RngRight = RngRight.End(xlToLeft)
    End If
    
    'Setting TotFTE.
    Set TotFTE = Range(RngRight, RngLeft)
    
End Sub

It will return the range:

  • from the most-left cell of the original TotFTE non-empty with non-text value
  • to the most-right cell of the original TotFTE non-empty with non-text value.

It will include any empty and/or with text value between those 2 cells.

CodePudding user response:

I ran the code on an example sheet and a few things to note:

  1. the .Cells(0,16) - as mentioned in the comments - this is actually the row above the row you define (in your example this would be row 18, the row above E19:P19), that cell would also be past your defined range (in the example it is T18)

  2. the code will resize down if the final column (all of the column not just the part in the defined range, eg. P1:P1048576), sums to 0

  3. an odd behaviour will happen if there is a column that sums to 0 prior to a column that does not. in this case the code will resize down by 1 but that will drop a column that does have data in it

  4. if no columns have data in then your code will try to resize a range to null, that wont work and will throw an error.

Given these things the code does actually work, can you expand on what you're trying to do and what you mean by "but it loops only once and stops on month 11" and we can try to help to adjust the code to your use

  • Related