【问题标题】:Referencing most recently added worksheet in Excel在 Excel 中引用最近添加的工作表
【发布时间】:2017-11-08 06:39:56
【问题描述】:

当点击说明工作表上的按钮时,我的宏就会运行。它设置为在必须作为工作表从另一个工作簿添加到工作簿的数据上运行。

但是,我不确定添加后工作表的名称是什么。有没有办法让我的宏在最近添加的工作表上运行,而不是寻找特定的工作表名称?

我设想最终用户右键单击工作表选项卡并复制整个工作表。在这种情况下,名称将是 Sheet1。但是,他们可能会创建一个我不知道其名称的新选项卡,然后从数据工作表复制并粘贴到这个新选项卡中。

我的宏当前激活 Sheet1,然后在此工作表上运行宏。但是,用户可能会创建一个名为 Sheet2 或 Data 等的新工作表。在这种情况下,宏将找不到 Sheet1。

有没有一种方法可以让宏找到最新的工作表而不是查找工作表名称?

Dim datasheet As String, location As String, col As String, row As String
Dim i As Integer, LastRow As Integer, LastCol As Integer, lCol As Integer
Dim t As Long, LasRow As Long, LasCol As Long
Dim t As Long, LasRow As Long, LasCol As Long
Dim PSheet As Worksheet, DSheet As Worksheet
Dim PCache As PivotCache
Dim PTable As PivotTable
Dim PRange As Range

' Don't show macro as the macro runs
Application.ScreenUpdating = False
Worksheets("Sheet1").Activate
datasheet = ActiveSheet.Name

'Moves active sheet to end of active workbook.
ActiveSheet.Move _
After:=ActiveWorkbook.Sheets(ActiveWorkbook.Sheets.Count)

【问题讨论】:

  • 您也可以参考工作表的索引 - Worksheets(1).Activate,甚至可以使用循环从一个切换到另一个。
  • 如果你想找到最后一个工作表,你可以使用这个-Worksheet(Worksheets.Count).Activate
  • 也许我们想多了。也许您可以只使用Application.InputBox 要求用户指向他们想要处理的工作表上的范围。例如Set DSheet = Application.InputBox(Prompt:="Select a cell on your data sheet", Type:=8).Worksheet
  • 这似乎是一个非常实用的想法。我会尝试一下。谢谢!
  • 解决@YowE3K 的建议,您可以有一个输入框来询问工作表索引。另一种方法是使用Public const sheetName as string 并在将工作表添加到工作簿时触发以使用工作表名称填充它,我认为这将是最简单的方法(尽管不是特别有效)。

标签: vba excel


【解决方案1】:

假设您不更改各个工作表的代号,即使其他工作表已被删除,最后添加的工作表也应具有最高的数字代号。

dim w as long, lw as long, wsn as string
for w = 1 to worksheets.count
    if clng(replace(worksheets(w).codename, "Sheet", vbnullstring)) > lw then
        lw = int(replace(worksheets(w).codename, "Sheet", vbnullstring))
        wsn = worksheets(w).name
    end if
next w

with worksheets(wsn)
    'do stuff with the last added worksheet
end with

如果可以删除工作表,那么您可能需要仔细检查代号序列在关闭并重新打开工作簿后是否重新启动。 附录:是的,如果工作簿关闭并重新打开,已删除工作表的代号将被重新使用。

此方法应忽略最新工作表已复制到工作表队列中的位置。

【讨论】:

  • 感谢@YowE3K。赞赏。
  • 代码有一个缺点 - 用户必须进入 VBE 才能成功运行。例如。将代码添加到工作簿,保存该工作簿,关闭 Excel,打开 Excel,打开工作簿,添加一些工作表,运行宏(不打开 VBE!),您将得到类型不匹配,因为 worksheets(w).codename""
  • 嗯。在阅读新添加的代号之前,我不需要关闭工作簿并重新打开,但我是在以前保存的工作簿上完成的(即不是无标题)。
  • 您必须 (a) 创建新的工作表在 Excel 实例中您尚未在任何阶段打开 VBE,并且 (b) 确保您运行不打开 VBE 的宏,例如通过使用 Alt-F8 调出宏选择屏幕,或通过与宏关联的按钮。
  • @Excelosaurus “那些被复制的东西” - 迂腐地应该是“那些从具有代号的工作表中复制的将分配一个新的代号,但那些从尚未分配代号的工作表将不会分配代号"
【解决方案2】:

在 ThisWorkbook 模块中,添加:

Public sheetName As String

Private Sub Workbook_NewSheet(ByVal Sh As Object)
    sheetName = ActiveSheet.Name
End Sub

然后在您的代码中查找sheetName

Worksheets(sheetName).Activate

@cyboashu 是对的,这在从另一个工作簿复制工作表时不起作用。

你可以试试这个,当工作簿打开时,它首先用工作表的名称填充一个数组。然后,当您运行宏时,它会查找该数组中的每个 sheetName,如果未找到,则在打开文件后添加该工作表。 将此插入您的工作簿模块中:

Public arrBase

Private Sub Workbook_Open()
 Dim i As Integer
    ReDim arrBase(1 To Sheets.Count)
    For i = 1 To Sheets.Count
        arrBase(i) = ThisWorkbook.Sheets(i).Name
    Next
End Sub

Sub ActivateNewSheet()
    Dim i As Integer
    Dim found As Boolean

    For i = 1 To Sheets.Count
        found = Not IsInArray(Sheets(i).Name, arrBase)
        If found Then Sheets(i).Activate: Exit For
    Next

End Sub

Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
  IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function

【讨论】:

  • @cyboashu 你说得对,这让它变得相当复杂。
  • 不尝试分裂头发,但是当我重命名一张表时会发生什么? :)
  • 它假定重命名的工作表是一张新工作表并与那个工作表一起工作——也就是说,我很笨,没有想到这一点;^)
  • 我和我的老板谈过了,我们将添加到我们的说明中,让使用工作表的人将新工作表命名为“转移”。如果他们没有更改工作表名称或拼写错误,他们将收到一个消息框,指示他们将名称更改为“Transfers”,并且 sub 将结束。感谢所有帮助解决这个问题的人。我很感激。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2019-08-16
相关资源
最近更新 更多