如何在 Excel Sheet 中循环 FormulaArrays

How to loop through FormulaArrays in an Excel Sheet

Excel 2010。我需要找出 FormulaArrays 在 sheet 中的位置。特别是我需要得到他们的地址。

我不是在知道给定的 (1x1) 单元格是否是 "part of" FormulaArray 之后,而是知道 FormulaArray "blocks" 所在的位置。例如,如果在 A1:B2 中输入了 FormulaArray,我想获得 FormulaArray 区域超出范围 A1:B2 的信息,而不是知道单个单元格 A1、A2、B1、B2是 "a" FormulaArray 的一部分。

这可能吗?

这并不像我希望的那么容易。 Excel 似乎没有公开一组数组公式供您循环。这意味着您必须检查每个单元格。在高层次上,这段代码:

  1. 扫描每个单元格。

  2. 如果单元格包含数组公式,它会提取地址。

  3. 如果地址是新地址,则将其添加到地址变量中。

  4. 将所有地址输出到屏幕。

     ' Returns the address of array formula in the current worksheet.
     Sub GetArrayFormulaRangeAddresses()
         Dim r As Range              ' Used to loop over active cells.
         Dim addresses() As String   ' Holds each found address.
         Dim address As String       ' Used to avoid duplicate entries.
         Dim foundCount As Integer   ' Count of found array formulas.
    
         ' Initialise vars.
         foundCount = -1
    
         ' Check every active cell, in currently selected tab.
         ' Ideally you would loop over a formula collection but
         ' the Excel object model does not appear to expose this.
         For Each r In ActiveSheet.UsedRange.Cells
    
             ' Found one.
             ' WARNING: Array formula contains values,
             ' even when cell is not part of an array formula.
             If r.FormulaArray Like "={*}" Then
    
                 ' WARNING: Cannot pass array until after firt redim statement.
                 ' To avoid check found count, then addresses array.
                 If foundCount = -1 Then
    
                     ' Not found, add to list.
                     foundCount = foundCount + 1
                     ReDim Preserve addresses(foundCount)
                     addresses(foundCount) = r.CurrentArray.address
    
                 Else
                     ' Check if address already found.
                     If Not CheckArrayContains(addresses, r.CurrentArray.address) Then
    
                         ' Not found, add to list.
                         foundCount = foundCount + 1
                         ReDim Preserve addresses(foundCount)
                         addresses(foundCount) = r.CurrentArray.address
                     End If
                 End If
             End If
         Next
    
    
         ' TODO: What do you want to do with found addresses?
         For foundCount = LBound(addresses) To UBound(addresses)
             MsgBox addresses(foundCount)
         Next
     End Sub
    
     ' Returns true if the passed array contains a value.
     ' Otherwise returns false.
     Public Function CheckArrayContains(ByRef CheckArray() As String, ByVal CheckValue As String) As Boolean
         Dim i As Integer        ' Counter, used to check each element of the array.
    
         ' Check existing members.
         For i = LBound(CheckArray) To UBound(CheckArray)
             If CheckArray(i) = CheckValue Then
    
                 ' Match found.
                 CheckArrayContains = True
                 Exit Function
             End If
         Next
    
         ' No match found.
         CheckArrayContains = False
     End Function
    

我认为这段代码可以改进:

  1. Redim 很贵。以 1000 个为一组调整数组大小可能会更好。
  2. Excel Object Model可能公开一个你可以循环的集合。
  3. 对于较大的工作簿,提取所有地址然后对结果进行重复数据删除会更快。