【发布时间】:2016-01-07 12:24:03
【问题描述】:
在我的项目中,我经常利用表和底层的 ListObjects 和 ListColumns。我喜欢它们,因为它们比裸 Range 对象更容易引用和更新。然而,我仍然没有找到一种合理且可维护的方法来处理由许多 ListColumns 组成并在项目中的所有 Worksheets 中引用的多个 ListObjects。
假设我有一个工作表(将(名称)属性设置为“WorksheetA”),其中包含具有少量列(称为 Column1、Column2、...、Column10)的表(称为 TableA)。
现在我想从另一个工作表的代码中引用其中一列。我可以这样做:
WorksheetA.ListObjects("TableA").ListColumns("Column7")
现在,直接使用字符串是一种不好的做法,因为它难以维护并且容易出错。
那么现在呢?
我可以创建专门的模块来将我的字符串存储为常量。例如,名为“Constants”的模块:
Public Const TABLE_A As String = "TableA"
Public Const COLUMN7 As String = "Column7"
然后我的引用可以转换为:
WorksheetA.ListObjects(Constants.TABLE_A).ListColumns(Constants.COLUMN7)
但是,这种解决方案有一些缺点:
- 添加每个表和列后,常量模块的增长速度会快得离谱。
- 引用本身会增长并变得不那么可读。
- 所有工作簿中与表相关的所有常量都被扔进一个大坑。
我可以在 WorksheetA 中存储常量,并通过以下公共函数使它们可用:
Private Const TABLE_A As String = "TableA"
Private Const COLUMN7 As String = "Column7"
Public Function GetTableAName() As String
GetTableAName = TABLE_A
End Function
Public Function GetTableA() As ListObject
Set GetTableA = WorksheetA.ListObjects(TABLE_A)
End Function
Public Function GetTableAColumn7() As ListColumn
Set GetTableAColumn7 = GetTableA().ListColumns(COLUMN7)
End Function
这个解决方案实际上解决了上面提到的所有三个问题,但它仍然有点“脏”和耗时,因为添加新表需要为每列创建一个函数。
你知道如何处理这个问题吗?
EDIT1(为清楚起见):假设用户不得更改任何名称(表名和列名都不能更改)。如果用户这样做,那就是他/她的责任。
EDIT2(为清楚起见):我使用 Column7 作为列名仅作为示例。让我们假设列有更有意义的名称。
【问题讨论】:
-
有趣的问题。如果有一个简单的解决方案,我想我们会在 DAO、ADO、JDBC 等数据访问库中看到它。开发人员唯一能做的就是封装这些“字段名”和“表名”编写“持久”类,即每个表或数据对象一个类。那是“干净”的解决方案,但它增加了一层并且很耗时。建议用于大型数据库项目,但我怀疑 Excel 项目会达到如此规模,以至于该解决方案变得真正必要。
-
我猜你担心在字符串方法中,用户可以更改表名,从而破坏引用。如果工作表上只有一个表,则可以使用索引号 (1) 代替字符串。这仅对每张表最多一张表有效。不知道,这是否适用于您的所有工作表。它会在你的例子中。
-
如果你的列名真的和
Column7一样不起眼,那为什么不通过数字索引来引用它们呢? -
我是常量的大力支持者,但我认为你的想法太过分了。我根本不会为此烦恼。你做了很多工作却没有任何好处。它不会阻止用户更改表或列的名称。然后归结为您想对列做什么。我主要使用 VBA 中的数组。因此,您可以从结构化引用中获取列的所有值,而不是处理所有的引号和对象引用,如下所示:
v = [Table1[Column7]] -
你也可以创建一个通用的 ListColumn 返回函数。将 ws 名称、表名称和列名称传递给它,它会返回 ListColumn 对象。我不会在任何地方定义这些东西的名称。
标签: vba excel worksheet listobject