使用 VBA 将用户定义的函数输入到列中

Posted

技术标签:

【中文标题】使用 VBA 将用户定义的函数输入到列中【英文标题】:Enter User Defined Function into Column Using VBA 【发布时间】:2018-12-20 17:17:10 【问题描述】:

我目前正在我的工作簿第 2 表的 J 列中使用一个公式,该公式将从第 1 表的 5 列中查找值并返回相应的文本。例如,如果工作表 2 上 M 列中的值与工作表 1 上 J 列中的任何值匹配,它将返回“N”,如果不匹配,它将在 K 列中查找,如果匹配其中的任何值,则返回 D,依此类推.我在 VBA 中这样做,所以使用的公式是

ActiveSheet.Range("J2:J" & intLastRow).FormulaR1C1 = _
    "=IFERROR(IF(ISNUMBER(MATCH(RC[3],Sheet1!C10,0)),""N"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C11,0)),""D"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C12,0)),""R"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C13,0)),""G"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C14,0)),""F"",""""))))), """")"

这个公式效果很好,并填写了相应的值。然后,我创建了一个用户定义的函数,它将查找 J 列中与 C 列中的 ID 号相关联的所有值,并用逗号分隔它们。此功能在输入单元格时也能正常工作。

Function get_areas(ID As String) As String
Dim rng As Range, cel As Range

Set rng = Range("A2:A" & Cells(rows.count,1).End(xlUp).Row)

Dim areas As String
For Each cel In rng
If IsNumeric(Left(cel, 1)) And cel.Offset(0, 2) = ID Then
    If InStr(1, areas, cel.Offset(0, 9)) = 0 Then
        areas = cel.Offset(0, 9) & ", " & areas
    End If
End If
Next cel

areas = Trim(Left(areas, Len(areas) - 2))
get_areas = areas
End Function

理想情况下,我想做的是在 J 列中的所有单元格中运行原始公式,这些单元格不以 A 列中的 Master 开头,然后在所有以 master 开头的单元格中运行 get_areas($C2) 函数在 A 列中。如果这不可行,那么我想在 VBA 中的所有空白单元格中运行 get_areas 函数(这意味着它们没有从原始公式返回任何内容,但仍然有公式)。我已经尝试修改原始公式以阅读

ActiveSheet.Range("J2:J" & intLastRow).FormulaR1C1 = 
"=IFERROR(IF(LEFT(RC[-9],6)=""master"", get_areas(RC[-7]),             
IF(ISNUMBER(MATCH(RC[3],Sheet1!C10,0)),""N"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C11,0)),""D"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C12,0)),""R"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C13,0)),""G"", 
IF(ISNUMBER(MATCH(RC[3],Sheet1!C14,0)),""F"","""")))))), """")"

但收到有关 get_areas 函数的错误。

【问题讨论】:

你得到什么错误? @BigBen 我得到运行时错误'5':无效的过程调用或参数,当我调试它时,它会突出显示这部分功能 area = Trim(Left(areas, Len(areas ) - 2)). Len(areas) 那时可能不大于 2。 @BigBen 但是,如果我只是将公式 =get_areas(C2) 输入到单元格 J2 中,它可以工作,所以我不确定问题是什么。 无论哪种方式,您都需要在尝试使用Left(areas, Len(areas) - 2)之前检查If Len(areas) > 2 【参考方案1】:

WorksheetFunction.Trim

所有这些可能与您的情况无关,但在某些类似情况下可能有用。它只是一直在我的脑海里响起,当你无法闭嘴时,你知道它是怎么回事。

我会这样写函数:

Function get_areas(ID As String) As String

Dim rng As Range
Dim i As Long
Dim areas As String

Set rng = Range("A2:A" & Cells(Rows.Count, 1).End(xlUp).Row)

With rng
    For i = 1 To .Cells.Count
        If IsNumeric(Left(.Cells(i, 1))) And .Cells(i, 1).Offset(0, 2) = ID Then
            If InStr(1, areas, .Cells(i, 1).Offset(0, 9)) = 0 Then
                If i > 1 Then
                    areas = areas & ", " & .Cells(i, 1).Offset(0, 9)
                  Else
                    areas = .Cells(i, 1).Offset(0, 9)
                End If
            End If
        End If
    Next
End With

get_areas = WorksheetFunction.Trim(areas)

End Function

这根本不像'WorksheetFunction'部分那么重要。

WorksheetFunction.Trim 去除单词之间除了单个空格之外的所有空格,而 VBA 的Trim 函数只去除左右空格。

另一个最明显的区别是“If i > 1”块。

【讨论】:

欣赏编辑!当我尝试使用此代码时,我收到“参数不是可选”错误,并在 If IsNumeric 之后突出显示“左”。 我忘了左边的第二个参数。我应该是'IsNumeric(Left(.Cells(i,1),1))'。对不起。 谢谢!此代码有效,但它们都以“,”或“,”等开头,而不是字母本身,这可能是 Trim 的用途。 也许 'If Instr' 应该是 ' 0',我的意思是我不知道代码的作用。您显然得到了空的分隔值。 嗯,我不确定。你知道我怎么能把它变成一个 Sub 而不是一个函数吗?

以上是关于使用 VBA 将用户定义的函数输入到列中的主要内容,如果未能解决你的问题,请参考以下文章

由于无效的参数输入,VBA 用户定义的函数未运行

工作表循环用户定义的功能故障

使用用户定义函数 (VBA) 引发错误

EXCEL 的自定义 VBA 函数中的用户定义警告

在表列中查找值并返回表行号 - VBA

VBA 用户定义函数返回奇怪或没有结果