简体   繁体   English

在 Excel 公式中引用动态命名范围

[英]Referencing Dynamic Named Range in Excel Formula

I have a table in Excel with column headings that correspond to part of a dynamic named range elsewhere in my workbook.我在 Excel 中有一个表格,其列标题对应于我的工作簿中其他地方的动态命名范围的一部分。 For example, I have these column headings: "10", "20", etc., and these dynamic named ranges: "ExampleRange10", "ExampleRange2", etc. I'd like to enter a VLookup formula that references ExampleRange10 by concatenating the string "ExampleRange" and the column heading "10".例如,我有这些列标题:“10”、“20”等,以及这些动态命名范围:“ExampleRange10”、“ExampleRange2”等。我想通过串联输入引用 ExampleRange10 的 VLookup 公式字符串“ExampleRange”和列标题“10”。 This would allow me to simply extend the formula across all columns in the table, instead of manually typing "ExampleRange10", "ExampleRange20", etc. in each column's formula.这将允许我简单地将公式扩展到表中的所有列,而不是在每列的公式中手动键入“ExampleRange10”、“ExampleRange20”等。

I'm aware of the INDIRECT function, and have used it successfully in the past with named ranges, but it doesn't seem to be working with the dynamic named range in this case.我知道 INDIRECT 函数,并且过去曾成功地将它用于命名范围,但在这种情况下它似乎不适用于动态命名范围。 I'm guessing this is a nuance that has something to do with how dynamic named ranges are defined by Excel (they don't show up in the named range dropdown to the left of the formula bar, and they have some interesting properties in VBA, for example).我猜这是一个细微差别,与 Excel 定义动态命名范围的方式有关(它们没有显示在公式栏左侧的命名范围下拉列表中,并且它们在 VBA 中有一些有趣的属性, 例如)。 Is there a way I can use the INDIRECT formula in conjunction with a dynamic named range, or is there another way that I can go about solving this problem?有没有一种方法可以将 INDIRECT 公式与动态命名范围结合使用,或者是否有另一种方法可以解决这个问题?

Edit : Here are the exact formulas used.编辑:这是使用的确切公式。
This is the main formula: =VLOOKUP(B2,INDIRECT("ExampleRange"&C1),2,FALSE) where C1 contains "10" and the formula for my dynamic named range called "ExampleRange10" is: =OFFSET(Sheet1!$F$2,0,0,COUNTA(Sheet1!$F$2:$F$25),2) .这是主要公式: =VLOOKUP(B2,INDIRECT("ExampleRange"&C1),2,FALSE)其中 C1 包含“10”,我的名为“ExampleRange10”的动态命名范围的公式是: =OFFSET(Sheet1!$F$2,0,0,COUNTA(Sheet1!$F$2:$F$25),2) The main formula returns "#REF!", but it works correctly when I remove the dynamic named range formula and simply define "ExampleRange10" as a static range.主公式返回“#REF!”,但当我删除动态命名范围公式并简单地将“ExampleRange10”定义为静态范围时,它可以正常工作。

As best I could tell after doing further research, Excel's INDIRECT function simply doesn't work with dynamic ranges.在做进一步研究后,我所能说的最好的情况是,Excel 的INDIRECT函数根本不适用于动态范围。 There might be a clever way to get around using INDIRECT and sticking to the non-VBA Excel world, but I'm unaware of such a way.可能有一种巧妙的方法可以绕过使用INDIRECT并坚持使用非 VBA Excel 世界,但我不知道这种方法。 Instead, I ended up creating a user-defined function very similar to the one described here .相反,我最终创建了一个与此处描述的非常相似的用户定义函数。 I altered my main formula to read =VLOOKUP(B2,DINDIRECT("ExampleRange"&C1),2,FALSE) , where DINDIRECT is the name of the VBA function I created.我更改了我的主要公式以读取=VLOOKUP(B2,DINDIRECT("ExampleRange"&C1),2,FALSE) ,其中DINDIRECT是我创建的 VBA 函数的名称。

The only downsides (which may or may not be downsides depending on how you look at it) to this alternative is that the workbook must be saved as a macro-enabled workbook and the use of a custom function isn't very self-documenting and requires a little explanation to other users.这种替代方法的唯一缺点(可能是也可能不是缺点,取决于您如何看待它)是工作簿必须另存为启用宏的工作簿,并且自定义函数的使用不是很自我记录和需要向其他用户稍作解释。 All things considered, though, this was an acceptable solution for me.不过,考虑到所有因素,这对我来说是一个可以接受的解决方案。

For the link-averse, here's the code:对于链接厌恶,这里是代码:

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

Note: Although this solution worked, I'm not going to accept my answer because I don't want to discourage others from posting better solutions.注意:虽然此解决方案有效,但我不会接受我的答案,因为我不想阻止其他人发布更好的解决方案。 Also, I'm new to the site, so sorry if I'm breaking any etiquette codes by answering my own question...I just thought I'd share the exact solution that I used in case others find it useful.另外,我是该网站的新手,如果我通过回答我自己的问题而破坏了任何礼仪规范,那么抱歉……我只是想分享我使用的确切解决方案,以防其他人发现它有用。

I hit this exact brick wall recently and the answer as you have already guessed is simply that you can't reference dynamic named ranges with INDIRECT.我最近碰到了这个确切的砖墙,正如您已经猜到的那样,答案很简单,您不能使用 INDIRECT 引用动态命名范围。

You can however use the dynamic range formula itself as INDIRECT's argument, but this is no use for what you want to do.然而,您可以使用动态范围公式本身作为 INDIRECT 的参数,但这对您想要做的事情没有用。 Somewhat of a PITA since it's the kind of functionality that would be very useful.有点像 PITA,因为它是一种非常有用的功能。

If your data has headers like 10, 20 etc., then you don't need to use Indirect.如果您的数据具有 10、20 等标题,则不需要使用 Indirect。 Why not just use Index/Match to select the data you need?为什么不直接使用索引/匹配来选择您需要的数据?

Name your whole table ExampleRanges for example and use this formula:例如,将整个表命名为 ExampleRanges 并使用以下公式:

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

I know this is quite old, but I only just came across this and thought I'd add a solution that avoids any VBA coding in case it helps anyone else who stumbles across this:我知道这已经很老了,但我只是遇到了这个,并认为我会添加一个避免任何 VBA 编码的解决方案,以防它可以帮助任何其他偶然发现的人:

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

This is assuming the naming convention being 10,20,30,etc and will not be ideal for hundreds of ranges.这是假设命名约定为 10、20、30 等,并且对于数百个范围来说并不理想。

Untested, but I think this would work:未经测试,但我认为这会奏效:

user defined function to return the address of your dynamically named range:用户定义函数返回动态命名范围的地址:

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 

then you should be able to use your vlookup formula:那么你应该能够使用你的 vlookup 公式:

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

Today I was tinkering with Excel named ranges, and I discovered that, while it is true that you cannot compute the name of the range in the INDIRECT() call itself, you can still get it in a pure "Excel-way" by adding an intermediate step: just create some hidden cell in which you compute the named range.今天我正在修改 Excel 命名范围,我发现,虽然您确实无法在INDIRECT()调用本身中计算范围的名称,但您仍然可以通过添加以纯粹的“Excel 方式”获得它中间步骤:只需创建一些隐藏单元格,在其中计算命名范围。

For example, say that A1 contains the "dynamic part" of the range name, then in A2 use the formula = "ExampleRange" & A1 , and now you have the full range name, which you can use as = INDIRECT(A2) .例如,假设A1包含范围名称的“动态部分”,然后在A2使用公式= "ExampleRange" & A1 ,现在您有了完整的范围名称,您可以将其用作= INDIRECT(A2)

Adding a new twist, it is possible to use a named range with the Address and Indirect functions.添加一个新的变化,可以将命名范围与 Address 和 Indirect 函数一起使用。 I have a case where I am setting named ranges for a series of tables and am using the following:我有一个案例,我为一系列表设置命名范围并使用以下内容:

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

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

Then using the offset function copied multiple times to create a pivot table:然后使用多次复制的偏移函数来创建数据透视表:

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

So, the Address function can be embedded (or wrapped) into the Indirect function to create a dynamic cell address.因此,可以将 Address 函数嵌入(或包装)到 Indirect 函数中以创建动态单元格地址。

I know this is a really old thread, but I had the same issue, so perhaps my solution can help people in the future.我知道这是一个非常古老的线程,但我遇到了同样的问题,所以也许我的解决方案可以在未来帮助人们。

Basically, I created a Macro that would delete and re-define the range upon save, and give it a name.基本上,我创建了一个宏,它会在保存时删除和重新定义范围,并为其命名。 Therefore, the INDIRECT function would work as the range was not dynamic.因此,INDIRECT 函数将起作用,因为范围不是动态的。 All you need to do is save the workbook after adding any values to the named ranges您需要做的就是在将任何值添加到命名范围后保存工作簿

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM