【问题标题】:Code equivalent to Array Formula等效于数组公式的代码
【发布时间】:2015-07-06 05:22:15
【问题描述】:

我目前正在我的数据中使用数组公式来查找 O、Y 和 AA 列与当前行匹配且 A 列值不匹配的行,并为匹配行返回 C 列。

这是我的公式:

=INDEX(C:C,MATCH(1,(O:O=O2)*(Y:Y=Y2)*(AA:AA=AA2)*(A:A<>A2),0))

使用命名范围我已经能够使用 VBA 输入这个公式,但我真正想做的是使用 VBA 执行类似的功能并将结果值写入 D 列。

我在想可能是一个循环,对于从 2 到最后一行的每个 i,在匹配的范围内找到另一行并写入单元格(找到的行3).value 到单元格(i, 4),但我不知道 VBA 数组查找匹配行的语法。

【问题讨论】:

  • 要从 Excel 工作表中获取数组到 VBA 变量中,您可以使用以下内容对其进行赋值:aryArrayVariable() = Sheet1.Range("A1:Z100")。之后,您可以遍历数组并做任何您想做的事情,最后写回工作表。你可能想看看这个网站(以及以下五个部分)fastexcel.wordpress.com/2011/05/25/…
  • 您可以在数组上使用查找函数,就像在工作表中使用它们一样。例如 WorksheetFunction.Match(ValueToLookFor,SomeArray,False),前提是 SomeArray 是二维的。
  • Worksheet.Evaluate() 可用于数组公式,因此您应该几乎可以按原样使用公式。
  • 当声明'并将结果值写入列D'时,您的意思是要在单独的行中返回大量值吗?如果是这样,将公式放入 .Formula.Array 然后将结果恢复为其基础值可能是最好的方法。除非您处理内存块中的单个行并将结果转储回工作表,否则循环通过 application.evaluate 将非常耗时。

标签: arrays vba excel rows matching


【解决方案1】:

虽然没有明确说明,但很容易推断出您正在寻求使用 VBA 来提高数组公式的计算/重新计算的效率。您尚未提供数据的范围(即行数),但您不太可能需要您正在使用的完整列引用。以下计算周期时间基于约 1000 行静态数据。


你的数组公式:

=INDEX(C:C, MATCH(1, (O:O=O2)*(Y:Y=Y2)*(AA:AA=AA2)*(A:A<>A2), 0))

填写和计算所用时间:24.828 秒


您的列引用被截断为数据的实际范围的数组公式:

=INDEX($C$2:$C$999, MATCH(1, ($O$2:$O$999=O2)*($Y$2:$Y$999=Y2)*($AA$2:$AA$999=AA2)*($A$2:$A$999<>A2), 0))

填写和计算所用时间:0.203 秒


可比较的标准公式,列引用被截断为数据的实际范围:

=INDEX($C$2:$C$999, MIN(INDEX(ROW($1:$998)+(($A$2:$A$999=A2)+($O$2:$O$999<>O2)+($Y$2:$Y$999<>Y2)+($AA$2:$AA$999<>AA2))*1E+99, , )))

填写和计算所用时间:0.257 秒


如您所见,减少对实际使用内容的列引用会极大地提高效率。数组公式通过根据其他所有内容计算所有内容来处理。计算负载呈指数增长 随着引用的单元格行数的增加。

如果您的数据不断变化并且您不知道要处理多少行,请使用 命名范围 和动态定义的 Refers to:。示例:

  1. 选择通常定义数据范围的列并注意数据的性质。此方法略有不同,具体取决于您处理的是真实数字还是文本。出于演示目的,C 列有数字。
  2. 选择公式 ► 定义的名称► 名称管理器。当名称管理器对话框打开时,单击新建
  3. Name: 文本框中输入范围的友好名称;例如MyColAA。将 Scope: 作为 Workbook。
  4. 指代:
     
        =$AA$2:INDEX($AA:$AA, MATCH(1e99, $C:$C))
     
    这会将 myColAA 定义为与 C 列中最后一个数字匹配的行的 AA2。如果 C:C 列充满了文本值,您将使用以下内容,
     
        =$AA$2:INDEX($AA:$AA, MATCH("zzz", $C:$C)) 
  5. 对 A:A、C:C、O:O 和 Y:Y 列重复。将 last used 引用保留为 C:C 列,这样它们的行数将始终相同,但会更改其他列引用并为每个列指定一个新名称。
  6. 当您创建所有命名范围并返回工作表时,通过点击 F5 进行测试,在 Reference: 中键入 myColAA > 文本框并单击确定

您的数组公式现在类似于以下内容。

=INDEX(myColC, MATCH(1, (myColO=O2)*(myColY=Y2)*(myColAA=AA2)*(myColA<>A2), 0))

命名范围会随着可用数据量的增加而增长和缩小。

【讨论】:

  • 您正确推断出我正在寻找运行计算。更重要的是,我已经在使用vba输入这个公式了,但是留下数组公式使得Excel在处理大型数据集时非常慢。我已经在我的公式中使用了命名范围,这些命名范围也是动态确定的,以包含所有非空白单元格,出于隐私原因,我只是不想将命名范围放在这里。我最终像以前一样插入公式,然后像这样评估整个列:with columns("D") .value = .value 感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 2017-10-26
相关资源
最近更新 更多