I would like to find the cells (or Rows) in Column B, Sheet1, who have matching values placed into ListBox2. Then, I'd like to change the value of a cell 4 columns over (using an Offset command).
I believe using a For loop is the most efficient way of going thru the values placed into ListBox2. I tried using a Forloop to go thru all values placed into ListBox2.List. Upon calling a value, the code would look for this value in Column B. Once found, it would "remember" the Row in which this value was found. Then, the code would use a Range/Offset command to change the value of a cell 4 columns over in that Row.
Private Sub ButtonOK_Click()
Dim wb As Workbook
Dim ws As Worksheet
Dim SerialList As Range
Dim SerialRow As Long
Dim i As Long
Set wb = ActiveWorkbook
Set ws = ActiveWorkbook.Worksheets("Sheet1")
Dim strFind As Variant
With ws
For i = 0 To Me.ListBox2.ListCount - 1
Set SerialList = ws.Range("B:B").Find(What:=Me.ListBox2.List(i))
SerialRow = SerialList.Row
If Not SerialList Is Nothing Then
ws.Range("B", SerialRow).Offset(0, 4).Value = Me.ListBox2.List(i) 'error occurs here!
MsgBox (ListBox2.List(i) & " found in row: " & SerialList.Row)
Else
MsgBox (ListBox2.List(i) & " not found")
End If
Next i
End With
End Sub
The MsgBoxes do say the correct ListBox2.List(i) value and the correct SerialList.Row, meaning that the program is correctly finding the row in which the list box value is located. However, I get an error saying that my range is not correctly defined at line "ws.Range("B", SerialRow)....."
How do I select the cell I'm searching for to correctly set it to =Me.ListBox2.List(i)?
Couple of fixes:
Dim lv
'....
For i = 0 To Me.ListBox2.ListCount - 1
lv = Me.ListBox2.List(i)
Set SerialList = ws.Range("B:B").Find(What:=lv, LookAt:=xlWhole) '<< be more explicit
'don't try to access SerialList.Row before checking you found a match...
If Not SerialList Is Nothing Then
ws.Cells(SerialList.Row, "F").Value = lv '<< Cells in place of Range
MsgBox (lv & " found in row: " & SerialList.Row)
Else
MsgBox (lv & " not found")
End If
Next i
Related
Hello all this is my first question so I will try my best to format this best I can.
Quick description without specific cell names below
I am trying to write a macro where a user enters a value(X) and a macro searches a range of cells for a value(X), and then the macro returns the cell values in the 3 spaces next to wherever the location of value(X) is.
A couple things that are making this impossible to solve are the fact that the user inputs the value on Sheet1 and the value is moved to Sheet2 by a formula, I can't seem to figure out how to use Find where the values I am searching for isn't already defined in the macro.
The other thing making this difficult is that the range is not strictly definable either, as the list could be longer or shorter than it currently is, and I can't know when it will change. So the range of the search has to start based on which List is input by the User and needs to go until it hits a blank spot.
For example: Range.("C7:D10") wont work because the user could enter new info that changes the working range as described below.
Below is a screenshot with further explanation
https://i.stack.imgur.com/wlnhg.jpg
So in this screenshot the cells C3 and D3 are imported values from Sheet1.
C3 is (=Sheet1!B2)
D3 is (=Sheet1!B3)
The idea is that the macro runs and searches down column A till it has a match with C3.
Then the search function moves over two cells and searches down till it has a match with D3 or until it hits an empty space.
I don't know how to ask a macro to search based on an imported value, and I don't know how to ask it to search this weird certain range I need. The idea is that someone at my work could come along and add a row below C10 and add the necessary information and the macro would still work and search to C11 and there would be a blank space after to tell the macro to stop.
After the search finds a match for D3 it would return the values adjacent to the match to the corresponding cells at the top, E3, F3, and G3.
I hope this question is asked in a way that people can understand, I am very tired so can't tell if I wrote something that makes sense. Thank you for reading my post, y'all are the best!!
Search Twice
Workbook Download (Dropbox)
Sub SearchTwice()
Const cSheet As String = "Sheet2" ' Source Worksheet Name
Const cList As String = "C3" ' List Cell Range Address
Const cName As String = "D3" ' Name Cell Range Address
Const cListCol As String = "A" ' List Column Letter
Const cNameCol As String = "C" ' Name Column Letter
Const cFirst As Long = 6 ' First Row
Const cCol As Long = 3 ' Number of Columns
Dim rng1 As Range ' Find List Cell Range
' Found Name Cell Range
Dim rng2 As Range ' Next List Cell Range
' Name Search Range
Dim strList As String ' List
Dim strName As String ' Name
' In Source Worksheet
With ThisWorkbook.Worksheets(cSheet)
' Write from List Cell Range to List.
strList = .Range(cList)
' Write from Name Cell Range to Name.
strName = .Range(cName)
' Check if Cell Ranges do NOT contain data.
If strList = "" Or strName = "" Then ' Inform user.
MsgBox "Missing List or Name.", vbCritical, "Missing data"
Exit Sub
End If
' In List Column
With .Columns(cListCol)
' Create a reference to Find List Cell Range (rng1) containing
' List (strList).
Set rng1 = .Find(strList, .Cells(cFirst - 1), xlValues, xlWhole)
' Check if List has not been found.
If rng1 Is Nothing Then ' Inform user and exit.
MsgBox "The list '" & strList & "' has not been found", _
vbCritical, "List not found"
Exit Sub
End If
' Create a reference to Next List Cell Range (rng2).
Set rng2 = .Find("*", .Cells(rng1.Row), xlValues, xlWhole)
End With
' In Name Column
With .Columns(cNameCol)
' Check if the row of Next List Cell Range (rng2) is greater than
' the row of List Cell Range (rng1) i.e. if a cell with a value
' has been found below List Cell Range (rng1) in List Column.
If rng2.Row > rng1.Row Then ' Next List Cell Range FOUND.
' Create a reference to Name Search Range (rng2) which spans
' from the cell below Find List Cell Range (rng1) to the cell
' above the Next List Cell Range (rng2), but in Name Column.
Set rng2 = .Cells(rng1.Row + 1).Resize(rng2.Row - rng1.Row - 1)
Else ' Next List Cell Range NOT found.
' Create a reference to Name Search Range (rng2) which spans
' from the cell below Find List Cell Range (rng1) to the bottom
' cell, but in Name column.
Set rng2 = .Cells(rng1.Row + 1).Resize(.Rows.Count - rng1.Row)
End If
End With
' In Name Search Range (rng2)
With rng2
' Create a reference to Found Name Cell Range (rng1).
Set rng1 = .Find(strName, .Cells(.Rows.Count), xlValues, xlWhole)
End With
' Check if Name has not been found.
If rng1 Is Nothing Then ' Inform user and exit.
MsgBox "The name '" & strName & "' has not been found", _
vbCritical, "Name not found"
Exit Sub
End If
' Remarks:
' Source Range is calculated by moving the Found Name Cell Range (rng1)
' one cell to the right and by resizing it by Number of Columns (cCol).
' Target Range is calculated by moving the Name Cell Range one cell
' to the right and by resizing it by Number of Columns (cCol).
' Copy values of Source Range to Target Range.
.Range(cName).Offset(, 1).Resize(, cCol) _
= rng1.Offset(, 1).Resize(, cCol).Value
End With
' Inform user of succes of the operation.
MsgBox "The name '" & strName & "' was successfully found in list '" & _
strList & "'. The corresponding data has been written to the " _
& "worksheet.", vbInformation, "Success"
End Sub
One reason for being tired is that you tried to go for the kill before you had set up for slaughter. The solution below took an hour to prepare and 10 minutes to encode. Paste the entire code in a standard code module and call the function MatchRow either from the Immediate window (? MatchRow) or from your own code as shown in the test proc further down.
Option Explicit
Enum Nws ' worksheet navigation
' 01 Mar 2019
NwsCriteriaRow = 3
NwsList = 1 ' Columns: (1 = A)
NwsID = 3
NwsNumber ' (undefined: assigns next integer)
End Enum
Function MatchRow() As Long
' 01 Mar 2019
' return 0 if not found
Dim Ws As Worksheet
Dim Rng As Range
Dim R As Long
' The ActiveWorkbook isn't necessarily ThisWorkbook
Set Ws = ActiveWorkbook.Worksheets("Sheet2") ' replace tab's name here
With Ws
Set Rng = .Range(.Cells(NwsCriteriaRow, NwsList), .Cells(.Rows.Count, NwsList).End(xlUp))
R = FindRow(.Cells(NwsCriteriaRow, NwsID).Value, Rng, True)
If R Then ' skip if no match was found
Set Rng = .Cells(R + 1, NwsID)
Set Rng = .Range(Rng, Rng.End(xlDown))
MatchRow = FindRow(.Cells(NwsCriteriaRow, NwsNumber).Value, Rng)
End If
End With
End Function
Private Function FindRow(Crit As Variant, _
Rng As Range, _
Optional ByVal SearchFromTop As Boolean) As Long
' 01 Mar 2019
' return 0 if not found
Dim Fun As Range
Dim StartCell As Long
With Rng
If SearchFromTop Then
StartCell = 1
Else
StartCell = .Cells.Count
End If
Set Fun = .Find(What:=Crit, _
After:=.Cells(StartCell), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
MatchCase:=False)
End With
If Not Fun Is Nothing Then FindRow = Fun.Row
End Function
The function MatchRow returns the row number of Sheet2 where D3 is found, searching only that part of column D which belongs to the list identified in C3. The function returns 0 if no match was found, either of the list or the ID.
You didn't specify what you want to do with the found row. The procedure below will return data from that row. You might use the capability to address the cells to write to them instead.
Private Sub RetrieveData()
Dim R As Long
R = MatchRow
MsgBox "ID = " & Cells(R, NwsID).Value & vbCr & _
"Number = " & Cells(R, NwsNumber).Value
End Sub
Being intended for testing only the above proc doesn't specify the worksheet and, therefore, returns data from the ActiveSheet, presumed to be Sheet2.
VBA Solution
I think the non-VBA solution is ideal here, but I will leave this here separately just in case. This should work for your situation assuming no values in your tables are blank.
Sub Test()
Dim ws As Worksheet: Set Worksheet = ThisWorkbook.Sheets("Sheet2")
Dim iList As Range, iName As Range
Dim aLR As Long, cLR As Long
aLR = ws.Range("A" & ws.Rows.Count).End(xlUp).Row
Set iList = ws.Range("A1:A" & aLR).Find(ws.Range("C3"), LookIn:=xlWhole)
If Not iList Is Nothing Then
cLR = iList.Offset(0, 2).End(xlDown).Row
Set iName = ws.Range(ws.Cells(iList.Row, 3), ws.Cells(cLR, 3)).Find(ws.Range("C4"), LookIn:=xlWhole)
If Not iName Is Nothing Then
ws.Range("E3:G3").Value = iName.Offset(0, 1).Resize(1, 3).Value
End If
End If
End Sub
Non VBA Solution
Convert your two list ranges to tables
Change the name of your tables by (Formulas Tab > Name Manager > Select Table/Change Name). Specifically, you will want to change the names to your desired list name. (Table 1 Name = List1 & Table 2 Name = List2)
Next, drop these formulas inside E3, F3, & G3
E3 = VLOOKUP(D3, Indirect(C3), 2, 0)
F3 = VLOOKUP(D3, Indirect(C3), 3, 0)
G3 = VLOOKUP(D3, Indirect(C3), 4, 0)
This wil update dynamically as your table sizes expand. you can also add as many tables as you'd like and this will continue to work.
In use, it looks something like below
My last suggestion would be to nest each formula above inside an IFERROR()
I have column K in "filter" sheets that need to be compare with column A in "Active_Buy", "Active_Others" and "Active_Make" sheets accordingly.
First it need to be compare with active_buy sheets. if there is value that in column K (filter sheet) but not in column A (active_Buy sheet), then it need to hold that value and compare it with column A (active_others sheets). If also didnt match, it need to compared with column A (Active_Make sheets).
So, if there is no any match, then the value need to be paste in new sheets name (Unmatched Part No).
I already search everywhere but only can find code that can only compare 2 worksheets only but not more than that.
'Below is the code that i found but only compared two worksheets only
' the concept just same like this but need to hold unmatch value and compare to next worksheet and so on.
Sub compare()
Sheets(3).Activate 'Go to sheet 3
Cells.Clear 'and clear all previous results
Range("a1").Select 'set cursor at the top
Sheets(1).Activate 'go to sheet 1
Range("a1").Select 'begin at the top
Dim search_for As String 'temp variable to hold what we need to look for
Dim cnt As Integer 'optional counter to find out how many rows we found
Do While ActiveCell.Value <> "" 'repeat the follwoing loop until it reaches a blank row
search_for = ActiveCell.Offset(0, 1).Value 'get a hold of the value in column B
Sheets(2).Activate 'go to sheet(2)
On Error Resume Next 'incase what we search for is not found, no errors will stop the macro
Range("b:b").Find(search_for).Select 'find the value in column B of sheet 2
If Err <> 0 Then 'If the value was not found, Err will not be zero
On Error GoTo 0 'clearing the error code
Sheets(1).Activate 'go back to sheet 1
r = ActiveCell.Row 'get a hold of current row index
Range(r & ":" & r).Select 'select the whole row
cnt = cnt + 1 'increment the counter
Selection.Copy 'copy current selection
Sheets(3).Activate 'go to sheet 3
ActiveCell.PasteSpecial xlPasteAll 'Past the entire row to sheet 3
ActiveCell.Offset(1, 0).Select 'go down one row to prepare for next row.
End If
Sheets(1).Activate 'return to sheet 1
ActiveCell.Offset(1, 0).Select 'go to the next row
Loop 'repeat
Sheets(3).Activate 'go to sheet 3 to examine findings
MsgBox "I have found " & cnt & " rows that did not exist in sheet 2"
End Sub
I'd use a For Each loop to run through the values on the 'Filter' sheet, set ranges on each of the other sheets, then check in each of the ranges. I've tested this code and it seems to do the trick. I've commented so you can see what's going on at each line.
(You'll need to adjust the sheet names to match you own, and adjust Application settings to make things run faster if you've got a lot of data.)
Sub compareColumns()
Dim lastRow1, lastRowAB, lastRowAO, lastRowAM, lastRowUMPN As Long
Dim rng1, rngAB, rngAO, rngAM As Range
Dim cell As Range
Dim found As Range
' Define our last rows for each sheet
lastRow1 = ThisWorkbook.Worksheets("FilterSheet").Range("K" & Rows.Count).End(xlUp).Row
lastRowAB = ThisWorkbook.Worksheets("ActiveBuy").Range("A" & Rows.Count).End(xlUp).Row
lastRowAO = ThisWorkbook.Worksheets("ActiveOthers").Range("A" & Rows.Count).End(xlUp).Row
lastRowAM = ThisWorkbook.Worksheets("ActiveMake").Range("A" & Rows.Count).End(xlUp).Row
lastRowUMPN = ThisWorkbook.Worksheets("UnmatchedPartNo").Range("A" & Rows.Count).End(xlUp).Row
' Set the ranges that we'll loop through
Set rng1 = ThisWorkbook.Worksheets("FilterSheet").Range("K1:K" & lastRow1)
Set rngAB = ThisWorkbook.Worksheets("ActiveBuy").Range("A1:A" & lastRowAB)
Set rngAO = ThisWorkbook.Worksheets("ActiveOthers").Range("A1:A" & lastRowAO)
Set rngAM = ThisWorkbook.Worksheets("ActiveMake").Range("A1:A" & lastRowAM)
' Loop through each cell in the filtered sheet
For Each cell In rng1
' Try to find the value in ActiveBuy sheet
Set found = rngAB.Find(cell.Value)
' If not found, try the next sheet
If found Is Nothing Then
Set found = rngAO.Find(cell.Value)
' If not found, try the next sheet
If found Is Nothing Then
Set found = rngAM.Find(cell.Value)
' If still not found, copy to the value to the 'Unmatched Parts' sheet
If found Is Nothing Then
ThisWorkbook.Worksheets("UnmatchedPartNo").Range("A" & lastRowUMPN + 1).Value = cell.Value
MsgBox "I have found a value " & cell.Value & " that did not exist in any sheets."
End If
End If
End If
' Reset 'found' to equal nothing for the next loop
Set found = Nothing
Next
End Sub
Here's a sub that takes 2 parameters;
A cell that has the value to search for, and a number indicating the sheet to search in.
When the sub doesn't find the value in neither of the sheets, it adds a new sheet "Unmatched Part No" if it doesn't exist and adds the value that's not found in column A in that sheet:
Sub searchSheet(ByVal searchFor As Range, sheetNum As Integer)
Dim sheetsArr As Variant
sheetsArr = Array("Active_Buy", "Active_Others", "Active_Make", "Unmatched Part No") 'You can change the names of your sheets here
If sheetNum = 3 Then 'When we reach the last sheet in our array, then we haven't find a match in neither of the previous sheets
Dim ws As Worksheet, wsExist As Boolean, lastRow As Integer
wsExist = False
'Check if the sheet "Unmatched Part No" exists
For Each ws In Worksheets
If ws.Name = sheetsArr(3) Then
wsExist = True
Exit For
End If
Next ws
'If the sheet "Unmatched Part No" doesn't exist add one with this name
If Not (wsExist) Then ThisWorkbook.Sheets.Add(after:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)).Name = sheetsArr(3)
lastRow = ThisWorkbook.Sheets(sheetsArr(3)).Cells(Rows.Count, "A").End(xlUp).Row 'last used row in column A in the unmatched sheet
ThisWorkbook.Sheets(sheetsArr(3)).Range("A" & lastRow + 1).Value2 = searchFor.Value2 'append the unfound value in column A
'MsgBox "New value" & searchFor.Value2 & "appended to 'Unmatched Part No' A" & lastRow + 1
Exit Sub
End If
Dim search 'Search should be of a variant type to accept errors given by the match function
search = Application.Match(searchFor.Value2, ThisWorkbook.Sheets(sheetsArr(sheetNum)).Range("A:A"), 0)
If IsError(search) Then searchSheet searchFor, sheetNum + 1 'When match doesn't find the searchFor value, Search is an #N/A error, then search in the next sheet
End Sub
And you need another sub to call the first one passing each cell of column K of filter sheet to the first sub. Here it is:
Sub lookInSheets()
Dim lastRw As Integer, ctrlCol As Range
lastRw = ThisWorkbook.Sheets("filter").Cells(Rows.Count, "K").End(xlUp).Row 'To abbreviate the search to just the filled cells in column K
Set ctrlCol = ThisWorkbook.Sheets("filter").Range("K1:K" & lastRw)
For Each ctrlCell In ctrlCol
searchSheet ctrlCell, 0
Next ctrlCell
End Sub
Copy both subs in a new module and run the second one to achieve your goal.
I'm trying to delete all rows on my worksheet that have a unique value in column B.
I know this can be done with a filter or conditioned formatting, but I would like to know if the following is possible as well, since it could be useful in other situations:
I want to loop through all rows and store the row number in an Array if the row has a unique value in column B. Then delete all the rows whose number is stored in the Array in one single action.
The reasoning for storing the row numbers in an Array instead of deleting the desired rows in the loop is to reduce runtime.
My data varies in number of rows but is always in column A:K and it always begins on row 6.
Below is the code I've written with inspiration from the following links:
Dynamically adding values to the array on the go.
Deleting rows whose number is stored in array in one single action (see Tim Williams answer).
I get the error message: Run-time error '5': Invalid procedure call or Argument
Sub DeleteRows()
Dim ws4 As Worksheet: Set ws4 = Worksheets("Sheet1")
Dim LastRow As Long
Dim CurrentRow As Long
Dim GroupValue
Dim GroupTotal As Long
Dim MyArray()
Dim y As Long
Application.ScreenUpdating = False
ws4.Activate
GroupValue = ws4.Range("B6").Value ' Sets the first GroupValue
CurrentRow = 6 ' Sets the starting row
y = 0
LastRow = ws4.Cells(Rows.Count, "B").End(xlUp).Row
For x = 1 To LastRow
GroupTotal=Application.WorksheetFunction.CountIf(Range("B6:B"&LastRow), _
GroupValue) ' Searches for the GroupValue and finds number of matches
If GroupTotal = 1 Then ' If GroupTotal = 1 then add the row# to the array
ReDim Preserve MyArray(y)
MyArray(y) = CurrentRow
y = y + 1
End If
CurrentRow = CurrentRow + GroupTotal 'set the next row to work with
GroupValue = Range("B" & CurrentRow).Value 'set next GroupValue to find
If GroupValue = "" Then ' Checks to see if the loop can stop
Exit For
End If
Next x
'***This should delete all the desired rows but instead produces the error.***
ws4.Range("B" & Join(MyArray, ",B")).EntireRow.Delete
Application.ScreenUpdating = True
End Sub
I've researched for hours and tried to manipulate the code with no luck.
Use a variable defined as a Range and Union each row to it.
In the example below MyArray is the array of row numbers that should be deleted.
Public Sub Test()
Dim MyArray() As Variant
MyArray = Array(2, 4, 5, 8, 10, 15)
DeleteRows MyArray
End Sub
Public Sub DeleteRows(RowNumbers As Variant, Optional SheetName As String = "")
Dim wrkSht As Worksheet
Dim rRange As Range
Dim x As Long
On Error GoTo ERROR_HANDLER
If SheetName = "" Then
Set wrkSht = ActiveSheet
Else
Set wrkSht = ThisWorkbook.Worksheets(SheetName)
End If
For x = LBound(RowNumbers) To UBound(RowNumbers)
If rRange Is Nothing Then
Set rRange = wrkSht.Rows(RowNumbers(x))
Else
Set rRange = Union(rRange, wrkSht.Rows(RowNumbers(x)))
End If
Next x
If Not rRange Is Nothing Then rRange.Delete
On Error GoTo 0
Exit Sub
ERROR_HANDLER:
Select Case Err.Number
Case Else
MsgBox "Error " & Err.Number & vbCr & _
" (" & Err.Description & ") in procedure DeleteColumns."
Err.Clear
Application.EnableEvents = True
End Select
End Sub
Edit
The Test procedure can be replaced with any code that creates an array of row numbers. The array is then passed to the DeleteRows procedure. You could also pass it a sheet name to delete the rows from: DeleteRows MyArray, "Sheet2".
The DeleteRows procedure sets up the variables, turns error checking on and then checks if a sheet name was passed to it. It then sets a reference to either the active sheet or the named sheet. You could also check if the passed sheet actually exists here.
Next a loop starts going from the first to last element of the array. The first is usually 0 so you could replace LBOUND(RowNumbers) with 0.
rRange is the variable that's going to hold the row references to delete and Union won't work if it doesn't already hold a range reference.
On the first pass of the loop it won't hold a reference so will be nothing and the first row in the array will be set as the first row reference on the sheet held in wrkSht.
On subsequent passes rRange will already hold a reference so the next row will be unioned to it.
Those two decisions are made in an IF...END IF block seperated by an ELSE statement.
After the loop has finished a single line IF statement - no END IF required on single line - checks if rRange holds any references. If it does then those rows are deleted.
The procedure exits the main body of code, deals with the error handling and then ends.
Sub selecting()
Dim r as Range
Set r = Application.Selection
MsgBox r.Cells(1,1).Address(false,false)
MsgBox r.Cells(1,2).Address(false,false)
MsgBox r.Cells(2,1).Address(false,false)
End Sub
Now the thing is, I select some random cells as irregular range in excel sheet. I get first cell address correct but the next cell address is the cell neighbor to the first one, and not the next cell that I selected.
Basically, I want to collect values from irregular ranges into an array. It would be really helpful if I get addresses of each cell selected in this irregular range.
Simply saying, what I want is if I select cells e1,g4,d7,r1,t3 I should get an array of only these 5 cells in vba program, and this array should have no access to other cells apart from those that were selected.
I am a little unclear on exactly what you are attempting, but I believe this may help you understand the behavior of the script as it's running.
Sub selecting()
Dim myArray(0 To 100, 0 To 1) As Variant
Dim rngSelected As Range
Set rngSelected = Application.Selection
Dim rng As Range
For Each rng In rngSelected
Dim counter As Integer
Debug.Print "The value of cell " & counter & " is " & rng.Value & _
" , and the address is " & rng.Address(False, False)
myArray(counter, 0) = rng.Value
myArray(counter, 1) = rng.Address(False, False)
counter = counter + 1
Next rng
End Sub
Maybe you can tweak this until you get the behavior you are looking for?
I have a sheet in which I have data from two different sources.I've a blank row between them.I want to make this blank row as my delimiter.How can I find out if the entire row is blank or not.
If you're talking a literal entire row then code similar to this should work (so long as there are no formulas or spaces present in any of the cells as well):
If Application.CountA(ActiveCell.EntireRow)=0 Then
MsgBox "Row Empty"
Exit Sub
End If
Otherwise, for a range from a row:
Dim neValues As Range, neFormulas As Range, MyRange As Range
Set MyRange = Columns("C:AA")
On Error Resume Next
Set neValues = Intersect(ActiveCell.EntireRow.SpecialCells(xlConstants), MyRange)
Set neFormulas = Intersect(ActiveCell.EntireRow.SpecialCells(xlFormulas), MyRange)
On Error GoTo 0
If neValues Is Nothing And neFormulas Is Nothing Then
MsgBox "Nothing There"
Else
MsgBox "Something's There"
End If
(Source: http://www.ozgrid.com/forum/showthread.php?t=26509&page=1)
WorksheetFunction.CountA(), as demonstrated below:
Dim row As Range
Dim sheet As Worksheet
Set sheet = ActiveSheet
For i = 1 To sheet.UsedRange.Rows.Count
Set row = sheet.Rows(i)
If WorksheetFunction.CountA(row) = 0 Then
MsgBox "row " & i & " is empty"
End If
Next i