Home » excel » excel – How to modify this code to only search visible rows and columns

excel – How to modify this code to only search visible rows and columns

Posted by: admin April 23, 2020 Leave a comment

Questions:

I have a userform that allows the user to select which rows and columns are relevant to the user to check. I am using this code, but it searches all rows and all columns and therefore doesn’t delete the right rows. Could anyone suggest a solution to fixing this that will work for rows and columns? Thanks.

Dim RowToTest As Long
Dim MySheet As Worksheet
Dim ProjectedDate As Date
Dim ColToTest As Long
Dim TempKeep As Integer
TempKeep = 0

ProjectedDate = Date + 60

For Each MySheet In ThisWorkbook.Sheets
    For RowToTest = MySheet.Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
        For ColToTest = MySheet.Cells(2, Columns.Count).End(xlToLeft).Column To 15 Step -1
            With MySheet.Cells(RowToTest, ColToTest)
                If IsDate(MySheet.Cells(RowToTest, ColToTest).Value) Then
                    If .Value < ProjectedDate Then
                        TempKeep = 1
                    End If
                End If
            End With
        Next ColToTest
        If TempKeep = 0 Then
            MySheet.Rows(RowToTest).EntireRow.Delete
        End If
        TempKeep = 0
    Next RowToTest
Next
How to&Answers:

You can check if a cell is hidden through their .Rows and .Columns property like so:

If CelToCheck.Rows.Hidden or CelToCheck.Columns.Hidden Then
    'Your code if hidden
Else
    'Code if not hidden
End if

In your case CelToCheck would be

MySheet.Cells(RowToTest, ColToTest)

Alternatively you can set a range variable and loop through visible cells only with

For each CL in RangeVariable.SpecialCells(xlCellTypeVisible)
    'Your code
Next CL

Answer:

I was about to suggest the same as JvdV, using the .Hidden property. Can use it in your code something like this:

Dim RowToTest As Long
Dim MySheet As Worksheet
Dim ProjectedDate As Date
Dim ColToTest As Long
Dim TempKeep As Integer
TempKeep = 0

ProjectedDate = Date + 60

For Each MySheet In ThisWorkbook.Sheets
    For RowToTest = MySheet.Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
        For ColToTest = MySheet.Cells(2, Columns.Count).End(xlToLeft).Column To 15 Step -1
            With MySheet.Cells(RowToTest, ColToTest)
                If IsDate(MySheet.Cells(RowToTest, ColToTest).Value) Then
                    If .Value < ProjectedDate Then
                        TempKeep = 1
                    End If
                End If
            End With
        Next ColToTest
        If TempKeep = 0 and Not isHiddenRow(MySheet, RowToTest) Then
            MySheet.Rows(RowToTest).EntireRow.Delete
        End If
        TempKeep = 0
    Next RowToTest
Next

don’t necessarily need to have a function to do so, but makes it easier for code reuse.

Function isHiddenRow(sht As Worksheet, rowNr As Long) As Boolean
    On Error Resume Next
    isHiddenRow = sht.Rows(rowNr).Hidden
End Function

Function isHiddenCol(sht As Worksheet, colNr As Long) As Boolean
    On Error Resume Next
    isHiddenCol = sht.Columns(colNr).Hidden
End Function

PS: depending how much data you have in your sheet, is not a very good idea to loop directly over the sheet generally. Consider using arrays if you have thousands of rows.

EDIT: added an alternative using an array to do the same thing.

Option Explicit

Sub delVisibleRows()
Dim MySheet As Worksheet
Dim ProjectedDate As Date: ProjectedDate = Date + 60

Dim R As Long, C As Long, lRow As Long, lCol As Long
Dim arrData As Variant
Dim strRange As String

    For Each MySheet In ThisWorkbook.Sheets 'for each sheet
        With MySheet
            lRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'get last row
            lCol = .Cells(2, .Columns.Count).End(xlToLeft).Column 'get last column
            arrData = .Range(.Cells(1, 1), .Cells(lRow, lCol)) 'allocate the data to an array

            For R = 2 To lRow 'iterate through all rows starting at 2
                For C = 15 To lCol 'iterate through all columns, starting at 15 - this could cause a problem if there are less than 15 columns
                    If IsDate(arrData(R, C)) And arrData(R, C) < ProjectedDate Then 'check if is date, and if is less than projected date
                        Exit For 'if it is, skip to next row
                    End If

                    If C = lCol Then  'If we got to last col without meeting the skip condition
                        strRange = strRange & R & ":" & R & "," 'build the string for the range to delete
                    End If
                Next C
            Next R

            strRange = Left(strRange, Len(strRange) - 1) 'get rid of the last comma
            .Range(strRange).SpecialCells(xlCellTypeVisible).EntireRow.Delete 'delete only the visible rows
        End With
    Next MySheet
End Sub