如何在处理表格时编写清晰且可维护的代码?

在我的项目中,我经常利用表和底层的ListObjects和ListColumns。 我喜欢它们,因为它们比裸露的Range对象更容易引用和更新。 然而,我仍然没有find一种理智和可维护的方式来处理由多个ListColumns组成的多个ListObjects,并在项目中的所有Worksheet中被引用。

比方说,我有工作表(与(名称)属性设置为“WorksheetA”)包含表(称为TableA)与less数列(称为Column1,Column2,…,Column10)。

现在我想引用另一个Worksheet的代码中的一列。 我可以这样做:

WorksheetA.ListObjects("TableA").ListColumns("Column7") 

现在,直接使用string是一个糟糕的做法,因为它很难维护,容易出错。

所以现在怎么办?

我可以创build专用的模块来存储我的string作为常量。 例如,称为“常量”的模块:

 Public Const TABLE_A As String = "TableA" Public Const COLUMN7 As String = "Column7" 

然后我的参考可以转换为:

 WorksheetA.ListObjects(Constants.TABLE_A).ListColumns(Constants.COLUMN7) 

但是,这个解决scheme有一些缺点:

  1. 在添加每个表格和列的情况下,常量模块会快速增长。
  2. 引用本身增长,变得不太可读。
  3. 所有与所有工作簿中的表相关的常量被扔进一个巨大的坑里。

我可以在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 

这个解决scheme实际上解决了上面提到的所有三个问题,但是仍然有点“肮脏”且耗时,因为添加一个新表格需要为每个列创build一个函数。

你最好知道如何处理这个问题?

编辑1(为了清楚):假设用户不能更改任何名称(表名或列名)。 如果用户这样做,这是他/她的责任。

编辑2(为了清楚):我只使用Column7作为列名作为例子。 我们假设列有更多有意义的名字。

这是我的两分钱。 我不是一个受过良好教育的程序员,但是我确实得到了报酬,所以我想这让我很专业。

第一道防线是我创build一个类来build模一个表。 我从表格中填入课程,其他代码甚至不知道数据的位置。 当我初始化时,我会运行代码

 clsEmployees.FillFromListObject wshEmployees.ListObjects(1) 

然后在课堂上,代码看起来像

 vaData = lo.DataBodyRange.Value ... clsEmployee.EeName = vaData(i,1) clsEmployee.Ssn = vaData(i,2) etc 

每个工作表只有一个ListObject。 这是我的规则,我从来没有打破它。 任何有权访问该工作表的人都可以重新排列这些列并打破我的代码。 如果我想用Excel作为数据库,有时候我会这样做,那么我就冒这个风险。 如果它是如此重要,我不能冒这个风险,那么我将我的数据存储在SQL Server,SQLite或JET中。

而不是将范围放在数组中,我实际上可以调出ListColumns名称。 这样,如果有人重新安排列,我的代码将仍然工作。 但它介绍了他们可以重新命名列,所以我只是冒一个风险换另一个。 它会使代码更具可读性,所以它可能是你想要做的交易。 我喜欢从数组中填充的速度,所以这是我做的交易。

如果我的项目足够小或者应该直接使用ListObjects,那么我遵循与我为任何string相同的规则。

  • 我只用一次代码中的string。
  • 如果我不止一次地使用它,我会使程序级别保持不变
  • 如果我在多个程序中使用它,我试图通过它作为一个参数
  • 如果我不能把它作为一个parameter passing,我会做一个模块级别的常量
  • 如果这两个程序在不同的模块中,我首先问自己为什么两个程序在不同的模块中使用相同的常量。 相关程序不应该在同一个模块中吗?
  • 如果这两个程序真的属于不同的模块,那么我试图把它作为一个参数
  • 如果这些都不起作用,那么它确实是一个全球性的常量,我在MGlobals模块中进行设置。

如果MGlobals占用了大约一半的屏幕,我正在做一些错误的事情,我需要退后一步,思考我想要完成的事情。 然后我做一个自定义的类。