Reputation: 25
I'm a newbie to excel VB so I hope some one can help me with this: I'm trying to calculate the row number of the first cell which doesn't have the value zero in a column(eg:if it's 0 0 0 1 should give me 4) but have a hard time in making it display on the worksheet, Here is my code-
Function Module1(y As Integer)
Dim x As Integer
x = 1
Dim a As Integer
a = 0
Do While x < 100 Or a <> 0
If Cells(x, y).Value = 1 Then
a = x
x = x + 1
Loop
Cells(y, 101).Value = a
End Function
y is the column number I want to get this function and there are 100 columns.
Upvotes: 0
Views: 2203
Reputation: 5388
A few points, in addition to those made by the other responses:
By your code it seems that you are looping over 100 rows and the
result is displayed in row x
(which is the first non zero row of
column y
) and column 101
. Is this what you really want?
Why a function and not a subroutine? Unless you want to use it from the spreadsheet (in which case you can change only the content of the cell from which you call it, generally speaking), a function is not useful here. It would be useful if you would assign the return value of a function to another variable.
your code will crash if you go more than row 32,767
, which is the biggest number an Integer
can hold. I can see that you need your code to run until row 100, but I would suggest using Long
, which
is more robust and actually faster to evaluate.
a<>0
when a cell value equals one. In your description you state that you want to get the row number of the first non-zero cell, which, in general, it does not have to be the first non-zero cell that equals to 1. Which of the two do you actually want?Actually, there is a trick that avoids the loop altogether (see below).
Sub test1()
test 1
End Sub
' Optional passes a default value to the argument.
' If no value is given here, then y = 1
Sub test(Optional y As Long = 1)
Dim x As Long
With Sheet1
x = .Evaluate("MATCH(1,--(" & .Range(.Cells(1, y), .Cells(100, y)).Address & "<>0),0)")
.Cells(101, y) = x
End With
End Sub
The above uses EVALUATE
to parse an excel formula.
The idea is that
A
) A1:A100<>0
, which is a binary
array that looks like {FALSE, FALSE, ..., TRUE, ...}
--{FALSE, FALSE, ..., TRUE, ...}
Evaluates to {0, 0, ..., 1, ...}
MATCH(1,{0,0, ...,1, ...},0)
returns the position of the first 1
that is foundIFERROR
statement to control what happens if all values are 0
.We can actually test the excel version of this formula in a cell. It has to be array entered (confirmed with Control + Shift + Enter
), which happens automatically when entered from VBA
.
I hope this helps!
Upvotes: 0
Reputation: 702
You declare a function 'Module1'. Not a good name for a function because 'Module1' used to be the name of the code container 'Module1'.
So:
press Alt+F11, right click on your Project, add a module (autonumbering gives your new module the name Module1, Module2 etc), type this code:
Public Function GetNonZeroRank(r As Range)
x = 1
Do While x <= r.Rows.Count And a = 0
If r.Cells(x, 1).Value <> 0 Then
a = x
End If
x = x + 1
Loop
GetNonZeroRank = a
End Function
You can use this function from cell A101: type in the formula:
=GetNonZeroRank(A1:A100)
Thats how to use (Public) Functions
Important: you can't change cell values from inside a function called from a sheet:
Cells(y, 101).Value = a
you can do this inside a Sub method
Upvotes: 1