在不使用VBA的情况下,通过循环将n 个命名区域堆叠起来

编程语言 2026-07-09

我正在寻找一种方法,能够把数组(也就是存放在Excel表中的按名称命名的区域)堆叠起来,方法是利用另一个表中存放的表名。实际目标不仅是把两个区域堆叠起来,而是要堆叠更多的区域。

请参阅我的数据作为起点

Data to start with.

我知道以下这些会得到相同的结果:

=VSTACK(rangeA;rangeB)
=VSTACK(INDIRECT("range" & XLOOKUP(1;info[ID];info[Name])); INDIRECT("range" & XLOOKUP(2;info[ID];info[Name])))

同样地,

=LET(id;A1;INDIRECT("range" & XLOOKUP(id;info[ID];info[Name])))

返回(单元格 A1 的内容为1 或2 时)某一个命名区域,我原本以为/希望

=VSTACK(LET(id;SEQUENCE(2);INDIRECT("range" & XLOOKUP(id;info[ID];info[Name]))))

能够达成效果,但并没有。我感觉用某种方式 BYROW(SEQUENCE(x);LAMBDA(id;...)) 可能是正确的做法,但到目前为止我的尝试都产生了各种错误信息(也不清楚应该把堆叠公式放在哪里)。

数据

ID 名称
1 A
2 B

rangeA

ID
1 x11
2 x12

rangeB

ID
3 y11
4 y12

解决方案

在这里尝试使用 REDUCE() 函数:

=DROP(REDUCE("", XLOOKUP(SEQUENCE(2), 
                         Info[ID], 
                         "range"&Info[Name], ""), 
      LAMBDA(x,y, VSTACK(x, INDIRECT(y)))), 1)

以上公式把一组命名区域堆叠成一个列表。它先从查找表构建范围名称,然后把它们聚拢一起。逐步解释如下:

  • SEQUENCE(2) --> 这会生成 {1; 2},用于从 Info 表中提取前两个ID
  • XLOOKUP(SEQUENCE(2), Info[ID], "range"&Info[Name], "") --> 这会在 Info[ID] 中查找 12,并返回将 "range" 与在 Info[Name] 的每个匹配项拼接的结果
  • 输出将是 {"rangeA"; "rangeB"}
  • 为空字符串的引号只是为了应对没有匹配的情况。
  • REDUCE("", ..., LAMBDA(x, y, VSTACK(x, INDIRECT(y)))) --> 这从一个空值开始,然后遍历来自 XLOOKUP() 函数的每一个名称
  • INDIRECT() 函数在每次迭代时把文本 "rangeA" 转换成实际的区域
  • VSTACK() 函数在先前的基础上不断把每个区域追加,最终把所有内容堆叠成一列
  • DROP(..., 1) --> 由于 REDUCE() 是从空值开始,因此顶部会出现一行空白,这一步把第一行删去,只保留真正的数据。

为了更易读一些,可以尝试:

图片描述

=LET(
     _a, Info,
     _b, SEQUENCE(ROWS(_a)),
     _c, XLOOKUP(_b, Info[ID], "range"&Info[Name], ""),
     REDUCE({"ID","Value"}, _c, LAMBDA(x,y, 
     VSTACK(x, INDIRECT(y)))))

其中 Info 是包含ID及其对应Names的表的名称。


或者,使用Power Query:

图片描述

要使用Power Query,请按以下步骤:

  • 首先把源区域转换成表并按相应名称命名,在本例中我将其命名为 Info

  • 接下来,在 Data(数据) 选项卡里打开一个空白查询 --> Get & Transform Data --> Get Data --> From Other Sources --> Blank Query

  • 上述步骤会打开 Power Query 窗口,现在在 Home(主页) 选项卡中点击 Advanced Editor(高级编辑器) --> 将下面的 M-Code 粘贴进去(删除你看到的现有文本)并点击 Done(完成)

let
    Source = Excel.CurrentWorkbook(){[Name="Info"]}[Content],
    DataType = Table.TransformColumnTypes(Source, {{"ID", Int64.Type}, {"Name", type text}}),
    JoinRangeName = Table.AddColumn(DataType, "RangeName", each "range" & [Name], type text),
    AddTableContents = Table.AddColumn(JoinRangeName, "TableContent", each
        let
            RangeName = [RangeName],
            MatchingTable = Excel.CurrentWorkbook(){[Name = RangeName]}[Content]
        in
            MatchingTable),
    RemovedOtherCols = Table.SelectColumns(AddTableContents,{"TableContent"}),
    Answer = Table.ExpandTableColumn(RemovedOtherCols, "TableContent", {"ID", "Value"}, {"ID", "Value"})
in
    Answer

  • 最后,要把结果导回 Excel --> 点击 Close & LoadClose & Load To --> 第一个会创建一个带有所需输出的新工作表,后者会弹出一个窗口让你选择放置结果的位置。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章