【问题标题】:Issue passing an Excel array formula to a VBA function [duplicate]将 Excel 数组公式传递给 VBA 函数的问题 [重复]
【发布时间】:2021-08-21 02:46:58
【问题描述】:

我有以下场景(在 excel 2010 中):

  • 2 列,一列包含用户名列表,另一列包含相关电子邮件地址(我为它们分配了命名范围:UserName 和 UserEmail)。
  • 一个单元格 (“D2”),其中包含来自 UserName 的唯一用户名列表(由用户选择),用“,”分隔(例如:“user5, user3, user9”)。
  • 我需要解决的问题是在 UserEmail 中查找与所选用户相对应的电子邮件地址,用它们创建一个字符串,用“,”分隔并将其分配给一个单元格(例如:“u5@email. com, u3@email.com, u9@email.com”在 D5)

在我尝试将以下数组公式传递给用于将数组合并为字符串的函数(函数“Merge”)之前,一切似乎都运行良好:

    {=Merge(INDEX(UserEmail,MATCH(TRIM(MID(SUBSTITUTE(D2,",",REPT(" ",199)),(ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1))-(ROW(D2)))*199+((ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1)))=(ROW(D2))),199)),UserName,0)))}

我得到了#VALUE!错误。我在相邻单元格中使用 shift+Ctrl+Enter 检查了公式,它给出了正确的电子邮件地址。问题出在我要传递的数组中。

函数如下:

    Public Function Merge(arr As Variant) As String
    Dim tmpArr
        tmpArr = Application.WorksheetFunction.Transpose((arr))
        Merge = Join(tmpArr, ", ")
    End Function

我一直在试图找出为什么会出现此错误,但我真的不知道。我希望有人能帮助我。 真正让我困惑的是,如果我将数组公式传递到 MATCH 部分,它会按预期工作:

    {=Merge(MATCH(TRIM(MID(SUBSTITUTE(D2,",",REPT(" ",199)),(ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1))-(ROW(D2)))*199+((ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1)))=(ROW(D2))),199)),UserName,0))}

我得到“5, 3, 9”(用户名中所选用户的正确索引)。那么当我添加 INDEX 部分时,数组会发生什么? 我也尝试使用 VLOOKUP 并得到同样的错误:

    {=Merge(VLOOKUP(TRIM(MID(SUBSTITUTE(D2,",",REPT(" ",199)),(ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1))-(ROW(D2)))*199+((ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1)))=(ROW(D2))),199)),A2:B11,2))}

目前我求助于解决方法,但我不太喜欢:

    {="B" & SUBSTITUTE(Merge(MATCH(TRIM(MID(SUBSTITUTE(D2,",",REPT(" ",199)),(ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1))-(ROW(D2)))*199+((ROW(OFFSET(D2,,,LEN(D2)-LEN(SUBSTITUTE(D2,",",""))+1)))=(ROW(D2))),199)),UserName,0)+1),", "," & "", "" & B")}

这会产生“B6 &”、“& B4 &”、“& B10”(我在索引中添加了 1,因为在 A1 和 B1 中有标题),然后将其传递给 Evaluate 函数:

    Function ev(r As String) As Variant
        ev = Evaluate(r)
    End Function

这样我就可以在“D5”中使用公式 =ev(D4) 并获取我需要的电子邮件地址。 不过,我真的希望有人能告诉我一种通过初始公式的方法,以避免这种解决方法,或者建议我一个更优雅的解决方案。谢谢。

【问题讨论】:

    标签: arrays excel array-formulas


    【解决方案1】:

    由于您仍然使用 VBA UDF,您可以将其余公式合并到 UDF 中,如下所示。

    Public Function ConcatIf(rngCrit As Range, strDelim As String, rngToLookup As Range, rngToReturn As Range) As String
        Dim rng As Range
        Dim i As Long
        Dim varChkArr
        varChkArr = Split(rngCrit.Cells(1, 1).Value, strDelim)
        For i = LBound(varChkArr) To UBound(varChkArr)
            If IsNumeric(Application.Match(Trim(varChkArr(i)), rngToLookup, 0)) Then
                ConcatIf = ConcatIf & " " & Application.Index(rngToReturn, Application.Match(Trim(varChkArr(i)), rngToLookup, 0))
            End If
        Next i
        ConcatIf = Replace(Trim(ConcatIf), " ", ", ")
    End Function
    

    然后实现它,公式如下所示:

    =ConcatIf(D2,",",UserName,UserEmail)

    【讨论】:

    • 谢谢 shrivallabha.redij,这对我有用并且适合我的需要。我的第一个想法是完全避免使用 UDF,这就是我坚持使用数组公式的原因。然后我做不到,尝试了我在其他项目中已经使用的 Merge 功能。我仍然想了解传递数组公式的正确方法是什么。即使您的解决方案已经很好,如果有人能给我一些解释,那就太好了。谢谢。
    【解决方案2】:

    经过更深入的搜索,我在@jeffreyweir 的这篇精彩帖子中找到了我的问题的答案: https://stackoverflow.com/a/47189998/16110499 通过他建议的惊人解决方案,我能够解决我的问题。 总结一下,他解释说 INDEX 函数只将第一个元素传递给另一个函数。但是,有一些方法可以“取消引用”INDEX,以便您可以直接在其他公式中使用它的结果;其中一种方法是通过添加一个额外的位来包含范围参数来稍微修改 INDEX 函数。这是一个例子:

    原始公式(无法正常工作):=SUM(INDEX(Data,Elements))

    新公式(有效):=SUM(INDEX(Data, N(IF({1},Elements))))

    我添加了这个,以防万一有人遇到同样的问题:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-17
      • 1970-01-01
      • 1970-01-01
      • 2013-08-13
      • 2021-07-15
      相关资源
      最近更新 更多