我有一个函数,该函数传递了一系列和两个范围作为参数:

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语句内的行上收到错误,抱怨“对象'Point'的方法'DataLabel'失败”。

尝试查找错误,我尝试打印出循环中使用的每个对象的值,发现与在yverdier偏移一个偏移c的范围内的每个单元格不同,foreach引用了第一列的整个列直通。

通常情况并非如此,为什么在这种情况下for i = 1 to c.rows.count... -loop的行为有所不同?解决问题的最简单方法是什么?

显然我可以做ojit_code,但是我对VBA的奇怪行为感到困惑。

最佳答案

我认为这是预期的行为。

您将yverdier定义为langsone.Columns(2),这意味着yverdierRange类型的集合,集合中有一个(多个单元格)单列。我认为您的解释是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

10-02 00:38