【问题标题】:Set ArrayFormula to many Excel cells using VBA使用 VBA 将 ArrayFormula 设置为多个 Excel 单元格
【发布时间】:2011-08-28 05:33:15
【问题描述】:

我有一个输出单个值的数组公式,我想为一大堆单元格提供相同的数组公式。问题是当我将数组公式分配给范围时,它会以这样一种方式解释公式,即它们都共享对数组公式的单个调用的输出,而不是每个输出单独的值。

为了说明我的意思,我使用了以下代码:

With MarginalData
    .Range(.Cells(2, 1), .Cells(13, .UsedRange.Columns.Count)).FormulaArray = pullFormula
End With

我想要的,是这样的结果:

这就是我在区域的每个单元格中分别输入数组公式时的样子。

但是我得到的是这样的:

第一个单元格中的数组公式的输出在所有列中重复 - 它们都共享相同的输出。

如何以编程方式分配数组公式,就像每个单元格都单独分配一样?


公式为:

{=INDEX(BatchResults,MATCH(TTID&CHAR(1)&ROW()-1,BatchResultsTTIDS&CHAR(1)&BatchResultsLayers,0),MATCH(A$1,BatchTTIDData!$1:$1,0))}

它必须作为数组公式放入,因为它不是在单个列上执行匹配,而是在两个连接的列上执行匹配。列的连接必须作为数组返回,因此公式必须作为数组公式输入。


到目前为止,最简单的解决方案是以下公认答案的变体:

Const pullFormula = "=INDEX(BatchResults,MATCH(TTID&CHAR(1)&ROW()-1,BatchResultsTTIDS&CHAR(1)&BatchResultsLayers,0),MATCH(A$1,BatchTTIDData!$1:$1,0))"
With wrksht
    With .Range(.Cells(2, 1), .Cells(13, .UsedRange.Columns.Count))
        .Formula = pullFormula
        .FormulaArray = .FormulaR1C1
    End With
End With

【问题讨论】:

  • 您需要能够使 'pullFormula' 依赖于它所在的单元格,但我们需要该字符串来向您展示如何实现这一点(如果可能的话)。
  • 正如你在上面看到的,pullFormula 已经依赖于它所在的单元格。它考虑了当前行和列标题 (A$1),每个列都不同。
  • 好问题。根据this article,你有最好的方法

标签: excel vba array-formulas


【解决方案1】:

或者选择数组公式为 R1C1,分配给范围为 FormulaR1C1,然后将 FormulaR1C1 分配为数组公式。这假设数组公式在单元格 A2 中

Sub test()

With Sheet1
    pullFormula = .Range("A2").FormulaR1C1
    Set Rng = .Range(.Cells(2, 1), .Cells(13, .UsedRange.Columns.Count))

    Rng.Formula = pullFormula
    Rng.FormulaArray = Rng.FormulaR1C1

End With
End Sub

【讨论】:

  • 此解决方案有效,但发生了最奇怪的事情,当将公式数组设置为等于公式 1c1 时,操作速度非常慢 - 甚至比手动循环所有单元格还要慢,这似乎是如果您在屏幕更新打开的情况下执行代码行。
  • @Alain 哎呀,在大范围内相当慢!也许只在第一行使用我的方法会更快,然后自动填充 EG Rng.AutoFill Destination:=Rng.Resize(999, Rng.Columns.Count), Type:=xlFillDefault。或者使用Application.Calculation = xlCalculationManual会快一点
【解决方案2】:

尝试半自动完成。为第一行设置公式,然后使用 FillDown。

Private Sub soCopyFormula()

    Dim MarginalData As Worksheet
    Set MarginalData = ActiveWorkbook.Worksheets("Sheet2")
    Dim oRange As Range
    Dim i As Integer

    With MarginalData
        Set oRange = .Range(.Cells(2, 1), .Cells(13, .UsedRange.Columns.Count))
        ' for each column
        For i = 0 To oRange.Columns.Count - 1
            ' set first row
            oRange(1, i).FormulaArray = pullFormula
            ' copy down
            oRange.Columns(i).FillDown
        Next
    End With

End Sub

【讨论】:

  • 这个解决方案有效,但它比我想要的更复杂。我的临时解决方案实际上比这稍微简单一些,包括将公式设置为一个单元格,复制,然后向下复制。
  • @Alain 是的,绝对是一种解决方法。我并没有真正使用过 FormulaR1C1,但我现在会记得。
【解决方案3】:

试试 1 澳元,而不是 1 美元

INDIRECT(ADDRESS(1,COLUMN()))

【讨论】:

  • 我不知道为什么这么多人赞成,COL() 甚至不是 excel 中的有效函数——你的意思是 COLUMN()。此外,ADDRESS 返回字符串“$A$1”、“$B$1”等。 MATCH 函数采用范围,而不是字符串。将它放在函数中会破坏它。
  • 这不是问题的全部,要在将引用转换为字符串后使该函数工作,必须使用 INDIRECT 函数,该函数是易变的,意味着这些昂贵的数组公式每次更改工作簿中的任何内容时都会重新计算,这是非常不可接受的。
  • 即使有人忍受了 INDIRECT 公式,您的更改仍然无济于事,整个范围仍被视为具有单个输出,并且出现相同的重复问题,而不是每个单元格都有自己的问题价值。
  • 我对你的回答没有那么失望,对 3 个人盲目地支持一个明显不正确的答案这一事实更加失望。我们都会犯错,但如果人们不验证答案,就不应该投票。
  • @Alain,我没有给出正确答案,请注意 try 这个词。这是一种尝试,只有您可以测试,以帮助您找到答案。有时,当我寻找答案时,我只需要一条线索。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多