use*_*266 2 excel vba function
我正在尝试在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
Run Code Online (Sandbox Code Playgroud)
它基本上会这样做:
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
Run Code Online (Sandbox Code Playgroud)
如果right cell = valuex(例如字符串"System")类似于valuex,则将左单元格值放在公式/函数单元格中并删除左列值.
但无论我编程什么,它返回的都是零(0)或名称#错误.
请帮忙
您正在编写用户定义函数(UDF),即Public Function可以从工作表单元格调用的公共标准模块中 - 这种特定类型的函数具有一组特定的约束.例如,不允许有副作用.UDF接受一些输入,处理它,然后返回结果.
所以UDF 的签名应如下所示:
Public Function {name}({args}) As {type}
Run Code Online (Sandbox Code Playgroud)
当你编写一个函数时,首先要考虑的是你需要它返回什么=MYFUNCTION(A1,A2) - 换句话说,在计算之后,所说的单元格应该包含什么.例如,如果你编写了一个Add将两个Double值一起添加的函数,你会希望它返回一个Double:
Public Function Add(ByVal value1 As Double, ByVal value2 As Double) As Double
Run Code Online (Sandbox Code Playgroud)
所述主体的函数的计算结果根据给定的参数:
    Dim result As Double
    result = value1 + value2
Run Code Online (Sandbox Code Playgroud)
在返回/退出之前,您需要分配函数的返回值.这是通过分配函数的标识符来完成的:
    Add = result
Run Code Online (Sandbox Code Playgroud)
Excel的计算引擎然后获取该结果,这就是具有公式的单元格如何=Add(2, 2)以值结束4.
您的STATUS函数依赖于ActiveCell,它是当前在以下选择的任何单元格ActiveSheet:它不是调用该函数的单元格.如果选择任何随机单元格,重新计算工作簿可能会产生损坏的结果.
作为UDF,不允许.ClearContents在单元格上(或以任何方式影响任何其他单元格) - 这就是函数为#NAME?进入条件块的执行路径返回错误的原因,并且因为没有分配返回值,另一个执行路径产生0,这是Empty变量的数字表示,这是您的函数当前返回的.
如果UDF需要知道另一个单元格的值,那么最好的办法就是将该单元格的值作为参数:这种方式可以正常运行,而不需要对工作表的布局做任何假设.VLOOKUP如果没有lookup_value参数而是从.Offset(0, 1)单元格中获取该值,那么它会有用吗?会有骚乱!
当你的要求是做某事而不是计算/计算某事时,你需要的不是UDF,而是宏.
宏是公共标准模块(或模块)中的无参数 Public Sub过程Worksheet,可以从"宏"窗口调用,或者在用户单击一个ShapeActiveX 时执行CommandButton,或者可以将它们分配给OnAction某些属性自定义菜单项 - 无论你的船是什么岩石.
Sub程序做什么,他们的行动.他们可以访问和更改全局状态,修改任何单元格,工作表或工作簿; 他们甚至可以生成一个PowerPoint实例并将图表粘贴到一个新的Slide- 你可能想到的任何东西,天空是极限!
因为你需要的东西是做的东西,你需要编写的代码需要更像宏.别叫它STATUS; 使用动词并描述它正在做什么:您根据给定的标准将值从一列移动到另一列.编写Sub过程时,首先要考虑如何调用它.
我觉得这样的事情会很整洁:
MoveValues Sheet1.Range("$B$2:$B$22"), "System"
Run Code Online (Sandbox Code Playgroud)
因此,签名是这样的:
Private Sub MoveValues(ByVal Target As Range, ByVal Criteria As String)
Run Code Online (Sandbox Code Playgroud)
并且身体现在可以遍历指定的Target范围,评估右边的单元格是否匹配Criteria,然后相应地将值移动到左侧.或者更好 - 我们根本不假设工作表布局,并像这样调用它:
With Sheet1
    MoveValues .Range("A2:A22"), .Range("B2:B22"), .Range("C2:C22"), "System"
End With
Run Code Online (Sandbox Code Playgroud)
现在,如果我们需要在A和B之间,或者在B和C之间插入一个列,我们只需要更改我们传递给过程的参数,而不是过程本身!
Private Sub MoveValues(ByVal Source As Range, ByVal Target As Range, ByVal Status As Range, ByVal Criteria As String)
Run Code Online (Sandbox Code Playgroud)
但首先,我们需要验证我们的假设,并在未达到预期时决定做什么 - 我们需要具有相同行数的单列范围!
在许多情况下,提出运行时错误是最好的办法.错误#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
Run Code Online (Sandbox Code Playgroud)
我们甚至可以自定义错误消息,以便稍后调试调用代码,当我们在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
Run Code Online (Sandbox Code Playgroud)
我们还需要验证我们Criteria的不是空的,或者只是空白!
    If Trim$(Criteria) = vbNullString Then
        Err.Raise 5, "MoveValues", "Criteria string cannot be empty or whitespace."
    End If
Run Code Online (Sandbox Code Playgroud)
现在我们已经验证了我们的输入,其余的过程可以安全地假设Source,Target并且Status范围都是单列范围,它们的大小都相同,并且我们有一个有效的标准可以使用.所以我们可以继续迭代单元格并做我们的事情:
    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
Run Code Online (Sandbox Code Playgroud)
现在剩下要做的就是编写一个调用它的宏:
Public Sub MoveSystemValues()
    With Sheet1
        MoveValues .Range("A2:A22"), .Range("B2:B22"), .Range("C2:C22"), "System"
    End With
End Sub
Run Code Online (Sandbox Code Playgroud)
现在我们可以MoveSystemValues从Excel的宏窗口运行该宏,或者分配MoveSystemValues给某些Shape或按钮......然后意识到它适用于少量行,但是在较大范围内相当慢 - 但我们有足够的咀嚼现在.