Excel表格页名称与Visual Basic表格名称的区别

22

看起来 Visual Basic 不能根据用户修改的工作表名称引用工作表。工作表选项卡可以更改其名称,但似乎 Visual Basic 仍认为工作表名称为 Sheet1 等,尽管工作簿选项卡已更改为有用的名称。

我有这个:

TABname = rng.Worksheet.Name  ' Excel sheet TAB name, not VSB Sheetx name.

但我希望在Visual Basic程序中使用工作表名称。到目前为止,我能想到的最好方法是选择工作表选项卡和Visual Basic名称之间进行Select Case操作,但这并不能使我满意。

Visual Basic必须知道Sheet1、Sheet2等名称。我该如何将它们与Excel选项卡名称相关联,以便我不必维护一个随着每个新工作表或工作表选项卡重新命名而更改的查找表?


1
我从未遇到过这样的情况,即工作表名称已更改但VB无法看到更改。您能展示一下相关代码吗? - M.A. Hanin
10个回答

30

在Excel对象模型中,工作表有两个不同的名称属性:

Worksheet.Name
Worksheet.CodeName

Name属性是可读写的,包含显示在工作表标签上的名称。用户和VBA都可以更改。

CodeName属性是只读的。

您可以通过以下两种方式引用特定的工作表:

  • Worksheets("Fred").Range("A1"),其中Fred是.Name属性值
  • Sheet1.Range("A1"),其中Sheet1是工作表的codename。

现在我想要一个带有ParamArray输出的Visual Basic函数,并且我希望该输出可以在另一个函数中使用,而不必将其放到工作表中再选择到第二个函数中。是否有一种方法可以在Visual Basic中在函数之间传递数组?感谢您的回复。 - SteveNeedsSheetNames
5
"CodeName属性是只读的":这仅在运行时成立。在VBA编辑器中的设计时,可以设置CodeName属性:选择Microsoft Excel对象列表中的工作表并按F4显示属性。带括号的"(Name)"属性是CodeName,而不带括号的"Name"属性是工作表选项卡上显示的名称。 - Wim
这就是我想知道的,非常感谢! - Birasafab

5
这将会把所有工作表对象的名称(从VBA编辑器的角度)修改为与它们的工作表名称(从Excel的角度)相匹配:
Sub ZZ_Reset_Sheet_CodeNames()
'Changes the internal object name (codename) of each sheet to it's conventional name (based on it's sheet name)

    Dim varItem As Variant

    For Each varItem In ThisWorkbook.VBProject.VBComponents
        'Type 100 is a worksheet
        If varItem.Type = 100 And varItem.Name <> "ThisWorkbook" Then
            varItem.Name = varItem.Properties("Name").Value
        End If
    Next
End Sub

需要注意的是,对象名称(代号)“(Name)” 被属性名称 “Name” 覆盖,因此它必须作为子属性引用。


1
“无法信任对 Visual Basic 项目的编程访问” - 启用宏设置 https://dev59.com/k18e5IYBdhLWcg3wja1I#25638419/ - user423430
.Properties("Name").Value 正是我正在寻找的,谢谢! - baldmosher
列出 Proc Lets set Get Subs Func 的问题困扰了我几年,其中模块名称、工作表名称和代码名称都很混乱。这个修复了那个问题。非常感谢你的代码,Harry S。 - Harry S

3

您应该能够通过用户提供的名称引用工作表。您确定您正在引用正确的工作簿吗?如果您在引用工作表时打开了多个工作簿,那肯定会导致问题。

如果这是问题所在,使用ActiveWorkbook(当前活动的工作簿)或ThisWorkbook(包含宏的工作簿)应该可以解决问题。

例如:

Set someSheet = ActiveWorkbook.Sheets("Custom Sheet")

3

实际上,“Sheet1”对象/代码名称可以更改。在VBA中,单击Excel对象列表中的Sheet1。在属性窗口中,您可以将Sheet1更改为rng。

然后,您可以引用rng作为全局对象,无需先创建变量。因此,debug.print rng.name就可以正常工作了。不再需要Worksheets(“rng”)。name。

与选项卡不同,对象名称具有与其他变量相同的限制(即不能有空格)。


2
这是一个非常基础的解决方案(也许我没有完全理解问题的重点)。ActiveSheet.Name将返回当前选项卡名称的字符串(并且将反映用户未来的更改)。我只需调用活动工作表,设置变量,然后将其用作Worksheets对象。在这里,我正在从表中检索数据以设置部门报告。此宏将适用于我的工作簿中任何格式化为相同筛选器(条件和复制范围)的工作表 - 每个部门都有自己的工作表,并可以通过使用此单个宏更改条件并进行更新。
Dim currRPT As String
ActiveSheet.Select
currRPT = (ActiveSheet.Name)
Range("A6").Select
Selection.RemoveSubtotal
Selection.AutoFilter
Range("PipeData").AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=Range _
    ("C1:D2"), CopyToRange:=Range("A6:L9"), Unique:=True
Worksheets(currRPT).AutoFilter.Sort.SortFields.Clear
Worksheets(currRPT).AutoFilter.Sort.SortFields.Add Key:= _
    Range("C7"), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:= _
    xlSortNormal

列出 Proc Lets set Get Subs Func 的问题困扰了我几年,其中模块名称、工作表名称和代码名称都很混乱。这个修复了那个问题。非常感谢你的代码,Harry S。 - Harry S

0

至少有两种不同的方法可以获取Worksheet对象

  • 通过DanM提到的SheetsWorksheets集合
  • 通过未经修饰的对象名称

当创建一个包含三个工作表的新工作簿时,将存在四个对象,您可以通过未经修饰的名称访问:ThisWorkbookSheet1Sheet2Sheet3。这使您可以编写如下内容:

Sheet1.Range("A1").Value = "foo"

虽然这似乎是一个有用的快捷方式,但问题在于工作表被重命名时。即使将工作表重命名为完全不同的名称,未经限定的对象名称仍然保持为Sheet1

这样做是有一些逻辑的,因为:

  • 工作表名称不符合变量名称的相同规则
  • 您可能会意外掩盖现有的变量

例如(在Excel 2003中测试),创建一个新的 Workbook ,其中包含三个工作表。创建两个模块。在一个模块中声明以下内容:

Public Sheet4 As Integer

在另一个模块中放置:

Sub main()

Sheet4 = 4

MsgBox Sheet4

End Sub

运行此程序,消息框应该正确显示。

现在将第四个工作表添加到工作簿中,创建一个 Sheet4 对象。尝试再次运行主程序,此时您会收到一个“对象不支持此属性或方法”的错误提示。


0

我不得不采取这种方式,但这会带来维护方面的问题。

Function sheet_match(rng As Range) As String  ' Converts Excel TAB names to the required VSB Sheetx names.
  TABname = rng.Worksheet.Name                ' Excel sheet TAB name, not VSB Sheetx name. Thanks, Bill Gates.
' Next, match this Excel sheet TAB name to the VSB Sheetx name:
   Select Case TABname 'sheet_match
      Case Is = "Sheet1": sheet_match = "Sheet1"  ' You supply these relationships
      Case Is = "Sheet2": sheet_match = "Sheet2"
      Case Is = "TABnamed": sheet_match = "Sheet3" 'Re-named TAB
      Case Is = "Sheet4": sheet_match = "Sheet4"
      Case Is = "Sheet5": sheet_match = "Sheet5"
      Case Is = "Sheet6": sheet_match = "Sheet6"
      Case Is = "Sheet7": sheet_match = "Sheet7"
      Case Is = "Sheet8": sheet_match = "Sheet8"
   End Select
End Function

0

使用工作表代号也是我需要的答案,以防止一系列宏崩溃 - ccampj上面的答案反映了这个解决方案(附有屏幕截图)


0
也许我错了,但是你可以打开一个工作簿,选择一个工作表并将其属性(名称)更改为任何你需要的名称。 这会覆盖“Sheetx”命名约定。这些名称也显示在VBA编辑器中。
如何手动完成: 1. 选择工作簿中的工作表(我倾向于创建模板)。 2. 将其选项卡名称设置为您喜欢的任何名称(“foo”)。 3. 单击开发人员菜单(您之前启用了它,对吧?)。 4. 找到“属性”并点击它,以打开该工作表的属性窗口。 5. 字母列表中的第一项是(名称),在(名称)右侧是“Sheetx”。 6. 单击该字段并更改它(我们使用“MyFav”)。 7. 关闭属性窗口。 8. 转到Visual Basic编辑器。 9. 查看您刚修改的工作簿中的工作表。 10. 观察MicroSoft Excel对象显示您刚刚更改的名称“MyFav”,以及在括号中的工作表选项卡名称(“foo”)。
如果你愿意,你也可以通过编程方式更改.CodeName。我使用非Sheet名称来方便我的模板操作。您不必使用通用默认值“Sheetx”。

-1

我想我可能有一个替代方案。虽然它有点丑陋,但似乎可以工作。

Function GetAnyNameValue(NameofName) As String
    Dim nm, ws, rng As String
    nm = ActiveWorkbook.Names(NameofName).Value
    ws = CStr(Split(nm, "!")(0))
    ws = Replace(ws, "'", "")
    ws = Replace(ws, "=", "")
    rng = CStr(Split(nm, "!")(1))
    GetAnyNameValue = CStr(Worksheets(ws).Range(rng).Value)
End Function

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接