我有一个函数,它传递一系列和两个范围作为参数:
Call settInnISerie(.SeriesCollection("Toppsuging"), r, langsone.Columns(2))
Sub settInnISerie(srs As Series, xverdier As Range, yverdier As Range)
Dim c As Range
Dim i As Long
srs.XValues = xverdier
srs.Values = yverdier
i = 1
srs.ApplyDataLabels
For Each c In yverdier.Offset(0, -1)
If Not IsError(c) And i <= srs.Points.Count Then
srs.Points(i).DataLabel.Text = "=" & Replace(c.Address(external:=True), "[" & ThisWorkbook.Name & "]", "", 1, -1, vbTextCompare)
End If
i = i + 1
Next c
End Sub
然而,我在if语句中的行上出现错误,抱怨&#34; Method&#39; DataLabel&#39;对象&#39;点&#39;失败&#34;
尝试追踪错误,我尝试打印出循环中使用的每个对象的值,并发现不是像我预期的那样在yverdier
范围内偏移一个范围内的每个单元格而不是{ {1}}引用第一个直通的整个列。
通常当我使用类似的构造时情况并非如此,为什么c
- 循环在这种情况下表现不同?解决问题的最简单方法是什么?
显然我可以做foreach
,但我很困惑,对我来说,VBA是一种奇怪的行为。
答案 0 :(得分:3)
我认为这是预期的行为。
您将yverdier
定义为langsone.Columns(2)
,这意味着yverdier
是Range
类型的集合,集合中包含一列(多个单元格)。我认为你的解释是yverdier
是由langsone.Columns(2)
内的单元组成的单一范围,但两者之间存在细微差别。
因此,For...Each
上的Range
循环将迭代集合中的每一列(单个列),而不是Cells
。如果编码,我想你会得到你的欲望行为:
For Each c In yverdier.Offset(0, -1).Cells
此示例代码和调试输出显示了我在实践中的含义 - 只需创建一个空白工作簿并将此代码放在Module
中:
Option Explicit
Sub Test()
Dim rngSource As Range
Dim rng As Range
Set rngSource = Sheet1.Range("A1:D3")
Debug.Print "Columns:"
For Each rng In rngSource.Columns
Debug.Print rng.Address
Next rng
Debug.Print "Rows:"
For Each rng In rngSource.Rows
Debug.Print rng.Address
Next rng
Debug.Print "Cells:"
For Each rng In rngSource.Cells
Debug.Print rng.Address
Next rng
Debug.Print "No property:"
For Each rng In rngSource
Debug.Print rng.Address
Next rng
End Sub
将输出:
Columns:
$A$1:$A$3
$B$1:$B$3
$C$1:$C$3
$D$1:$D$3
Rows:
$A$1:$D$1
$A$2:$D$2
$A$3:$D$3
Cells:
$A$1
$B$1
$C$1
$D$1
$A$2
$B$2
$C$2
$D$2
$A$3
$B$3
$C$3
$D$3
No property:
$A$1
$B$1
$C$1
$D$1
$A$2
$B$2
$C$2
$D$2
$A$3
$B$3
$C$3
$D$3