Loops 用于循环的excel自定义函数
我是excel VB的新手,因此我希望有人能帮助我: 我试图计算第一个单元格的行号,该单元格在列中没有值0(例如:如果为0,则1应给我4),但很难将其显示在工作表上, 这是我的密码-Loops 用于循环的excel自定义函数,loops,excel,vba,Loops,Excel,Vba,我是excel VB的新手,因此我希望有人能帮助我: 我试图计算第一个单元格的行号,该单元格在列中没有值0(例如:如果为0,则1应给我4),但很难将其显示在工作表上, 这是我的密码- 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
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
功能模块1(y为整数)
作为整数的Dim x
x=1
将a变暗为整数
a=0
当x<100或a为0时,执行此操作
如果单元格(x,y).Value=1,则
a=x
x=x+1
环
单元格(y,101)。值=a
端函数
y是我要获取此函数的列号,共有100列。您声明了一个函数“Module1”。函数的名称不好,因为“Module1”过去是代码容器“Module1”的名称 因此: 按Alt+F11,右键单击项目,添加模块(自动编号为新模块命名为Module1、Module2等),键入以下代码:
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
这就是如何使用(公共)功能
重要提示:不能在从工作表调用的函数中更改单元格值:
单元格(y,101)。值=a
您可以在子方法中执行此操作,除了其他响应所做的操作外,还可以执行以下几点:
- 根据您的代码,您似乎正在循环100行,而
结果显示在第
x行中(这是数据的第一个非零行) 列
)和列y
。这是你真正想要的吗101
- 为什么是函数而不是子例程? 除非您想从电子表格中使用它(一般来说,在这种情况下,您只能更改调用它的单元格的内容),否则函数在这里没有用处。如果将一个函数的返回值赋给另一个变量,这将非常有用
- 如果超过了行
,代码将崩溃,这是32767
整数所能容纳的最大数字。我可以看出您需要代码一直运行到第100行,但我建议使用
,这 更健壮,评估速度更快Long
- 当单元格值等于1时,代码在条件
下退出循环。在描述中,您声明要获取第一个非零单元格的行号,通常,它不必是第一个等于1的非零单元格。你到底想要哪一个a0
- 实际上,有一个技巧可以完全避免循环(见下文)
子测试1() 测试1 端接头 '可选将默认值传递给参数。 '如果此处未给出值,则y=1 子测试(可选y,长度=1) 暗x等长 附页1 x=.Evaluate(“匹配(1,--(&.Range(.Cells(1,y),.Cells(100,y))。地址和“0”,0)”) .单元(101,y)=x 以 端接头
EVALUATE
解析excel公式
这个想法是
- 数组部分是(例如列
)A
,它是二进制的 看起来像A1:A1000
{FALSE,FALSE,…,TRUE,…}
计算结果为--{FALSE,FALSE,…,TRUE,…}
{0,0,…,1,…}
返回找到的第一个MATCH(1,{0,0,…,1,…},0)
的位置1
- 我还将把这个表达式包装在
语句中,以控制如果所有值都是IFERROR
会发生什么0
Control+Shift+Enter
确认),从VBA
输入时会自动进行
我希望这有帮助 我不反对为这个函数设置函数。函数返回值,子函数不返回值。它实际上并不特定于单元内公式,因为利用其他SUB中的函数将您的设计模块化为可重用代码并防止重复维护性较差的代码非常有用。@PortlandRunner我同意模块化论点,并且函数的使用不特定于单元内公式。我的感觉是,模块化的论点在这个特定的上下文中是不相关的(使用sub不会使设计变得不那么模块化),如果OP不打算从单元格调用这个过程,我认为sub是一个更优雅的选择。此外,OP似乎没有从其原始代码的函数返回任何内容,因此我怀疑他可能首先不知道
sub
s。
=GetNonZeroRank(A1:A100)
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