"CodeName" Excel table 列用于 VBA
A "CodeName" for an Excel table column for use in VBA
我希望能够通过行号和列名从 Excel table 中检索值(为了代码的可读性和健壮性)。
在公式中,我可以将结构化引用与列 header 文本一起使用,并从 table 中获取一个值,如下所示:
=INDIRECT(ADDRESS(<absolute_line_number>;COLUMN(<table_name>[<column_name>])))
这对公式来说很稳健,因为如果用户重命名该列,公式中对它的所有结构化引用都会自动更新。
但 VBA 代码并非如此。
对于 worksheets,可以定义 Worksheet.CodeName
用于 VBA 代码,如果用户重命名可见的 sheet 名称,代码将保持不变。
Excel table AFAICS 不存在这样的 属性。
我目前最好的想法是制作 table headers 1-cell 命名范围。然后我可以从 VBA 中的 table 中获取一个值,如下所示:
<sheet_codename>.Cells(<line_number>,Range("<range_name>").Column)
然而,这让我很困扰,因为命名范围与 table 断开连接。例如。如果我在 sheet 上重新排列 tables,范围将保留在原来的位置。
有更好的选择吗? "Better"具体意思是:
- 重命名 and/or 重新排列 table 中的列,至少在 sheet
中移动 table
评论
如果列被重命名或重新排列,ListObject
的每个 header 单元格中的注释将保留在那里。
If(!) 您可以通过 Application.DisplayCommentIndicator = xlNoIndicator
隐藏所有评论(所有评论既不能被红色三角形识别,也不能在鼠标悬停期间看到),这可能是一种解决方法:
Private Sub RecognizeColumnsOfListObject()
Dim lo As ListObject
Dim lc As ListColumn
For Each lo In ActiveSheet.ListObjects
For Each lc In lo.ListColumns
Debug.Print lc.Index ' not unique, always 1, 2, 3, ...
Debug.Print lc.Name ' not unique, changeable
If Not lc.Range.Cells(1).Comment Is Nothing Then
Debug.Print lc.Range.Cells(1).Comment.text ' unique
End If
Next lc
Next lo
End Sub
命名范围
如果我为 ListObject
的每个 header 单元格命名,如果我重新排列 ListObject,它会随列一起移动。由于其 Name.Value
或 Name.RefersTo
以 =<ListObjectName>...
开头,我通过以下方式获得绝对地址:
Dim n As Name
With <sheet_codename>
For Each n In .Names
Debug.Print .Range(Mid(n.RefersTo, 1)).Address
Next n
End With
仔细观察,创建 table headers 命名范围没有任何问题。 这是因为 这样的名称被分配给结构化引用而不是原始单元格地址, 因此它们将与列一起移动!
缺点,选择header时,此名称未在地址字段中打印(至少在Office 2007中),这是不便的('cuz,我无法快速查找名称我应该输入代码以获取此列)。
我希望能够通过行号和列名从 Excel table 中检索值(为了代码的可读性和健壮性)。
在公式中,我可以将结构化引用与列 header 文本一起使用,并从 table 中获取一个值,如下所示:
=INDIRECT(ADDRESS(<absolute_line_number>;COLUMN(<table_name>[<column_name>])))
这对公式来说很稳健,因为如果用户重命名该列,公式中对它的所有结构化引用都会自动更新。
但 VBA 代码并非如此。
对于 worksheets,可以定义 Worksheet.CodeName
用于 VBA 代码,如果用户重命名可见的 sheet 名称,代码将保持不变。
Excel table AFAICS 不存在这样的 属性。
我目前最好的想法是制作 table headers 1-cell 命名范围。然后我可以从 VBA 中的 table 中获取一个值,如下所示:
<sheet_codename>.Cells(<line_number>,Range("<range_name>").Column)
然而,这让我很困扰,因为命名范围与 table 断开连接。例如。如果我在 sheet 上重新排列 tables,范围将保留在原来的位置。
有更好的选择吗? "Better"具体意思是:
- 重命名 and/or 重新排列 table 中的列,至少在 sheet 中移动 table
评论
如果列被重命名或重新排列,ListObject
的每个 header 单元格中的注释将保留在那里。
If(!) 您可以通过 Application.DisplayCommentIndicator = xlNoIndicator
隐藏所有评论(所有评论既不能被红色三角形识别,也不能在鼠标悬停期间看到),这可能是一种解决方法:
Private Sub RecognizeColumnsOfListObject()
Dim lo As ListObject
Dim lc As ListColumn
For Each lo In ActiveSheet.ListObjects
For Each lc In lo.ListColumns
Debug.Print lc.Index ' not unique, always 1, 2, 3, ...
Debug.Print lc.Name ' not unique, changeable
If Not lc.Range.Cells(1).Comment Is Nothing Then
Debug.Print lc.Range.Cells(1).Comment.text ' unique
End If
Next lc
Next lo
End Sub
命名范围
如果我为 ListObject
的每个 header 单元格命名,如果我重新排列 ListObject,它会随列一起移动。由于其 Name.Value
或 Name.RefersTo
以 =<ListObjectName>...
开头,我通过以下方式获得绝对地址:
Dim n As Name
With <sheet_codename>
For Each n In .Names
Debug.Print .Range(Mid(n.RefersTo, 1)).Address
Next n
End With
仔细观察,创建 table headers 命名范围没有任何问题。 这是因为 这样的名称被分配给结构化引用而不是原始单元格地址, 因此它们将与列一起移动!
缺点,选择header时,此名称未在地址字段中打印(至少在Office 2007中),这是不便的('cuz,我无法快速查找名称我应该输入代码以获取此列)。