gpt4 book ai didi

excel - 具有参数的Excel自定义函数

转载 作者:行者123 更新时间:2023-12-02 23:34:26 35 4
gpt4 key购买 nike

我正在尝试在excel模块中创建一个自定义函数,如下所示:

Function STATUS(valuex As String)

If ActiveCell.Offset(0, 1).Value = valuex Then

ActiveCell.Value = ActiveCell.Offset(0, -1).Value

'Remove value from left column
Activecell.offset(0,1).clearcontents

End If

End Function


它基本上会这样做:

Number  Result  Status
11 System
22 Type
33 System
44 System
55 Hardware
66 Type
77 System
88 System
99 Software
110 Type
121 System
132 System
143 Hardware
154 Type
165 Type
176 System
187 Hardware
198 Type
209 Software


如果右单元格= valuex(例如字符串“ System”)类似于valuex,则
将左单元格的值放在公式/函数单元格中,然后删除左列的值。

但是我编写的所有程序返回的都是零(0)或Name#错误。

请帮忙

最佳答案

您正在用公共标准模块编写用户定义函数(UDF),即Public Function,可以从工作表单元格中调用它-这种特定类型的函数具有特定的约束集。例如,不允许有副作用。 UDF接受一些输入,对其进行处理,然后返回结果。

因此,UDF的签名应如下所示:

Public Function {name}({args}) As {type}


编写函数时,首先要考虑的是返回它需要什么-换句话说,计算出 =MYFUNCTION(A1,A2)的单元格应该包含什么。例如,如果您编写了一个 Add函数,将两个 Double值加在一起,则希望它返回一个 Double

Public Function Add(ByVal value1 As Double, ByVal value2 As Double) As Double


函数的主体根据给定的参数计算结果:

    Dim result As Double
result = value1 + value2


在返回/退出之前,您需要分配函数的返回值。这是通过分配给函数的标识符来完成的:

    Add = result


然后,Excel的计算引擎将获得该结果,这就是具有 =Add(2, 2)之类的公式的单元格以 4值结束的方式。



您的 STATUS函数依赖于 ActiveCell,这是 ActiveSheet当前选择的任何单元格:不是调用该函数的单元格。如果选择了某些随机单元格,则重新计算工作簿可能会产生错误的结果。

作为UDF,不允许在某个单元格上使用 .ClearContents(或以任何方式影响任何其他单元格)-这就是该函数为进入条件块的执行路径返回 #NAME?错误的原因,并且没有分配返回值,其他执行路径产生 0,这是 Empty变量的数字表示,这是您的函数当前返回的内容。

如果UDF需要了解另一个单元格的值,则最好的办法是将该单元格的值作为参数:这样一来,该函数就可以工作,而无需任何关于工作表布局的假设。如果 VLOOKUP不使用 lookup_value参数,而是从 .Offset(0, 1)单元格中获取该值,它将有多大用处?会有骚乱!



当您需要执行某项操作而不是计算/计算某些操作时,所需的不是UDF,而是宏。

宏是公共标准模块(或 Public Sub模块)中的无参数 Worksheet过程,可以从“宏”窗口调用该宏,也可以在用户单击ActiveX Shape CommandButton时执行>,或者可以将它们分配给某些自定义菜单项的 OnAction属性-无论您的船摇动什么。

Sub程序做了一些事情,它们是动作。他们可以访问和更改全局状态,修改任何单元格,工作表或工作簿;他们甚至可以生成PowerPoint实例,然后将图表作为图片粘贴到新的 Slide上-您可能会想到的一切都是天空的极限!

由于这里需要的是可以完成工作的东西,因此需要编写的代码必须更像是宏。不要称它为 STATUS;使用动词并描述其作用:您正在根据给定的条件将值从一列移动到另一列。编写 Sub过程时,请先考虑如何调用它。

我认为这样会很整洁:

MoveValues Sheet1.Range("$B$2:$B$22"), "System"


所以签名看起来像这样:

Private Sub MoveValues(ByVal Target As Range, ByVal Criteria As String)


现在,主体可以遍历指定的 Target范围,评估右侧的单元格是否与 Criteria匹配,然后相应地将值向左移动。或者更好-我们根本不假设工作表布局,而是这样调用它:

With Sheet1
MoveValues .Range("A2:A22"), .Range("B2:B22"), .Range("C2:C22"), "System"
End With


现在,如果我们需要在A与B之间或B与C之间插入一列,我们只需要更改传递给过程的参数,而不是过程本身!

Private Sub MoveValues(ByVal Source As Range, ByVal Target As Range, ByVal Status As Range, ByVal Criteria As String)


但是首先,我们需要验证我们的假设,并确定在未达到期望值时该怎么做-我们需要行数相等的单列范围!

在许多情况下,最好是执行运行时错误。错误#5“无效的过程调用或参数”似乎很合适:

    If Source.Columns.Count <> 1 Or Target.Columns.Count <> 1 Or  Status.Columns.Count <> 1 Or _
Source.Rows.Count <> Target.Columns.Count Or _
Status.Rows.Count <> Target.Columns.Count _
Then
Err.Raise 5
End If


我们甚至可以自定义错误消息,以帮助我们稍后调试调用代码,当我们在此行的6个月后更改参数并忘记有关该 MoveValues过程的假设的所有信息时:

    If Source.Columns.Count <> 1 Or Target.Columns.Count <> 1 Or  Status.Columns.Count <> 1 Or _
Source.Rows.Count <> Target.Columns.Count Or _
Status.Rows.Count <> Target.Columns.Count _
Then
Err.Raise 5, "MoveValues", _
"Source, Target, and Status ranges must be 1 column and the same number of rows."
End If


我们还需要验证我们的 Criteria不是空的还是空白!

    If Trim$(Criteria) = vbNullString Then
Err.Raise 5, "MoveValues", "Criteria string cannot be empty or whitespace."
End If


既然我们已经验证了输入,接下来的过程可以安全地假设 SourceTargetStatus范围都是单列范围,并且它们都具有相同的大小,并且有效的标准。这样我们就可以迭代细胞并做我们的事情:

    Dim current As Long
For current = 1 To Target.Rows.Count
If Status.Cells(current).Value = Criteria Then
Target.Cells(current).Value = Source.Cells(current).Value
Source.Cells(current).ClearContents
End If
Next


现在剩下要做的就是编写一个调用它的宏:

Public Sub MoveSystemValues()
With Sheet1
MoveValues .Range("A2:A22"), .Range("B2:B22"), .Range("C2:C22"), "System"
End With
End Sub


现在我们可以从Excel的“宏”窗口运行该 MoveSystemValues宏,或将 MoveSystemValues分配给某些 Shape或按钮...,然后意识到对于少量的行它可以很好地工作,但是给定的速度很慢范围更大-但我们现在有足够的咀嚼空间。

关于excel - 具有参数的Excel自定义函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52096953/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com