excel - Excel VBA 工作表范围存储位置最佳实践
问题描述
我从未找到一个很好的解决方案的问题之一是在 VBA 项目的工作表中定义事物的位置。如果你们中的任何人不得不使用 VBA 和工作表函数构建工作表,那么您就会知道这很重要。运行脚本并意识到保存 f 测试结果的单元格从 F20 移动到 H20 是非常令人沮丧的,因为您必须添加两列数据并且您没有在 VBA 中找到所有范围引用需要更新。
我正在寻找更多有助于系统存储 VBA 范围引用的想法和最佳实践,这些引用易于更新并与不断发展的电子表格保持一致。
我列出了我认为常见的选项。我之前做过前四个,但它们并没有完全做到这一点。
选项1:在每个子的顶部定义和编程位置变量
这通常是发生的事情。在每个主子的顶部,您定义范围接口变量,然后使用完全限定的引用设置它们。对于具有一两个主要功能的快速项目,这通常已经足够了。
当您开始拥有大量嵌套函数时,这将成为一个问题。您是否在函数内部重新定义headerRow
and ?还是您每次都传递所有这些信息?多么痛苦。小规模可管理。随着事情的发展,完全变成了意大利面怪物和大海捞针(我们都知道他们通常会这样做)。firstDataRow
moveDataRow()
选项2:定义我自己的 Worksheet 对象
我已经竭尽全力定义自己的工作表对象,该对象具有“headerRow”或“firstDataRow”等附加属性,以便可以将这些属性存储在工作表代码中。然后,当我定义一个工作表对象时,我使用dim srcSheet as myWorksheet
而不是dim srcSheet as Worksheet
. 这使我可以通过对象模型找到属性。前任:srcSheet.headerRow
当您处理同一工作表的大量重复时,此解决方案非常棒。如果您有六张纸都在做不同的事情并需要不同的属性,那完全是浪费时间。例如:一张表可能是蒙特卡洛控制,而另一张表正在运行 f 检验。我不想为每个人创建一个新的工作表对象。
选项 3:动态查找所有内容
这可能是最强大的,但令人难以置信的耗时。找到一种基于其内容、格式和相对位置来定义每个单元格位置的方法。通常,您尝试引用的单元格的某些特定内容不会改变。编写一个脚本来找到那个东西会让事情变得更容易。但是,这是一项繁重的工作,并非对每个项目都真正可行。对于大多数项目来说,工作量太大了,这是浪费时间。
选项 4:模块级位置变量
将新模块用于与工作表子集交互的主要功能。然后在该模块的顶部将所有位置的东西定义为私有常量。
这适用于中型项目。但是,当您处理多个模块并在处理数据时跨多个工作表移动数据时,您开始必须多次定义相同的常量。
选项 5:创建“位置”模块
这可能会很好,因为所有位置都将在一个地方。我还没有尝试过,但这就是我在这里问这个问题的原因。每当您创建位置参考时,它都会进入位置模块。每个工作表都有一个定义的前缀,用于标识该特定工作表。这样,在子或函数中,您无需在子中设置工作表范围位置,而是调用srcHeaderRow = dataHeaderRow
以定义数据标题位于第 5 行,而不必在每次需要使用时重新定义行srcHeaderRow
。
还有什么?你尝试过的任何东西都很棒吗?
您还使用了哪些其他方法来保持单元格/范围位置以在 VBA 和工作表之间进行接口?
解决方案
我不知道这些是否符合最佳实践,但这是我的做法。
更改工作表的代码名称
为什么dim srcSheet as myWorksheet
您可以只更改工作表的代码名称?
枚举列和标题行
我为每个 Worksheet 创建一个 Enum 来枚举每一列、[First Column]、[Last Column] 和 [Header Row]。将 Enum 成员括在括号中并在其名称中使用特殊字符将创建隐藏成员。请参阅下面的示例代码。如果我以后决定对列重新排序、添加列或重新定位数据,我所要做的就是更新枚举并且代码不会中断。
枚举可用于 Intellisense
样本数据
我使用Excel 示例数据中的前 10 行作为数据。
演示代码
Public Enum EnumWSDataColumns
dcOrderDate = 3
dcRegion
dcRep
dcItem
dcUnits
dcUnitCost
dcTotal
[_dcFirstColumn] = dcOrderDate
[_dcLastColumn] = dcTotal
dcHeaderRow = 4
End Enum
Sub DemoEnum()
Dim r As Long, c As Long
Dim value As String * 10
With wsData
For r = dcHeaderRow To .Cells(.Rows.count, [_dcFirstColumn]).End(xlUp).Row
For c = [_dcFirstColumn] To [_dcLastColumn]
value = .Cells(r, c)
Debug.Print value; "|";
Next
Dim n As Long
n = ([_dcLastColumn] - [_dcFirstColumn] + 1) * (Len(value) + 1)
Debug.Print
Debug.Print String(n, "-")
Next
End With
End Sub
输出
推荐阅读
- php - 未定义索引:Laravel 中针对少数用户的 HTTP_USER_AGENT
- c# - C# 项目属性的文档:`
严格的 ` - reactjs - 如何在另一个 wordpress 网站中显示反应网站记录的用户详细信息
- oauth-2.0 - 如何申请领英邀请、人员和连接 API
- reactjs - 无法集成 styleguidist 以生成文档
- python - numpy 有一个名为 math 的模块吗?
- reactjs - 如何在反应中使用 Hooks 更新设备宽度的状态
- javascript - 页面上特定元素上的滚动指示器
- spring-cloud-deployer-kubernetes - 使用 containerCommand 属性执行多行命令
- pseudocode - TSP 的大 O 时间复杂度