如何在Excel工作表中循环使用FormulaArrays

时间:2017-04-05 14:04:32

标签: excel vba excel-vba array-formulas

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

我不知道给定的(1x1)单元是否是""的一部分。一个FormulaArray,而是知道FormulaArray"阻止"位于。例如,如果在A1:B2中输入FormulaArray,我想获得FormulaArray区域超出范围A1:B2的信息,而不是知道单个单元格A1,A2,B1,B2是其中的一部分" a" FormulaArray。

这可能吗?

1 个答案:

答案 0 :(得分:1)

这并不像我希望的那么容易。 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: Action you output as necessary!
        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
    
  5. 我认为这段代码可以改进:

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