【问题标题】:How to set Range from activesheet (or any other)如何从活动表(或任何其他)设置范围
【发布时间】:2018-05-06 09:23:15
【问题描述】:

我对 VBA 在不同情况下如何处理 Range 感到困惑..

我有 2 张“主要”和“数据”。 “Main”工作表上有一个按钮,其中包括以下代码:

Worksheets("Data").Activate
Worksheets("Data").Select
LastRow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row    
Dim SrchRange As Range
Set SrchRange = Range(Cells(1, 1), Cells(LastRow, 7))

因为它是 SrchRange 将引用工作表“主要”,即使“数据”工作表被激活并选择。对于“LastRow”,我发现此解决方法将其作为 ActiveSheet.Cells(... 但对于“SrchRange”,我找不到这样做的方法。 我至少尝试过:

Set SrchRange = ActiveSheet.Range(Cells(1, 1), Cells(LastRow, 7))
Set SrchRange = Sheets("Data").Range(Cells(1, 1), Cells(LastRow, 7))
Set SrchRange = Range(ActiveSheet.Cells(1, 1), ActiveSheet.Cells(LastRow, 7))

所有这些都会给我一个运行时错误“1004”。如果更详细地描述 Range,我不明白情况会如何变化。即使使用 Sheets 和 ActiveSheet,它不应该仍然是范围吗?我应该如何做到这一点?

我设法通过完全不使用 Range 变量来规避这个问题。 这是使用 SrchRange 变量的部分。

For Each HeaderMatch In SrchRange
If HeaderMatch Like HeaderKeyWord Then

我用这个代替了:

For Each HeaderMatch In ActiveSheet.Range(ActiveSheet.Cells(1, 1), 
ActiveSheet.Cells(LastRow, 7))
If HeaderMatch Like HeaderKeyWord Then

我更喜欢第一个,因为它更清楚一点,而且不符合原则,我想让它按我的意图工作,因为我知道这是可能的,但我不知道如何。

我不太了解 ActiveSheet 和选择工作表的概念。如果我仍然需要将其称为 ActiveSheet,那么激活工作表有什么意义?如果您仍然需要始终使用参考,为什么不只使用 Sheets() 来选择特定的工作表。更要搅动它,选择有什么用?

【问题讨论】:

  • Set SrchRange = Sheets("Data").Range(Sheets("Data").Cells(1, 1), Sheets("Data").Cells(LastRow, 7))
  • SrchRange 将在您激活后引用工作表“DATA”。不知道你是如何让它仍然参考“MAIN”表的。但是您的方法是使用activesheet,这从来都不是一件好事。尝试按照其他人的建议直接引用您的工作表。
  • 在我看来,如果您从“MAIN”表调用marco,即使您已激活“DATA”,RangeCells 集合的默认母集将是“MAIN”表" 表格优先。
  • 我已经测试了该代码,它将活动表设置为 DATA,范围和单元格默认为活动表。激活 DATA 后,您调用宏的工作表与 activesheet 有什么关系?
  • 包含代码的按钮被放置在“MAIN”表上。我再次测试了代码,并且在 LastRow 语句中没有 ActiveSheet,即使激活并选择了工作表“数据”,它也会返回数字 3,这是“主”工作表上的行数。如果活动表。或Shees(“数据”)。被添加到 LastRow 语句,然后它会给出数字 513,这是“数据”表中的行数。

标签: excel vba range worksheet


【解决方案1】:

同时处理 2 个或更多工作表时,使用 ActiveSheet 会造成混淆。最好将工作表设置为变量,例如以下代码:

Dim ws1 as Worksheet, ws2 As Worksheet
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")

然后用这两个指向工作表的变量来做你的事情。此外,使用With 块将使代码更清晰地告诉您正在处理哪个工作表。因此,您给出的代码可以重写如下:

Dim wsData As Worksheet
Set wsData = Worksheets("Data")
With wsData
    LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
    Dim SrchRange As Range
    Set SrchRange = .Range(.Cells(1, 1), .Cells(LastRow, 7))
End With

我对@9​​87654326@ 进行了一些测试,并在没有指定特定参考的情况下调用集合。假设我有一个 Workbook 和 2 个 Worksheets,一个名为 SheetA,另一个是 SheetB。下面的代码放在SheetA

Private Sub test()
    Worksheets("B").Activate
    MsgBox Range("A1").Parent.Name
    MsgBox ActiveSheet.Range("A1").Parent.Name
End Sub

结果是第一个MsgBox 给出SheetA,第二个给出SheetB。因此,我假设如果您在没有指定引用的情况下调用集合,则默认为调用 marco 的集合。

然后我将代码放入一个模块中。这一次 MsgBox 给出相同的结果 SheetB 无论在执行代码之前哪个工作表处于活动状态。所以这是我的结论。

  1. 调用集合不指定引用,默认是代码所在的地方。
  2. 在模块级别时,默认为当前活动工作表。
  3. 指定引用是一种很好的方式,可以避免一些不可预知的错误。请注意,在同时处理多个工作簿时,最好指定 Workbook

让我们看看你问的这三行:

  1. Set SrchRange = Range(Cells(1, 1), Cells(LastRow, 7))

所有三个集合,即RangeCellsCells。来自同一个父级,代码属于还是活动表,取决于代码的位置。所以它总是会通过编译器,但并不总是给你正确的结果。

  1. Set SrchRange = Sheets("Data").Range(Cells(1, 1), Cells(LastRow, 7))

Range 集合来自Sheets("Data"),但Cells 可能来自另一个工作表,因此有时会出错。

  1. Set SrchRange = Range(Sheets("Data").Cells(1, 1), Sheets("Data").Cells(LastRow, 7))

Cells 都来自同一张表,但 Range 的父级取决于。所以和[2]一样,有时通过,有时失败。

【讨论】:

  • ws1 是您代码中的一个变体,ws2 是一个工作表。应该是Dim ws1 As Worksheet, ws2 As Worksheet
  • 感谢您的评论。所以我总是用错误的方式编码:/
  • @newacc2240 是的。 Rubberduck(我管理的一个 OSS VBIDE 插件项目)可能也可以帮助你改掉其他坏习惯 =)
  • @Mat'sMug 仍在尝试授权安装 Rubberduck。我可能得偷偷摸摸地一大早在他们开始工作之前问它。
  • 如果我将范围和单元格都定义在 sheet("Data") 下,它仍然会给我一个运行时错误。
【解决方案2】:

我自己也遇到过这个问题。原因是.End() 方法只适用于活动工作表。

Microsoft's documentation.End()相当于按end+end+ , end+end+。只读范围对象。这就是为什么使用Set Range1 = Sheets("Data").Range(("A1"),Range("A1").End(Xldown)) 设置范围仅在当前选择数据时才有效。

作为一种解决方法,使用数据表上的.Activate 方法来设置范围。

【讨论】:

    【解决方案3】:

    如果所有工作表都在包含 vba 代码的工作簿中,则可以使用工作表代码名称,而不必设置为单个变量。

    例如,我将工作表“Data”的代码名称更改为 cnData 并使用它...

    With cnData
        LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row
        Dim SrchRange As Range
        Set SrchRange = .Range(.Cells(1, 1), .Cells(LastRow, 7))
    End With
    

    【讨论】:

      【解决方案4】:

      感谢您的快速回复。之前的两个答案似乎可以解决问题。我通过将 Worksheets 定义为变量并通过 with 块操作它们来使代码正常工作。

      我仍然很困惑这一切是如何运作的。有人可以就这些不同的陈述有何不同提供一些见解吗?

      LastRow = Cells(Rows.Count, 1).End(xlUp).Row
      LastRow = Sheets("Data").Cells(Rows.Count, 1).End(xlUp).Row
      

      这两个似乎都可以正常工作。第一个是从“主”表中获取值,即使“数据”表已激活。第二个将给出“数据”表的最后一行。即使结果不同,它们也都可以工作。

      Set SrchRange = Range(Cells(1, 1), Cells(LastRow, 7))
      Set SrchRange = Sheets("Data").Range(Cells(1, 1), Cells(LastRow, 7))
      Set SrchRange = Range(Sheets("Data").Cells(1, 1), Sheets("Data").Cells(LastRow, 7))
      

      但是对于这三个只有第一个有效,但其他会给出运行时错误。我也尝试过不使用 Set 并且没有像 LastRow 一样将变量预定义为 As Range。

      我认为问题在于,如果例如 Sheets("Data"),则语句不再是范围。被添加。那么我的变量可能应该是别的东西?即使 Sheets("Data").LastRow 变量似乎如何工作。被添加?

      【讨论】:

      • RangeWorksheet 的子集,但LastRowVariable,它不是一个对象。添加Sheets("Data")的目的是告诉excel它应该查看哪个表。
      • 我认为Range(Cells(1, 1), Cells(LastRow, 7))Sheets("Data").Range(Cells(1, 1), Cells(LastRow, 7)) 都是范围,因此可以放入定义为范围的 SrchRange。显然情况并非如此,我试图找出原因。
      • 后面的其实是Sheets("Data").Range(Sheets("Unknown").Cells(1,1),Sheets("Unknown").Cells(LastRow, 7))
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 2017-04-29
      • 1970-01-01
      • 2017-01-02
      • 1970-01-01
      相关资源
      最近更新 更多