【问题标题】:Is the . in .Range necessary when defined by .Cells?是个 。在 .Cells 定义时需要在 .Range 中吗?
【发布时间】:2016-07-21 23:05:30
【问题描述】:

人们普遍认为这不是“最佳实践”。

dim rng as range
with thisworkbook    '<~~ possibly set an external workbook 
    with .worksheets("sheet1")
        set rng = .range(cells(2, 1), cells(rows.count, 1).end(xlup))
    end with
end with

定义Range object 范围的两个Range.Cells 属性将默认为ActiveSheet property。如果这不是 Sheet1(定义为 With ... End With statement 中的 .Parent),则分配将失败,

Run-tim error '1004': Application-defined or object-defined error

解决方案:使用.Cells 而不是Cells。结案。

但是……

Range.Cells 属性都继承.Parent 工作表属性(在With ... End With statement 中定义)时,此Range object 定义中是否需要.

这怎么可能,

dim rng as range
with thisworkbook    '<~~ possibly set an external workbook 
    with .worksheets("sheet1")
        ' define rng as Sheet1!A2 to the last populated cell in Sheet1!A:A
        set rng = .range(.cells(2, 1), .cells(rows.count, 1).end(xlup))  '<~~ .range
    end with
end with
debug.print rng.address(0, 0, external:=true)

...与此不同,

dim rng as range
with thisworkbook    '<~~ possibly set an external workbook 
    with .worksheets("sheet1")
        ' define rng as Sheet1!A2 to the last populated cell in Sheet1!A:A
        set rng = range(.cells(2, 1), .cells(rows.count, 1).end(xlup))  '<~~ range not .range
    end with
end with
debug.print rng.address(0, 0, external:=true)

当定义范围范围的参数不明确时,我们使用.range;例如.range([A1]) A1 单元格可以来自任何工作表,默认为 ActiveSheet property 而没有 .。但是,当定义范围对象的范围正确引用了它的父工作表时,为什么我们需要引用它的父对象呢?

【问题讨论】:

    标签: excel vba range


    【解决方案1】:

    这里我的看法略有不同。

    这是必需的。你不能总是控制用户可以从哪里运行代码。

    请考虑这几个测试用例

    场景

    工作簿有 2 个工作表。 Sheet1 和 Sheet2


    测试 1(从模块运行)

    两个代码给出相同的结果

    测试 2(从 Sheet1 的工作表代码区域运行)

    两个代码给出相同的结果

    测试 3(从 Sheet2 的工作表代码区域运行)

    '~~> This code fails
    set rng = range(.cells(2, 1), .cells(rows.count, 1).end(xlup))
    

    你会得到Application Defined or Object defined错误

    因此始终建议正确限定您的对象,以便代码可以在任何地方运行

    【讨论】:

    • 我和悉达多在一起。这真的取决于什么是“ActiveSheet”,如果 activesheet 是图表表,那么底部的代码集肯定会出错,除非使用了.Range(...)
    【解决方案2】:

    不,如果括号内的单元格引用是合格的,则不需要.,除非代码位于Worksheet 模块中。也就是说,运行 set rng = .range(.cells(...), .cells(...)) 比运行 set rng = range(.cells(...), .cells(...)) 更快,所以包含 . 会有些好处。

    对于Worksheet 模块,. 是必需的。

    【讨论】:

    • 现在更有意义了:)
    【解决方案3】:

    答案似乎是:仅当代码位于 Worksheet 对象中时。我强烈怀疑这是因为 Worksheet 对象是唯一既可扩展又具有Range 函数的对象。当从 Worksheet 调用 Range 时,该对象的 Range 函数具有作用域。当代码位于 ThisWorkbook 或用户模块或类中时,具有最近可用范围的 Range 函数是全局 Range 对象(当然假设没有用户定义的 Range 函数)。那个绑定到Application必须根据传递的参数解析它并将调用转发到正确的工作表。

    【讨论】:

    • @Jeeped - 我在测试它时实际上有点惊讶。将行 Debug.Print Range("A1").Parent.Name 放入工作表中,然后激活其他内容并运行它。
    • @chrisneilsen - 实际上,我不是。单元格引用是否合格并不重要 - 从工作表模块调用的Range(Foo) 将被评估为Me.Range(Foo)。从其他任何地方调用的Range(Foo) 将评估为ActiveSheet.Range(Foo)。论据无关紧要。事实上,由于Cells 具有与Range 相同的作用域行为,因此相对于 Worksheet 对象表现出完全相同的作用域解析问题。
    • 我不得不承认,工作表代码表的 Private 特性覆盖了“独狼”范围对象的特性,但同时您不能在具有来自另一个工作表的单元格范围的工作表,除非您只使用它们的字符串地址。
    • @Jeeped - 不用担心,首先并不意味着您认为最有用的答案。如果您觉得 Siddharth 的回答对个人或其他任何可能偶然发现这个问题的人更有帮助,请不要犹豫,在我的帐户上接受它。
    • @BrakNicku 不,这是 COM 意大利面条的问题。不合格的Range 不会神奇地作用于Application,而是作用于隐藏的_Global 模块,并最终解析为ActiveSheet 是什么。如果您正在查看实际的内部结构,MSDN 正在讲述完全误导的半真半假。工作表的代码隐藏中使用的不合格Range 仅解析为该工作表,因为这就是 VBA 中作用域的工作方式; Me 有一个Range 属性,所以不合格的Range 就像Me.Range,就像Me.TextBox1TextBox1 在表单的代码隐藏中一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多