如何在 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 似乎没有公开一组数组公式供您循环。这意味着您必须检查每个单元格。在高层次上,这段代码:
扫描每个单元格。
如果单元格包含数组公式,它会提取地址。
如果地址是新地址,则将其添加到地址变量中。
将所有地址输出到屏幕。
' 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
我认为这段代码可以改进:
- Redim 很贵。以 1000 个为一组调整数组大小可能会更好。
- Excel Object Model可能公开一个你可以循环的集合。
- 对于较大的工作簿,提取所有地址然后对结果进行重复数据删除会更快。
Excel 2010。我需要找出 FormulaArrays 在 sheet 中的位置。特别是我需要得到他们的地址。
我不是在知道给定的 (1x1) 单元格是否是 "part of" FormulaArray 之后,而是知道 FormulaArray "blocks" 所在的位置。例如,如果在 A1:B2 中输入了 FormulaArray,我想获得 FormulaArray 区域超出范围 A1:B2 的信息,而不是知道单个单元格 A1、A2、B1、B2是 "a" FormulaArray 的一部分。
这可能吗?
这并不像我希望的那么容易。 Excel 似乎没有公开一组数组公式供您循环。这意味着您必须检查每个单元格。在高层次上,这段代码:
扫描每个单元格。
如果单元格包含数组公式,它会提取地址。
如果地址是新地址,则将其添加到地址变量中。
将所有地址输出到屏幕。
' 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
我认为这段代码可以改进:
- Redim 很贵。以 1000 个为一组调整数组大小可能会更好。
- Excel Object Model可能公开一个你可以循环的集合。
- 对于较大的工作簿,提取所有地址然后对结果进行重复数据删除会更快。