Home > Blockchain >  VBA, If all rows in Col A is filled and Col B is blank(and vice versa) then copy those rows to a new
VBA, If all rows in Col A is filled and Col B is blank(and vice versa) then copy those rows to a new

Time:10-31

I am trying to incorporate the following logic, If all rows in Col A is filled and Col B is blank(and vice versa) then copy those rows to a new sheet.

Here is what I have so far:

Sub DataValidation()

    Dim rng As Range
    Dim cell As Range

    Set rng = Range("A:B")

    For Each cell In rng
        
    If Cel.Value = "" Then
    Sheets("List").Cel.Value.EntireRow.Copy Destination:=Sheets("test").Range("A" & Rows.Count).End(xlUp).Offset(1)
        
    Next cell
    
End Sub

Can anyone help with this? I need help with 1) If.Cel.Value="" , I dont think this identifies the logic for Col A filled and Col B is blank. 2) And I need help identifying these rows and copying to a new tab.

CodePudding user response:

First off, your reference to cell.value has a typo, it needs to be cell.value

As for the solution, just like Bigben said, a Range.AutoFilter is probably the simplest option here without Advanced Filters.

You'll be looking for something like this

rng.AutoFilter Field:=1, Criteria1:="<>" 'This will filter by non-blanks in Column 1

rng.AutoFilter Field:=2, Criteria1:="=" 'This will filter by blanks in Column 2

When a range is filtered, if you use rng, it will still refer to the entire range including those hidden (essentially ignoring the filter). This is why you should now use rng.specialCells(xlCellTypeVisible) to now refer to the displaying range.

Mix and match filters and then use rng.specialCells(xlCellTypeVisible).Copy

CodePudding user response:

Please, try the next way. It uses an array and builds a Union range, to be copied at the code end. That's why is should be much faster than iterating between all cells and copying a row at a time:

Sub DataValidation()
    Dim ws As Worksheet, lastR As Long, arr, rngCopy As Range, i As Long

    Set ws = ActiveSheet
    lastR = ws.Range("A" & ws.rows.count).End(xlUp).row
    arr = ws.Range("A1:B" & lastR).Value2 'place the range in an array for faster iteration/processing

    For i = 2 To UBound(arr) '2 supposing that headers exist on the first row
        If (arr(i, 1) <> "" And arr(i, 2) = "") Or (arr(i, 2) <> "" And arr(i, 1) = "") Then
            addToRange rngCopy, ws.Range("A" & i)
        End If
    Next i
        
   If Not rngCopy Is Nothing Then rngCopy.EntireRow.Copy _
         Sheets("test").Range("A" & rows.count).End(xlUp).Offset(1)
End Sub

Sub addToRange(rngU As Range, rng As Range)
    If rngU Is Nothing Then
        Set rngU = rng
    Else
        Set rngU = Union(rngU, rng)
    End If
End Sub
  • Related