Trying something like this. My code is find the value of cell B7 of Sheet1 in column A of Sheet15. If it is not found, do nothing. If it is found, write the value in the cell next to the found value to the next available cell in column F of Sheet4.
I have this number in Sheet1
Code will find that Sheet1 value in Sheet2 Col"A" then copy the Col"B" value that is "156".
After that code will paste that "156" VALUE IN Sheet3.Range("C2") to till where Col"B" used range end.
Looking forward to your help.
Dim lastR4 As Long
lastR4 = Sheet4.Range("E" & Rows.Count).End(xlUp).Row
If Sheet15.Range("A2:B2") Is Empty Then
Exit Sub
Else
Sheet4.Range("F11:F" & lastR4).Value = Sheet15.Range("A" & _
WorksheetFunction.Match(Sheet1.Range("B7").Value, Sheet15.Range("A:A"), 0)).Offset(0, 1)
End If
Try the next slightly adapted code, please:
Sub testFillDat()
Dim lastR4 As Long
lastR4 = Sheet4.Range("E" & rows.count).End(xlUp).row
If WorksheetFunction.CountA(Sheet15.Range("A2:B2")) = 0 Then
Exit Sub
Else
If Sheet15.Range("B2") = "" Then
Sheet4.Range("F11:F" & lastR4).Value = 0
Else
Sheet4.Range("F11:F" & lastR4).Value = Sheet15.Range("A" & _
WorksheetFunction.match(Sheet1.Range("B7").Value, Sheet15.Range("A:A"), 0)).Offset(0, 1)
End If
End If
End Sub
If there is no match of "B7" (Sheet1) in "A:A" (Sheet15) the code will raise an error. It can be adapted to catch it, but I only tried to show you how checking if a range with multiple cells is empty... In rest, your code should work.
Lookup Using Application.Match
Using Application.Match is easier and cleaner then using WorksheetFunction.Match because you can test the result with IsError or IsNumeric.
The Code
Option Explicit
Sub test()
' The cell containing the lookup value.
Dim cel1 As Range
Set cel1 = Sheet1.Range("B7")
' First 'available' cell in column `E` column, but in column `F`.
Dim cel4 As Range
Set cel4 = Sheet4.Range("E" & Sheet4.Rows.Count).End(xlUp).Offset(1, 1)
' Range from cell `A1` to the last non-empty cell.
Dim rng15 As Range
Set rng15 = Sheet15.Range("A1", Sheet15.Range("A" & Sheet15.Rows.Count).End(xlUp))
' The index of the found value. If not found, returns error value.
' Therefore we use 'Variant'.
Dim cMatch As Variant
cMatch = Application.Match(cel1.Value, rng15, 0)
' Test if found with 'IsNumeric()'. You can also use 'Not IsError()'
' instead. Or even 'IsError()', but then switch the statements.
If IsNumeric(cMatch) Then
cel4.Value = rng15.Cells(cMatch).Offset(, 1).Value
MsgBox "Value '" & cel1.Value & "' copied.", vbInformation, "Success"
Else
MsgBox "Value '" & cel1.Value & "' not found.", vbCritical, "Fail"
End If
End Sub
EDIT
Adjust the sheets and cells appropriately.
Fill Range with Found Value
Sub test2()
' The cell containing the lookup value.
Dim cel1 As Range
Set cel1 = Sheet1.Range("B7")
' Range from cell 'E2' to the last non-empty cell, but column `F`.
Dim rng4 As Range
Set rng4 = Sheet4.Range("E2", Sheet4.Range("E" & Sheet4.Rows.Count) _
.End(xlUp)).Offset(, 1)
' Range from cell `A1` to the last non-empty cell.
Dim rng15 As Range
Set rng15 = Sheet15.Range("A1", Sheet15.Range("A" & Sheet15.Rows.Count) _
.End(xlUp))
' The index of the found value. If not found, returns error value.
' Therefore we use 'Variant'.
Dim cMatch As Variant
cMatch = Application.Match(cel1.Value, rng15, 0)
' Test if found with 'IsNumeric()'. You can also use 'Not IsError()'
' instead. Or even 'IsError()', but then switch the statements.
If IsNumeric(cMatch) Then
rng4.Value = rng15.Cells(cMatch).Offset(, 1).Value
MsgBox "Value '" & cel1.Value & "' copied.", vbInformation, "Success"
Else
MsgBox "Value '" & cel1.Value & "' not found.", vbCritical, "Fail"
End If
End Sub
Related
I'm trying to run this code in VBA to find out which row has the highest number in column 'A'? But it's not working. Can someone help please? Below is the Code:
Sub ForNextDemo()
Dim MaxVal As Double
Dim Row As Long
MaxVal = WorksheetFunction.Max(Range("A:A"))
For Row = 1 To Rows.Count
If Range("A1").Offset(1, 0).Value = MaxVal Then
Range("A1").Offset(1, 0).Activate
MsgBox "Maximum Value is in" & Row
Exit For
End If
Next Row
End Sub
Your code fails because you check always the same cell. No matter which value row has, Range("A1").Offset(1, 0) will always check cell A2 (1 row below A1)
What you mean is probably something like Range("A1").Offset(row, 0)
However, there is a much easier (and faster) way to get the row with the maximum value, using the Match-function.
An advice: You should tell VBA always which sheet is should use. When you write Range(A1), it will use the current active sheet. This is not always what you want. Instead, use for example ThisWorkbook.Sheets(1) (first sheet of the workbook where the code is stored). You can also use the sheet name, eg ThisWorkbook.Sheets("Sheet1")
Dim MaxVal As Double
Dim Row As Long
With ThisWorkbook.Sheets(1)
Dim r As Range
Set r = .Range("A:A")
MaxVal = WorksheetFunction.max(r)
Row = WorksheetFunction.Match(MaxVal, r, 0)
Debug.Print "The maximum value is " & MaxVal & " and it is found in row " & Row
End With
Get the Maximum and the Row of Its First Occurrence
You can avoid the loop if there are no error values in the column.
Sub ForNextDemo()
Dim ws As Worksheet: Set ws = ActiveSheet ' improve!
Dim MaxVal As Variant ' could be an error value
Dim MaxRow As Long
With ws.Range("A:A")
If Application.Count(.Cells) = 0 Then
MsgBox "There are no numbers in the column.", vbCritical
Exit Sub
End If
MaxVal = Application.Max(.Cells)
If IsError(MaxVal) Then
MsgBox "There are error values in the column.", vbCritical
Exit Sub
End If
MaxRow = Application.Match(MaxVal, .Cells, 0)
' Select and scroll to the first 'max' cell.
Application.Goto .Cells(MaxRow), True
End With
MsgBox "The maximum value is " & MaxVal & "." & vbLf _
& "Its first occurrence is in row " & MaxRow & ".", vbInformation
End Sub
I have a worksheet where column C has a formula that looks up value if column D = "Metered".
Users, who are mostly farm workers, have the ability to overwrite it (or possibly delete it using the Make Correction button). Unless column D = "Metered", I don't care if column C is overwritten because data validation makes sure entry is OK. Users are supposed to Tab past column C unless load is "Metered". As a failsafe, I duplicated the "Metered" lookup formula elsewhere and the results are in column S. I don't get any errors on code below, but it doesn't do anything -- previous versions would do things but not the right things. Clearly, I cannot solve this on my own and very much appreciate any help you can provide. I want to run the failsafe once a day when the workbook is opened (running on laptops and speed is important).
Private Sub Workbook_Open()
Application.OnTime TimeValue("02:57:00"), "SaveBeforeDailyRestart"
Application.MoveAfterReturnDirection = xlToRight
Call MeteredLookupRefreshFormula
End Sub
Sub MeteredLookupRefreshFormula()
Sheet1.Unprotect Password:="Cami8"
Dim bng As Range
Set bng = Range("D8:D10009")
For Each cell In bng
If Value = "Metered" Then
bng.Offset(0, -1).Select
Selection.Value = "S & ActiveCell.Row)"
Else
End If
Next
Sheet1.Protect Password:="Cami8"
End Sub
Loop Through Cells
A Quick Fix (Slow)
To not be dependent on the offset you could additionally do:
cell.EntireRow.Columns("C").Value = cell.EntireRow.Columns("S").Value
Sub MeteredLookupRefreshFormulaQuickFix()
With Sheet1
.Unprotect Password:="Cami8"
With .Range("D8:D10009")
Dim cell As Range
For Each cell In .Cells
If StrComp(CStr(cell.Value), "Metered", vbTextCompare) = 0 Then
cell.Offset(0, -1).Value = cell.EntireRow.Columns("S").Value
End If
Next cell
End With
.Protect Password:="Cami8"
End With
End Sub
An Improvement (Fast)
If you have many cells containing formulas evaluating to an empty string ="" at the bottom of column D, replace xlFormulas with xlValues for these cells not to be processed and speed up even more.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Refreshes...
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Calls: RefColumn,GetRange.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub MeteredLookupRefreshFormula()
Const cfcAddress As String = "D8"
Const dCol As String = "C"
Const sCol As String = "S"
Const Criteria As String = "Metered"
Const pw As String = "Cami8"
Sheet1.Unprotect Password:=pw
Dim crg As Range: Set crg = RefColumn(Sheet1.Range(cfcAddress))
If crg Is Nothing Then Exit Sub ' no data
Dim cData As Variant: cData = GetRange(crg)
Dim drg As Range: Set drg = crg.EntireRow.Columns(dCol)
Dim dData As Variant: dData = GetRange(drg)
Dim sData As Variant: sData = GetRange(crg.EntireRow.Columns(sCol))
Dim r As Long
For r = 1 To UBound(cData, 1)
If StrComp(CStr(cData(r, 1)), Criteria, vbTextCompare) = 0 Then
dData(r, 1) = sData(r, 1)
End If
Next r
drg.Value = dData
Sheet1.Protect Password:=pw
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Creates a reference to the one-column range ('crg') whose first
' cell is defined by the first cell of the range ('FirstCell')
' and whose last cell is the bottom-most non-empty cell
' of the first cell's worksheet column.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function RefColumn( _
ByVal FirstCell As Range) _
As Range
Const ProcName As String = "RefColumn"
On Error GoTo ClearError
With FirstCell.Cells(1)
Dim lCell As Range
Set lCell = .Resize(.Worksheet.Rows.Count - .Row + 1) _
.Find("*", , xlFormulas, , , xlPrevious)
If lCell Is Nothing Then Exit Function
Set RefColumn = .Resize(lCell.Row - .Row + 1)
End With
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Purpose: Returns the values of a range ('rg') in a 2D one-based array.
' Remarks: If ˙rg` refers to a multi-range, only its first area
' is considered.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function GetRange( _
ByVal rg As Range) _
As Variant
Const ProcName As String = "GetRange"
On Error GoTo ClearError
If rg.Rows.Count + rg.Columns.Count = 2 Then ' one cell
Dim Data As Variant: ReDim Data(1 To 1, 1 To 1): Data(1, 1) = rg.Value
GetRange = Data
Else ' multiple cells
GetRange = rg.Value
End If
ProcExit:
Exit Function
ClearError:
Debug.Print "'" & ProcName & "' Run-time error '" _
& Err.Number & "':" & vbLf & " " & Err.Description
Resume ProcExit
End Function
It appears as though the contents of your FOR loop is all screwed up. This is untested but change this ...
For Each cell In bng
If Value = "Metered" Then
bng.Offset(0, -1).Select
Selection.Value = "S & ActiveCell.Row)"
Else
End If
Next
... to this ...
For Each cell In bng
If cell.Value = "Metered" Then
cell.Offset(0, -1).Value = cell.Worksheet.Range("S" & cell.Row).Value
End If
Next
... and it should help.
I need a macro to add text to blank cells in Column A. The macro needs to skip cells that have text. The macro needs to stop looping at the end of the data set.
I am trying to use an If Else statement, but I think I'm on the wrong track. My current, non-working code is below. Thank you so much - I'm still new to VBA
Sub ElseIfi()
For i = 2 To 100
If Worksheets("RawPayrollDump").Cells(2, 1).Value = "" Then
Worksheets("RawPayrollDump").Cells(2, 1).Value = "Administration"
Else if(not(worksheets("RawPayrollDump").cells(2,1).value="")) then 'go to next cell
End If
Next
End Sub
To find the last row of data, use the End(xlUp) function.
Try this code. It replaces all empty cells in column A with Administration.
Sub ElseIfi()
Set ws = Worksheets("RawPayrollDump")
lastrow = ws.Cells(Rows.Count, 1).End(xlUp).Row ' last data row
For i = 2 To lastrow ' all rows until last data row
If ws.Cells(i, 1).Value = "" Then ' column A, check if blank
ws.Cells(i, 1).Value = "Administration" ' set text
End If
Next
End Sub
There is no need to loop. Please try this code.
Sub FillBlanks()
Dim Rng As Range
With Worksheets("RawPayrollDump")
Set Rng = Range(.Cells(2, "A"), .Cells(.Rows.Count, "A").End(xlUp))
End With
On Error Resume Next
Set Rng = Rng.SpecialCells(xlCellTypeBlanks)
If Err Then
MsgBox "There are no blank cells" & vbCr & _
"in the specified range.", _
vbInformation, "Range " & Rng.Address(0, 0)
Else
Rng.Value = "Administration"
End If
End Sub
Replace Blanks feat. CurrentRegion
Range.CurrentRegion
Since OP asked for "... stop looping at the end of the data set. ",
I've written this CurrentRegion version.
As I understand it, the end of the data set doesn't mean that there
cannot be blank cells below the last cell containing data in column
A.
Use the 1st Sub to test the 2nd, the main Sub (replaceBlanks).
Adjust the constants including the workbook (in the 1st Sub) to fit your needs.
Criteria is declared as Variant to allow other data types not just strings.
The Code
Option Explicit
Sub testReplaceBlanks()
Const wsName As String = "RawPayrollDump"
Const FirstCellAddress As String = "A2"
Const Criteria As Variant = "Administration"
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.Worksheets(wsName)
replaceBlanks ws, FirstCellAddress, Criteria
End Sub
Sub replaceBlanks(Sheet As Worksheet, _
FirstCellAddress As String, _
Criteria As Variant)
' Define column range.
Dim ColumnRange As Range
Set ColumnRange = Intersect(Sheet.Range(FirstCellAddress).CurrentRegion, _
Sheet.Columns(Sheet.Range(FirstCellAddress) _
.Column))
' To remove the possibly included cells above the first cell:
Set ColumnRange = Sheet.Range(Range(FirstCellAddress), _
ColumnRange.Cells(ColumnRange.Cells.Count))
' Note that you can also use the addresses instead of the cell range
' objects in the previous line...
'Set ColumnRange = sheet.Range(FirstCellAddress, _
ColumnRange.Cells(ColumnRange.Cells.Count) _
.Address)
' or a mixture of them.
' Write values from column range to array.
Dim Data As Variant
If ColumnRange.Cells.Count > 1 Then
Data = ColumnRange.Value
Else
ReDim Data(1 To 1, 1 To 1): Data(1, 1) = ColumnRange.Value
End If
' Modify array.
Dim i As Long, k As Long
For i = 1 To UBound(Data)
If IsEmpty(Data(i, 1)) Then Data(i, 1) = Criteria: k = k + 1
Next i
' Write modified array to column range.
' The following line is used when only the first cell is known...
'Sheet.Range(FirstCellAddress).Resize(UBound(Data)).Value = Data
' ...but since the range is known and is the same size as the array,
' the following will do:
ColumnRange.Value = Data
' Inform user.
If k > 0 Then GoSub Success Else GoSub Fail
Exit Sub
' Subroutines
Success:
MsgBox "Wrote '" & Criteria & "' to " & k & " previously " _
& "empty cell(s) in range '" & ColumnRange.Address & "'.", _
vbInformation, "Success"
Return
Fail:
MsgBox "No empty cells in range '" & ColumnRange.Address & "'.", _
vbExclamation, "Nothing Written"
Return
End Sub
I am trying to write a script where as it reads down an entire column starting with E2 and if a cell in that column has a particular value (for this example, let's say A, E, I, O, or U) then it enters a value of "Y" in cell F2, however it continues this pattern until it runs out of filled cells in column E.
I understand the logic of
Dim ColE As String
For ColE = 2 To Rows.Count
Next i
If E1 = "A" Or "E" Or "I" Or "O" Or "U" Then F2 = "Y"
but how do i repeat that say all the way down the entire column of E until it runs out of filled cells in column E
Here is an easy way to implement a list of OR's:
Sub marine()
Dim s1 As String, s2 As String
s1 = "AEIOU"
For i = 2 To 25
If Range("E" & i).Value <> "" Then
If InStr(s1, Range("E" & i).Value) > 0 Then
Range("F" & i).Value = "Y"
End If
End If
Next i
End Sub
Suitable option here is using the select case command with an if-loop
for i = 2 to Cells(Rows.Count, 5).End(xlUp).Row '5 = Column E
Select Case Range("E"&i).value
Case "A", "E", "I", "O", "U"
Range("F"&i).value
End Select
next
Using Select Case allows you to also give different commands for other inputs in column E and is way easier to handle than if-conditions for your specific requirements.
Cells(Rows.Count, 5).End(xlUp).Row '5
This will return the row number of the last entry in the fifth column (column E). You can use it in the for-loop to iterate until the very last row.
Search Multiple Criteria
Copy the code into a standard module (e.g. Module1).
Carefully adjust the values in the constants section.
The Code
Option Explicit
Sub searchMultipleCriteria()
' Handle Errors
Const Proc = "searchMultipleCriteria"
On Error GoTo cleanError
' Define constants.
Const SheetName As String = "Sheet1"
Const FirstRow As Long = 2
Const CriteriaCol As Variant = "E" ' 1 or "A"
Dim CriteriaVals As Variant: CriteriaVals = Array("A", "E", "I", "O", "U")
Const ResultCol As Variant = "F" ' 1 or "A"
Const ResultVal As String = "Y"
Dim wb As Workbook: Set wb = ThisWorkbook
' Write values from Criteria Column Range to Criteria Array.
Dim ws As Worksheet: Set ws = wb.Worksheets(SheetName)
Dim rng As Range
Set rng = ws.Columns(CriteriaCol).Find("*", , xlFormulas, , , xlPrevious)
If rng Is Nothing Then GoTo EmptyColumn
If rng.Row < FirstRow Then GoTo NoRange
Set rng = ws.Range(ws.Cells(FirstRow, CriteriaCol), rng)
Dim Criteria As Variant: Criteria = rng.Value
' Write values from Result Column Range to Result Array.
Set rng = rng.Offset(, ws.Columns(ResultCol).Column - rng.Column)
Dim Result As Variant: Result = rng.Value
' Modify values in Result Array.
Dim i As Long, Curr As Variant
For i = 1 To UBound(Criteria)
' Note: 'Match' is not case-sensitive i.e. A=a...
Curr = Application.Match(Criteria(i, 1), CriteriaVals, 0)
If Not IsError(Curr) Then
Result(i, 1) = ResultVal
Else ' Maybe you wanna do something here...
'Result(i, 1) = "N"
End If
Next i
' Write values from Result Array to Result Range.
rng.Value = Result
' Inform user.
MsgBox "Data transferred.", vbInformation, "Success"
' Revert Settings (not utilized in this Sub)
CleanExit:
Exit Sub
' Not As Planned
EmptyColumn:
MsgBox "Looking in an empty column to define a range with values!?", _
vbExclamation, "'" & Proc & "': Empty Column"
GoTo CleanExit
NoRange:
MsgBox "Trying to define a range with an ending row lower than " _
& "the starting row!?", _
vbExclamation, "'" & Proc & "': No Range"
GoTo CleanExit
cleanError:
MsgBox "An unexpected error occurred in '" & Proc & "'!" & vbCr _
& "Run-time error '" & Err.Number & "':" & vbCr & Err.Description, _
vbCritical, "'" & Proc & "': Unexpected Error"
On Error GoTo 0
GoTo CleanExit
End Sub
I have this code (This code is in Access VBA which tries to read an excel file and after checking, possibly import it):
Set ExcelApp = CreateObject("Excel.application")
Set Workbook = ExcelApp.Workbooks.Open(FileName)
Set Worksheet = Workbook.Worksheets(1)
now I want to iterate over all rows of the excel worksheet. I want something such as this:
for each row in Worksheet.rows
ProcessARow(row)
next row
where
function ProcessARow(row as ???? )
' process a row
' how Should I define the function
' how can I access each cell in the row
' Is there any way that I can understand how many cell with data exist in the row
end function
My questions:
How to define the for each code that it iterate correctly on all
rows that has data?
How to define ProcessARow properly
How to get the value of each cell in the row.
How to find how many cell with data exist in the row?
Is there any way that I detect what is the data type of each cell?
edit 1
The link solves on problem :
How to define the for each code that it iterate correctly on all rows that has data?
but what about other questions?
For example, how to define ProcessARow correctly?
If you need the values in the Row, you need use the 'Value' Property and after do an cycle to get each value
for each row in Worksheet.rows
Values=row.Value
For each cell in Values
ValueCell=cell
next cell
next row
Unfortunately you questions are very broad however I believe the below sub routine can show you a few ways of achieving what you are after. In regards to what datatype each cell is more involved as it depends what data type you wish to compare it to however I have included some stuff to hopefully help.
sub hopefullyuseful()
dim ws as worksheet
dim rng as Range
dim strlc as string
dim rc as long, i as long
dim lc as long, j as long
dim celltoprocess as range
set ws = activeworkbook.sheets(activesheet.name)
strlc = ws.cells.specialcells(xlcelltypeLastCell).address
set rng = ws.range("A1:" & lc)
rc = rng.rows.count()
debug.print "Number of rows: " & rc
lc = rng.columns.count()
debug.print "Number of columns: " & lc
'
'method 1 looping through the cells'
for i = 1 to rc
for j = 1 to lc
set celltoprocess = ws.cells(i,j)
'this gives you a cell object at the coordinates of (i,j)'
'[PROCESS HERE]'
debug.print celltoprocess.address & " is celltype: " & CellType(celltoprocess)
'here you can do any processing you would like on the individual cell if needed however this is not the best method'
set celltoprocess = nothing
next j
next i
'method 2 looping through the cells using a for each loop'
for each celltoprocess in rng.cells
debug.print celltoprocess.address & " is " & CellType(celltoprocess)
next celltoprocess
'if you just need the data in the cells and not the actual cell objects'
arrOfCellData = rng.value
'to access the data'
for i = lbound(arrOfCellData,1) to ubound(arrOfCellData,1)
'i = row'
for j = lbound(arrOfCellData,2) to ubound(arrOfCellData,2)
'j = columns'
debug.print "TYPE: " & typename(arrOfCellData(i,j)) & " character count:" & len(arrOfCellData(i,j))
next j
next i
set rng=nothing
set celltoprocess = nothing
set ws = nothing
end sub
Function CellType(byref Rng as range) as string
Select Case True
Case IsEmpty(Rng)
CellType = "Blank"
Case WorksheetFunction.IsText(Rng)
CellType = "Text"
Case WorksheetFunction.IsLogical(Rng)
CellType = "Logical"
Case WorksheetFunction.IsErr(Rng)
CellType = "Error"
Case IsDate(Rng)
CellType = "Date"
Case InStr(1, Rng.Text, ":") <> 0
CellType = "Time"
Case IsNumeric(Rng)
CellType = "Value"
End Select
end function
sub processRow(byref rngRow as range)
dim c as range
'it is unclear what you want to do with the row however... if you want
'to do something to cells in the row this is how you access them
'individually
for each c in rngRow.cells
debug.print "Cell " & c.address & " is in Column " & c.column & " and Row " & c.row & " has the value of " & c.value
next c
set c = nothing
set rngRow = nothing
exit sub
if you want your other questions answered you will have to be more specific as to what you are trying to accomplish
While I like the solution offered by #krazynhazy I believe that the following solution might be slightly shorter and closer to what you asked for. Still, I'd use the CellType function offered by Krazynhazy rather than all the Iif I currently have in the below code.
Option Explicit
Sub AllNonEmptyCells()
Dim rngRow As Range
Dim rngCell As Range
Dim wksItem As Worksheet
Set wksItem = ThisWorkbook.Worksheets(1)
On Error GoTo EmptySheet
For Each rngRow In wksItem.Cells.SpecialCells(xlCellTypeConstants).EntireRow.Rows
Call ProcessARow(wksItem, rngRow.Row)
Next rngRow
Exit Sub
EmptySheet:
MsgBox "Sheet is empty." & Chr(10) & "Aborting!"
Exit Sub
End Sub
Sub ProcessARow(wksItem As Worksheet, lngRow As Long)
Dim rngCell As Range
Debug.Print "Cells to process in row " & lngRow & ": " & wksItem.Range(wksItem.Cells(lngRow, 1), wksItem.Cells(lngRow, wksItem.Columns.Count)).SpecialCells(xlCellTypeConstants).Count
For Each rngCell In wksItem.Range(wksItem.Cells(lngRow, 1), wksItem.Cells(lngRow, wksItem.Columns.Count)).SpecialCells(xlCellTypeConstants)
Debug.Print "Row: " & lngRow, _
"Column: " & rngCell.Column, _
"Value: " & rngCell.Value2, _
IIf(Left(rngCell.Formula, 1) = "=", "Formula", IIf(IsDate(rngCell.Value), "Date", IIf(IsNumeric(rngCell.Value2), "Number", "Text")))
Next rngCell
End Sub
Note, that you have to call the sub to call a row must also include the sheet on which a row should be processed.