如何测试 Excel VBA 范围变量以引用整列..?
Posted
技术标签:
【中文标题】如何测试 Excel VBA 范围变量以引用整列..?【英文标题】:How can Excel VBA range variables be tested for references to entire columns..? 【发布时间】:2018-12-05 16:49:58 【问题描述】:有哪些方法可以测试 Excel VBA 范围变量以引用整列?
我正在使用 Excel 2007 VBA,使用 For-Each 循环遍历 Range 变量。范围作为参数传递给函数。对单个单元格、单元格范围和整行的引用都可以。
例如,这些是okiedokie:
Range("A1") 'One cell
Range("A1:D4") 'Range of cells.
Range("10:20") 'Entire rows 10 through 20.
但是,如果任何范围都引用了整个列,它将把函数拖到一个急停的位置。例如,这些不是 okiedokie,需要对其进行测试和避免:
Range("A:A")
Range("A:Z")
Range("AA:ZZ")
我有几种方法可以做到这一点,每一种都看似合理,但也有弱点。该代码包含用于在具有数千行的工作表中搜索单元格的循环,因此速度至关重要。
以下是我能想到的三种方式,但我想知道是否还有其他方式..?
最简单、最快的方法是计算行数。如果Range(x).Rows.Count=1048576
,这是工作表中的最大行数。但是,如果 实际 行数正好是那个数字,或者如果偶然有多个重叠区域/范围,这将不起作用
所有这些加起来就是那个数字。两者都不太可能,但可能。此外,如果 Excel 的版本发生变化,该数字也可能发生变化,从而导致代码损坏。
对 Range.Address(False,False) 的文本使用正则表达式匹配,其模式为 ([A-Z]1,3):([A-Z]1,3)
。我认为这将是速度规模的媒介。
使用 VBA 循环、If-Then
和字符串函数(例如 InStr()
和 Mid()
)选择 Range.Address(False,False)
的文本。我认为这是最慢的方法。
【问题讨论】:
对于数字 1,不要硬编码行数,而是从Range.Parent
获取 Rows.Count
。另外,多个重叠行是什么意思?
范围。对不起,我说错了,错了……打错了。我纠正了错字。我试图传达的是一个 Range 变量可以塞进很多东西。具体来说,许多 Area 对象。嗯......也许不是很多,我似乎记得在我的实验中,Range(string) 中的字符串的限制是 255 个字符。但是任何人,考虑一下:Range("A1:D4, B2:E5")
。这两个范围重叠。确实,Excel 会修复它并将其分解为矩形区域对象而不重叠,但我的函数将接受任何输入,因此重叠是可能的。
感谢 Range.Parent.Rows.Count 的建议;这适用于获得最大行数。在此之后,我在 Debug 模式下浏览了 Locals,我发现可以通过几种不同的方式找到它。
【参考方案1】:
您可以通过检查Range.Address
和Range.EntireColumn.Address
来测试范围是否是对列的引用,如下所示:
If Range("AA:ZZ").Address = Range("AA:ZZ").EntireColumn.Address Then
'This returns True
End If
If Range("AA1:ZZ4").Address = Range("AA1:ZZ4").EntireColumn.Address Then
'This returns False
End If
【讨论】:
有趣。你提到的 .EntireColumn 让我思考,我意识到我必须改变处理这个问题的方式。无论我做什么,我的函数的工作方式,它都会接受范围引用的任何组合。通常我使用Intersect(UsedRange, Range(SomeRange))
来约束循环活动,这可能适用于您建议的列测试。但是......我只需要考虑到函数可能最终达到最大行数的事实,并且要么用MsgBox
警告用户,要么让它完成工作。谢谢。【参考方案2】:
不确定我是否完全理解这个问题,但这可能对你有用:
Public Sub Test()
Debug.Print RowCheck(ThisWorkbook.Worksheets("Sheet1").Range("A1:A10"))
End Sub
Public Function RowCheck(InputRange As Range)
Dim u As Long 'used number of rows
Dim x As Long 'max number of rows for any column
Dim r As Long 'number of rows based on input range
With InputRange
u = Cells(Rows.Count, .Columns(1).Column).End(xlUp).Row
r = .Rows.Count
x = Rows.Count
End With
If r = x And u < r Then
RowCheck = "A bad column reference provided"
Else
RowCheck = "This is a valid reference"
End If
End Function
【讨论】:
【参考方案3】:好的,在阅读了大家的建议后,我意识到无论我做什么,传递给我的函数的任何Range
对象都可能包含整个列引用或任何重叠范围引用的组合结果 整个列被选中。
但在翻译中,这意味着...数据中的所有行,也就是 UsedRange
。对于大量数据,UsedRange
实际上可能会在 1048576 处到达最后一行。传递给我的 Function
的 Range
引用的任何组合可能会导致一个巨大的区域覆盖一整列,一直到最大行。
当然,这种情况发生的可能性非常低,但我确实喜欢在我的代码中涵盖所有基础。但这个谜题的关键是UsedRange
。这将创建一个“合成最大最后一行”。如果GrandRange
,由于没有更好的名称,覆盖了UsedRange
中的所有行,那么我的函数将无事可做,也没有数据可返回。所以一个简单的 IF-Then-Exit 应该会给我我正在寻找的解决方案:
If Intersect(UsedRange,LeGrandeRange).Rows.Count = UsedRange.Rows.Count Then
'All rows in `UsedRange` are affected.
'Nothing to do.
Exit Function
Else
'Do everything here.
'Then exit normally.
...
...
...
Endif
【讨论】:
以上是关于如何测试 Excel VBA 范围变量以引用整列..?的主要内容,如果未能解决你的问题,请参考以下文章