如何从活动表(或任何其他)

时间:2017-11-22 15:11:58

标签: excel vba range worksheet

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

我有两张“Main”和“Data”。 “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()来选择特定的工作表。并且更加激动Select的用途是什么?

3 个答案:

答案 0 :(得分:2)

在同时处理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

我为ActiveSheet进行了一些测试,并在没有指定特定参考的情况下调用集合。假设我有WorkbookWorksheets,一个名为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
  4. 让我们来看看你提到的这三行:

    1. Set SrchRange = Range(Cells(1, 1), Cells(LastRow, 7))
    2. 所有三个集合,即RangeCellsCells。来自同一父代,代码属于或活动表,取决于代码的位置。所以它总是会通过编译器,但并不总能给你正确的结果。

      1. Set SrchRange = Sheets("Data").Range(Cells(1, 1), Cells(LastRow, 7))
      2. Range集合来自Sheets("Data"),但Cells可能来自另一张表,因此有时会出错。

        1. Set SrchRange = Range(Sheets("Data").Cells(1, 1), Sheets("Data").Cells(LastRow, 7))
        2. 两个Cells来自同一张表格,但Range的父级取决于atob('message I want to obfuscate')。因此它与[2]相同,有时会通过,有时会失败。

答案 1 :(得分:1)

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

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

要解决此问题,请使用数据表上的.Activate方法来设置范围。

答案 2 :(得分:0)

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

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

var currentView = '',
  d = new Date(),
  today = d.getDay(),
  dow = 1;
$('#calendar').fullCalendar({
  header: {
    left: 'prev,next',
    center: 'title',
    right: 'month,agendaWeek'
  },
  defaultDate: d,
  navLinks: true,
  firstDay: 1, //Monday
  viewRender: function(view) {
    if (view && view.name !== currentView) {
      if (view.name === 'agendaWeek') {
        dow = today;
      } else {
        dow = 1;
      }
      setTimeout(function() {
        $("#calendar").fullCalendar('option', 'firstDay', dow);
      }, 10);
    }
    if (view) {
      currentView = view.name;
    }
  }
});