Vba 范围,非连续范围中的单元格(和项目)

Vba 范围,非连续范围中的单元格(和项目),vba,excel,Vba,Excel,我在看Holene的问题时,在试图理解MSDN文档时,遇到了以下问题。有人能解释为什么下面几行给出了两种不同的结果吗 Sub test() Debug.Print "With Cells(2)" Debug.Print Intersect(Range("B:B, C:C"), Rows(1)).Cells(2).Address 'prints $C$1 Debug.Print Intersect(Range("B:B, D:D"), Rows(1)).Cells(2).A

我在看Holene的问题时,在试图理解MSDN文档时,遇到了以下问题。有人能解释为什么下面几行给出了两种不同的结果吗

Sub test()
    Debug.Print "With Cells(2)"
    Debug.Print Intersect(Range("B:B, C:C"), Rows(1)).Cells(2).Address 'prints $C$1
    Debug.Print Intersect(Range("B:B, D:D"), Rows(1)).Cells(2).Address 'prints $B$2
    Debug.Print Range("B:B, C:C").Cells(2).Address 'prints $B$2
    Debug.Print Range("B:B, D:D").Cells(2).Address 'prints $B$2
    Debug.Print "With Item(2)"
    Debug.Print Intersect(Range("B:B, C:C"), Rows(1)).Item(2).Address 'prints $C$1
    Debug.Print Intersect(Range("B:B, D:D"), Rows(1)).Item(2).Address 'prints $B$2
    Debug.Print Range("B:B, C:C").Item(2).Address 'prints $B$2
    Debug.Print Range("B:B, D:D").Item(2).Address 'prints $B$2
End Sub
相交(范围(“B:B,C:C”),行(1))
给出一个连续的范围,
$B$1:$C$1
相交(范围(“B:B,D:D”),行(1))
给出一个非连续范围,
$B$1,$D$1

连续范围只有一个。非连续的有多个

当您引用范围的单元格时,没有明确说明哪个
区域
,默认情况下,您得到的是第一个区域

$B$1:$C$1
的第一个区域是
$B$1:$C$1
,该区域的第二个单元格是
$C$1


$B$1、$D$1
的第一个区域是
$B$1
,第二个单元格是(超出区域边界!)
$B$2

如果您不向
单元格提供行和列索引,它将从左到右、从上到下遍历指定范围的第一个区域

如果传递的索引大于该范围内的单元格数,则模式将继续,并根据原始范围内的列数限制遍历的区域

因此,如果您使用:

Range("A1:C1").Cells(3).address
Range("A1").Cells(rows.Count + 1).address
你可以得到1加元。如果将4作为索引传递,它将循环到下一行,得到$A$2

请注意,如果在第一个区域的整列中超过了可用单元格的数量,则会出现错误。因此:

Range("A1").Cells(rows.Count).address
将返回$A$1048576,但如果您使用:

Range("A1:C1").Cells(3).address
Range("A1").Cells(rows.Count + 1).address

您会得到一个错误,而不是$B$1,因为该范围仅限于工作表第一个区域的宽度和高度(即整个A列)。

许多VBA范围方法在连续范围内工作得很好,但当该范围有多个区域时,它们具有特殊行为,即应用于该范围的第一个区域。单元格(i)是其中之一,尽管当使用排序
中的循环为myRange
中的每个单元格跨越范围时,它们将正常工作并跨越所有单元格,即使该范围有多个区域

在测试的第一行中,Intersect方法返回了一个连续的范围B1:C1,因此项目2自然是C1。因为带有一个参数的单元格(i)从左到右逐行跨越该区域

在第二行中,Intersect方法返回了一个多区域范围:(B1,D1)。因此,单元格(i)仅适用于第一个区域,即B1

ps:Range.Cells()以这种方式工作时,不会检查返回的单元格是否属于原始范围

编辑:回答关于第三行的问题


在第三行中,(B:B,C:C)的定义是一个多区域范围,第一个区域是B行,第二个区域是C行。对于人类来说,这等同于(B:C),但对于编译器来说则不然。在定义范围时,编译器不会尝试合并区域,因为在一般情况下,这样的操作需要大量计算,并且很困难。它只是在定义范围时不尝试自动合并区域,而是遵循程序员的定义。我更喜欢这样:遵循程序员的逻辑并保持快速。

感谢@Rory的解释。好的,但是为什么第三行没有返回C1呢?“B:B,C:C”是连续的,所以返回的单元格应该是左上角单元格右侧的单元格,不是吗?@VincentG(B:B,C:C)的定义是一个多区域范围,第一个区域是B行,第二个区域是C行。编译器没有做出足够的努力来认识到这些区域可以合并为一个区域,这一点不要感到惊讶。它是计算密集型的。它只是在定义范围时不尝试自动合并区域,而是遵循程序员的定义。我更喜欢这样,遵循程序员的逻辑并保持快速。正如我对A.s.H答案的评论,我理解(这是我从你对Holene问题的回答中推断出来的),但我无法解释为什么两个相邻的整列不被认为是连续的。我认为A.s.H.很好地回答了这一点。相邻范围与相邻范围不同。抱歉@a.S.H我不理解您的评论。你刚才的回答不是被接受了吗?这封信发错地方了,抱歉。