为什么 Range 有效,但 Cells 不行?

Why does Range work, but not Cells?

提问人:user2597163 提问时间:7/19/2013 最后编辑:user2597163 更新时间:6/26/2019 访问量:48521

问:

我试图通过将值从一个范围分配到另一个范围来将一些数据从一个工作簿移动到另一个工作簿。当我使用普通的 Range 语法指定目标范围 (Range(“A1:B2”)) 时,我的代码可以工作,但是如果我尝试使用 Range, Cells 语法(Range(Cells(1,1),Cells(2,2)))我的代码不起作用。

我激活了目标工作簿 (ActiveWorkbook) 并让代码在源工作簿 (ThisWorkbook) 中运行。

此代码的工作原理:

ActiveWorkbook.Worksheets(1).Range("A1:B2").Value _
= ThisWorkbook.Worksheets(1).Range(Cells(1, 1), Cells(2, 2)).Value

但此代码不会:

ActiveWorkbook.Worksheets(1).Range(Cells(1, 1), Cells(2, 2)).Value _
= ThisWorkbook.Worksheets(1).Range(Cells(1, 1), Cells(2, 2)).Value

我得到的错误是运行时错误“1004”:应用程序定义或对象定义错误。

有谁知道为什么使用单元格对象会给我带来问题,或者是否有其他一些我不知道的问题?

VBA 范围 单元

评论


答:

48赞 Dick Kusleika 7/22/2013 #1

问题是它是不合格的,这意味着这些单元格引用的工作表会根据代码所在的位置而有所不同。每当您调用 or or or 或 或 任何返回 Range 对象的内容,并且您没有指定它在哪个工作表上时,都会根据以下条件分配工作表:CellsRangeCellsRowsUsedRange

  • 在工作表的类模块中:无论活动内容如何,该工作表
  • 在任何其他模块中:ActiveSheet

您限定了引用,但该引用是非限定的,并且可能指向 Activesheet。这就像写作一样RangeCells

ThisWorkbook.Worksheets(1).Range(ActiveSheet.Cells(1, 1), ActiveSheetCells(2, 2)).Value

当然,除非 ThisWorkbook.Worksheets(1) 碰巧处于活动状态,否则这没有任何意义。我经常喜欢使用 With 块,这样我就可以确保一切都是完全合格的。

With Sheets(1)
    .Range(.Cells(1,1), .Cells(2,2)).Value = "something"
End With

但是你引用了两个不同的工作表,所以你最好使用短工作表变量,比如:

Dim shSource As Worksheet
Dim shDest As Worksheet

Set shSource = ThisWorkbook.Worksheets(1)
Set shDest = Workbooks("myBook").Worksheets(1)

shDest.Range(shDest.Cells(1, 1), shDest.Cells(2, 2)).Value = _
    shSource.Range(shSource.Cells(1, 1), shSource.Cells(2, 2)).Value

但实际上,如果你要对参数进行硬编码,你可以像这样清理它Cells

shDest.Cells(1, 1).Resize(2, 2).Value = shSource.Cells(1, 1).Resize(2, 2).Value

评论

1赞 h2so4 4/22/2017
无需在指令中限定范围,这也是正确的shDest.Range(shDest.Cells(1, 1), shDest.Cells(2, 2)).Value = _ shSource.Range(shSource.Cells(1, 1), shSource.Cells(2, 2)).Value Range(shDest.Cells(1, 1), shDest.Cells(2, 2)).Value= _ Range(shSource.Cells(1, 1), shSource.Cells(2, 2)).Value
1赞 BruceWayne 1/23/2020
@h2so4 - 等等 - 所以这是否意味着如果你做内部,你不必获得资格?这是明确正确的,还是“只是工作”......我一直对 a 的所有部分都进行了资格认证,如果我能跳过资格赛,那就太好了......Range()Cells()Range(cells(),Cells())Range()
1赞 h2so4 1/24/2020
@BruceWayne,到目前为止,我发现的 Excel 文档对此尚不清楚。(我发现在工作表模块中必须为范围添加前缀,但在任何其他类型的模块中都不需要。这是明确正确的还是只是偶然起作用,我不知道......
2赞 Dick Kusleika 1/24/2020
我的猜测(这只是一个猜测)是它绝对正确。由于 Range 可以采用各种参数类型 - 计算结果为范围的字符串、单个单元格对象、两个单元格对象 - 因此在幕后有一些东西可以评估您发送的参数类型。如果你发送一个完全限定的单元格对象,我敢打赌它会跳过大部分计算/转换代码,它是通过代码的最直路径。就像它不会将其转换为字符串然后返回单元格一样。因此,为了我的钱,如果单元格是合格的,您可以省略 Range 中的引用。
2赞 chris neilsen 3/28/2020
虽然让 Range 不合格确实有效,但合格它的速度也略快一些。