【问题标题】:Simplifying complex excel formula with VBA使用 VBA 简化复杂的 Excel 公式
【发布时间】:2018-04-12 22:06:14
【问题描述】:

由于过度使用 LOOKUP 公式,我有一个通常很慢的宏。我想插入一些 VBA 变量来加快这些速度。我目前正在加快以下公式的速度:在 Excel 中:

=IF(ISNA(MATCH(A2,Summary!B:B,0)),"n",I2-((I2/LOOKUP(2,1/(I:I<>""),I:I))*VLOOKUP(A2,Summary!$G$10:$H$902,2,FALSE)))

在 VBA 中:

"=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-((RC[-1]/LOOKUP(2,1/(C[-1]<>""""),C[-1]))*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))"

我需要替换的部分是LOOKUP(2,1/(C[-1]&lt;&gt;""""),C[-1])。所有这一切都是引用第一列中最后一个非空单元格。现在我有以下代码来返回 VBA 中最后一个单元格的地址

Sub FormulaTest()
Set lRow = Range("I1").SpecialCells(xlCellTypeLastCell).Address

End Sub

我试图弄清楚如何将这个“lRow”实现到公式的 VBA 代码中。谁能引导我朝着正确的方向前进?

**编辑 1 请参阅下面费尔南多的评论。他有正确的想法,但解决方案仍然有点偏离。我会尝试在几个 cmets 中更好地解释它:首先,第一行始终是标题行,最后一行始终是总和行,当前选项卡是“销售”选项卡,以及任何给定的行数销售标签会有所不同(可能是 I1:I59,也可能是 I:1:I323)。

在本例中,I1 是行标题,I59 是 I2:I58 的总和。 I2:I58 行是美元金额。我的宏将这个公式放在 J2:J58 中。此公式将每行的美元金额 (I2:I58) 作为总额 (I59) 的百分比,并将其乘以“摘要”选项卡 (VLOOKUP) 上的输入金额。然后从 I 列中的美元值中按比例减去该金额,其中 J 单元格显示结果。

我希望在上面的公式中消除对 LOOKUP 函数(选择最后一个非空单元格)的需要: LOOKUP(2,1/(C[-1]""""),C[-1 ])。

**编辑 2 费尔南多的解决方案奏效了。谢谢大家的意见

【问题讨论】:

  • 你把这些公式放在哪里了? "=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-((RC[-1]/LOOKUP(2, 1/(C[-1]""""),C[-1]))*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))" 只是在一列?
  • 对于单元格 A 与“摘要”选项卡上的相应单元格匹配的任何行,这些公式都放在 J 列中
  • 您真的需要工作表上的公式吗?你可能会更好地完成你在 VBA 中所做的任何事情。将您的范围读入一个变体数组;然后通过数组来创建你的结果;然后将其写回工作表。
  • 您的问题说您使用的是 INDIRECT,但您的示例中没有 INDIRECT。您还需要提供更多信息才能从该论坛获得最佳结果。公式有什么作用?查找列表中有多少项?目前计算需要多长时间?将逻辑转移到 VBA 可能会加快速度,但我几乎可以肯定,如果您回答我的问题,那么我可以为您提供一个闪电般快速的公式或使用数据透视表的方法,它比 VBA 方法更快、更简单。跨度>
  • 另外,您只发布了部分代码。您的慢速症状的一部分可能与您使用这些公式填充工作表的方式有关。您是否一次将公式写入一个单元格?您还可以通过使用IFERROR 来替换对IF(ISNA 的需要,从根本上加快公式的速度,并且您可以使用数组公式一次处理整个范围。但同样,您需要进一步详细说明您正在尝试做什么、您的数据布局是什么样的以及其余代码的结构。

标签: vba excel excel-formula


【解决方案1】:

这将返回 I 列中的最后一个非空行

with Worksheets("Summary")
lRow = .Cells(.Rows.Count, "I").End(xlUp).Row
end with

所以你的代码是

sub testy
dim lRow as long
with Worksheets("Summary")
lRow = .Cells(.Rows.Count, "I").End(xlUp).Row
end with

"=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-_
((RC[-1]/R"&lRow&"C[-1])*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))"

在您的解决方案中,您使用的是xlCellTypeLastCell。这非常有用,但它基于UsedRange 计算,这可能不是您想要的。有了这个,如果你有数据到行n,然后你更新数据,现在你有更少的记录,最后一行xlCellTypeLastCell仍然是n,所以要小心。

【讨论】:

  • 我使用了以下代码,它为新的 LOOKUP 值返回零 IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-((RC[-1]/" &amp; lRow &amp; ")*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))"
  • 尝试使用"=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-((RC[-1]/R"&amp;lRow&amp;"C[-1])*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))"
  • 我必须添加方括号:"=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-((RC[-1]/R[" &amp; lRow &amp; "]C[-1])*VLOOKUP(RC[-9],Summary!R10C7:R902C8,2,FALSE)))" 请看一下我上面的 cmets - 公式返回的单元格比我需要的单元格低 2 个单元格。知道可能是什么原因造成的吗?我还需要将此作为绝对参考
  • 在 RC 表示法中,如果您使用方括号,它是一个 relative 引用,这意味着它将使用低于其中 n 行的单元格您正在调用公式。同时,没有括号,它是一个 absolute 引用,这意味着例如,R100 将始终引用行号 100,而不是 R[100],它将是您调用位置正下方的 100 行参考。
【解决方案2】:

假设您正在活动工作表上完成所有工作,查找“摘要”工作表:

Sub fillCol()

    Dim aRow As Long, bRow As Long

    aRow = Cells(Rows.Count, "I").End(xlUp).Row
    bRow = Sheets("Summary").Cells(Rows.Count, "I").End(xlUp).Row

    Range("J2:J" & aRow).FormulaR1C1 = "=IF(ISNA(MATCH(RC[-9],Summary!C[-8],0)),""n"",RC[-1]-" _
                       & "((RC[-1]/" & aRow & ")*VLOOKUP(RC[-9],Summary!R10C7:R" & bRow & "C8,2,FALSE)))"

End Sub

您需要更改包含连续范围的列(以确定最后一行)

【讨论】:

  • 这将返回我正在寻找的单元格的行号:=IF(ISNA(MATCH(A2,Summary!B:B,0)),"n",I2-((I2/59)*VLOOKUP(A2,Summary!$G$1:$H$10,2,FALSE)))。我需要它来返回地址,因此公式将使用第 59 个单元格
  • 该公式已将59 硬编码到其中。如果该行不会改变,只需设置aRow = 59。或者有一些其他的算法方式来选择行号。但是您的公式基本上是选择硬编码行地址的一种非常复杂的方法。
  • 您的问题不清楚。如果您可以用一种不需要我们根据您的嵌套公式来解释您的数据可能是什么的方式来表达它,那么我们可以给出更具体的回应。您是否要获取摘要表的最后一行?这就是我的解决方案中的bRow
  • 请参阅上面费尔南多的评论。他有正确的想法,但解决方案仍然有点偏离。我会尝试在几个 cmets 中更好地解释它:首先,第一行始终是标题行,最后一行始终是总和行,当前选项卡是“销售”选项卡,以及任何给定的行数销售标签会有所不同(可能是 I1:I59,也可能是 I:1:I323)。
  • 在本例中,I1 是行标题,I59 是 I2:I58 的总和。 I2:I58 行是美元金额。我的宏将这个公式放在 J2:J58 中。此公式将每行的美元金额 (I2:I58) 作为总额 (I59) 的百分比,并将其乘以摘要选项卡 (VLOOKUP) 上的输入金额。然后从 I 列中的相应值中按比例减去该金额,其中 J 单元格显示结果。
猜你喜欢
  • 1970-01-01
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 2015-07-23
相关资源
最近更新 更多