【问题标题】:Referencing Dynamic Named Range in Excel Formula在 Excel 公式中引用动态命名范围
【发布时间】:2013-01-29 04:42:22
【问题描述】:

我在 Excel 中有一个表格,其列标题对应于我工作簿中其他地方的动态命名范围的一部分。例如,我有这些列标题:“10”、“20”等,以及这些动态命名范围:“ExampleRange10”、“ExampleRange2”等。我想通过连接输入引用 ExampleRange10 的 VLookup 公式字符串“ExampleRange”和列标题“10”。这将允许我简单地将公式扩展到表中的所有列,而不是在每列的公式中手动键入“ExampleRange10”、“ExampleRange20”等。

我知道 INDIRECT 函数,并且过去曾成功地将它用于命名范围,但在这种情况下,它似乎不适用于 dynamic 命名范围。我猜这是一个细微差别,与 Excel 如何定义动态命名范围有关(它们不会显示在公式栏左侧的命名范围下拉列表中,并且它们在 VBA 中有一些有趣的属性, 例如)。有没有一种方法可以将 INDIRECT 公式与动态命名范围结合使用,或者有其他方法可以解决这个问题吗?

编辑:以下是使用的确切公式。
这是主要公式:=VLOOKUP(B2,INDIRECT("ExampleRange"&C1),2,FALSE),其中 C1 包含“10”,我的名为“ExampleRange10”的动态命名范围的公式是:=OFFSET(Sheet1!$F$2,0,0,COUNTA(Sheet1!$F$2:$F$25),2)。主公式返回“#REF!”,但当我删除动态命名范围公式并将“ExampleRange10”简单地定义为静态范围时,它可以正常工作。

【问题讨论】:

  • 能否请您提供不起作用的确切公式?
  • 您可以使用offset() 和 column() 的某种组合,具体取决于您的确切布局。
  • @KyleWurtz =VLOOKUP(B5,INDIRECT("range"&C1),1,0) 在 Excel 2007 中对我来说很好用。你确定公式的其余部分没有错误,例如第三个参数 - 要返回的范围内的列号?
  • @PeterL。嗯。你的“range10”是动态的吗?我仔细检查了我的公式和范围,但找不到任何错误。当我转到名称管理器并单击“引用”框时,动态范围和静态范围都突出显示同一区域,所以我认为问题不在于动态范围的 OFFSET 公式......并且正如我之前提到的,当我将静态范围文本的开头替换为动态范围的开头文本“ExampleRange”时,完全相同的 VLOOKUP 公式有效,因此 VLOOKUP 公式似乎也有效......跨度>
  • @KyleWurtz 你是对的 - 双动力确实不起作用......也许你获得"ExampleRange"&C1 的中间单元以进一步间接是一种选择?

标签: excel dynamic excel-formula named-ranges


【解决方案1】:

在进一步研究之后,我可以说,Excel 的INDIRECT 函数根本不适用于动态范围。可能有一种巧妙的方法可以使用INDIRECT 并坚持使用非 VBA Excel 世界,但我不知道这种方法。相反,我最终创建了一个与here 描述的非常相似的用户定义函数。我将主要公式更改为 =VLOOKUP(B2,DINDIRECT("ExampleRange"&C1),2,FALSE),其中 DINDIRECT 是我创建的 VBA 函数的名称。

此替代方案的唯一缺点(可能是也可能不是缺点,取决于您如何看待它)是工作簿必须保存为启用宏的工作簿,并且使用自定义函数不是很自我- 记录并需要对其他用户进行一些解释。不过,考虑到所有因素,这对我来说是一个可以接受的解决方案。

对于链接厌恶,这里是代码:

Public Function DINDIRECT(sName As String) As Range
     Dim nName As Name

     On Error Resume Next
          Set nName = ActiveWorkbook.Names(sName)
          Set nName = ActiveSheet.Names(sName)
     On Error GoTo 0

     If Not nName Is Nothing Then
          Set DINDIRECT = nName.RefersToRange
     Else
          DINDIRECT = CVErr(xlErrName)
End Function

注意:尽管此解决方案有效,但我不会接受我的回答,因为我不想阻止其他人发布更好的解决方案。另外,我是该网站的新手,如果我通过回答自己的问题而违反了任何礼仪规范,非常抱歉……我只是想分享一下我使用的确切解决方案,以防其他人发现它有用。

【讨论】:

    【解决方案2】:

    我最近碰到了这堵砖墙,而您已经猜到的答案很简单,就是您不能使用 INDIRECT 引用动态命名范围。

    但是,您可以使用动态范围公式本身作为 INDIRECT 的参数,但这对您想要做的事情没有用处。有点像 PITA,因为它是一种非常有用的功能。

    【讨论】:

    • 感谢您确认 INDIRECT 不适用于动态命名范围。我完全同意这个功能会很有用,而且考虑到变通方法代码的简单性(因此他们应该很容易合并它)以及问题出现的频率(至少对我而言),这尤其令人沮丧。跨度>
    • 没错。当您必须想出一个不使用 UDF(或以任何方式使用 VBA)的解决方案时,这是双重的令人沮丧,因为我经常需要这样做。
    【解决方案3】:

    如果您的数据具有 10、20 等标头,则无需使用间接。为什么不直接使用索引/匹配来选择您需要的数据?

    例如,将整个表格命名为 ExampleRanges 并使用以下公式:

    Index(ExampleRanges, match(B2, index(ExampleRanges, , 1), 0), match(C1, index(ExampleRanges, 1,), 0))
    

    【讨论】:

    • 成功了!使用索引解决了我在命名公式中的间接问题:)
    【解决方案4】:

    我知道这已经很老了,但我只是遇到了这个问题,并认为我会添加一个避免任何 VBA 编码的解决方案,以防万一它可以帮助其他偶然发现这个问题的人:

    =VLOOKUP(B2,CHOOSE(C1/10,example10,example20,example30,example40),2,0)
    

    这是假设命名约定为 10、20、30 等,并不适合数百个范围。

    【讨论】:

      【解决方案5】:

      未经测试,但我认为这可行:

      用户定义函数返回动态命名范围的地址:

      Function Named_Range_Address(Range_Name As Range, _ 
          Optional SheetName As Boolean) As String 
      
          Dim strName As String 
          Application.Volatile 
      
          If SheetName = True Then 
              strName = "'" & Range_Name.Parent.Name & "'!" & Range_Name.Address 
          Else 
              strName = Range_Name.Address 
          End If 
      
          Named_Range_Address = strName 
      End Function 
      

      那么您应该能够使用您的 vlookup 公式:

      =VLOOKUP(B2,INDIRECT(named_range_address("ExampleRange"&C1,TRUE)),2,FALSE)
      

      【讨论】:

      • 感谢您的建议。我在谷歌搜索时在某处看到了这样的函数,但是这个特定的函数要求第一个参数是 Range 类型,但是由于我将字符串“ExampleRange”和 C1 中的文本连接起来,所以我得到了一个 String 类型的参数.但是,您使用用户定义函数的建议是正确的。我确实找到了另一个使用 RangeName As String here 的函数,这对我来说效果很好。
      【解决方案6】:

      今天我正在修改 Excel 命名范围,我发现,虽然您确实无法在 INDIRECT() 调用本身中计算范围的名称,但您仍然可以通过纯“Excel 方式" 通过添加一个中间步骤:只需创建一些隐藏单元格,您可以在其中计算命名范围。

      例如,假设A1 包含范围名称的“动态部分”,然后在A2 中使用公式= "ExampleRange" & A1,现在您就有了完整的范围名称,您可以将其用作@987654325 @。

      【讨论】:

      • 问题不在于名称本身是动态的,而在于它所指的范围是动态的。
      【解决方案7】:

      添加一个新的转折点,可以将命名范围与 Address 和 Indirect 函数一起使用。我有一个案例,我正在为一系列表设置命名范围并使用以下内容:

      Named Range: WWDH-FF-PI which points to Linear!$A$19 (first cell in table)
      

      获取地址: $T$56: =ADDRESS(MATCH(S56,Linear!A:A,0),1,1,1,"Linear")

      然后使用多次复制的offset函数创建数据透视表:

      =OFFSET(INDIRECT($T$56),C5,$T$57-1)
      

      因此,Address 函数可以嵌入(或包装)到 Indirect 函数中以创建动态单元格地址。

      【讨论】:

      • 这行得通,但不幸的是,动态命名范围会出现问题,即一个命名范围,它引用可变数量的单元格,通常取决于它们的内容。
      【解决方案8】:

      我知道这是一个非常老的帖子,但我遇到了同样的问题,所以也许我的解决方案可以帮助将来的人们。

      基本上,我创建了一个宏,它会在保存时删除并重新定义范围,并为其命名。因此,INDIRECT 函数将起作用,因为范围不是动态的。您需要做的就是在将任何值添加到命名范围后保存工作簿

      Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
      
      Dim a, b, c, d, e, f As Integer
      Dim data As Worksheet
      
      Set data = ThisWorkbook.Worksheets("Data")
      
      a = data.Range("A" & Rows.count).End(xlUp).row
      b = data.Range("B" & Rows.count).End(xlUp).row
      c = data.Range("C" & Rows.count).End(xlUp).row
      d = data.Range("D" & Rows.count).End(xlUp).row
      e = data.Range("E" & Rows.count).End(xlUp).row
      f = data.Range("F" & Rows.count).End(xlUp).row
      
      
      
      ActiveWorkbook.Names("KP").Delete
      ActiveWorkbook.Names("KPT").Delete
      ActiveWorkbook.Names("AP").Delete
      ActiveWorkbook.Names("APT").Delete
      ActiveWorkbook.Names("DISC").Delete
      ActiveWorkbook.Names("SEATS").Delete
      
      ActiveWorkbook.Names.Add Name:="KP", RefersTo:="=Data!$A$2:$A$" & a
      ActiveWorkbook.Names.Add Name:="KPT", RefersTo:="=Data!$B$2:$B$" & b
      ActiveWorkbook.Names.Add Name:="AP", RefersTo:="=Data!$C$2:$C$" & c
      ActiveWorkbook.Names.Add Name:="APT", RefersTo:="=Data!$D$2:$D$" & d
      ActiveWorkbook.Names.Add Name:="DISC", RefersTo:="=Data!$E$2:$E$" & e
      ActiveWorkbook.Names.Add Name:="SEATS", RefersTo:="=Data!$F$2:$F$" & f
      
      End Sub
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-05
        • 1970-01-01
        相关资源
        最近更新 更多