为啥 Range 有效,但 Cells 无效?

Posted

技术标签:

【中文标题】为啥 Range 有效,但 Cells 无效?【英文标题】:Why does Range work, but not Cells?为什么 Range 有效,但 Cells 无效? 【发布时间】:2022-01-12 12:17:12 【问题描述】:

我试图通过将值从一个范围分配到另一个范围来将一些数据从一个工作簿移动到另一个工作簿。当我使用正常的 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”:应用程序定义或对象定义错误。

有谁知道为什么使用单元格对象会导致我出现问题,或者是否还有其他我不知道的问题?

【问题讨论】:

【参考方案1】:

问题在于Cells 是不合格的,这意味着这些单元格所引用的工作表根据您的代码所在的位置而有所不同。任何时候您调用 RangeCellsRowsUsedRange 或任何返回 Range 对象的东西,并且您没有指定它在哪个工作表上,工作表将根据以下方式分配:

在工作表的类模块中:无论处于活动状态的工作表如何 在任何其他模块中:ActiveSheet

您限定了Range 引用,但Cells 引用没有限定并且可能指向Activesheet。就像写作一样

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

【讨论】:

不需要在指令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 @h2so4 - 等等 - 这是否意味着如果你在里面做Cells(),你就不必限定Range()?这是明确正确的,还是“正常工作”...我总是限定Range(cells(),Cells()) 的所有部分,如果我可以跳过Range() 限定符,那就太好了... @BruceWayne,到目前为止我发现的 Excel 文档对此并不清楚。 (我发现在工作表模块中为范围添加前缀是必须的,但在任何其他类型的模块中都不需要。这是明确正确的还是只是偶然起作用,我不知道...... 我的猜测(这只是一个猜测)是它明确正确。由于 Range 可以采用多种参数类型 - 一个计算为范围的字符串、一个单元格对象、两个单元格对象 - 所以在幕后进行了一些事情来评估您发送的参数类型。如果您发送一个完全限定的单元格对象,我敢打赌它会跳过大部分评估/转换代码,并且它是通过代码的最直接路径。就像它不会将其转换为字符串然后再转换回单元格一样。所以为了我的钱,如果 Cells 是合格的,你可以省略 Range 中的引用。 虽然保持 Range 不合格确实有效,但合格它也会稍微快一些。

以上是关于为啥 Range 有效,但 Cells 无效?的主要内容,如果未能解决你的问题,请参考以下文章

为啥方法 getNodeSuccess 有效,但 getNodeFail 无效?

为啥 localhost 有效但我的别名无效?

列表理解有效,但 for 循环无效——为啥?

为啥 .forEach() 有效但 for 循环无效? [复制]

为啥 summary(object) 有效但 plot(object) 无效?

为啥导入 Vue.js 源代码有效,但模块无效?