命名范围的类 – Excel VBA
我正在不断更新和改进一个由Excel创build的财务模型,其中启用了VBAmacros,这个macros被多个人主动使用。 首先,这些模板被用作不同项目的预算,所以有很多创build的时间,而较老的预算被重新访问。
我是模板的“守护者”,而其他用户只是使用该文档。 无论何时我需要向每个人推送更新,都会产生问题,因为他们已经在模板的较早版本中创build了预算,并且在新模板中重新创build预算需要花费过多的时间。
我已经通过命名范围在较小规模的模板上解决了这个问题,然后将这些命名范围应用于旧版本,然后使用命名范围将其复制到新版本模板中相同的命名范围中。 但是,这是通过单独的代码行来复制每个命名的范围。
有没有办法将一组命名范围聚合到一个类中,以便Excel可以循环遍历类中的所有项目并复制数据,而不是我需要编写每行来执行复制?
下面是我正在运行的代码示例:
Workbooks(WB_Active_Name).Sheets("Office Staff Input").Range("Office_Employee_Names").Value = Workbooks(WB_Secondary_Name).Sheets("Office Staff Input").Range("Office_Employee_Names").Value Workbooks(WB_Active_Name).Sheets("Office Staff Input").Range("Office_Employee_Positions").Value = Workbooks(WB_Secondary_Name).Sheets("Office Staff Input").Range("Office_Employee_Positions").Value Workbooks(WB_Active_Name).Sheets("Office Staff Input").Range("Office_Employee_Numbers").Value = Workbooks(WB_Secondary_Name).Sheets("Office Staff Input").Range("Office_Employee_Numbers").Value Workbooks(WB_Active_Name).Sheets("Office Staff Input").Range("Office_Employee_Bonus_Sharing").Value = Workbooks(WB_Secondary_Name).Sheets("Office Staff Input").Range("Office_Employee_Bonus_Sharing").Value
对于每个命名的范围,有十几行类似的代码。 在模板中,范围指的是员工姓名,身份证号码,工作时间等等的列表,他们还跨越工作簿中的多个工作表,每个不同大小的范围。
我想知道当我定义它时,是否有某种类可以放在每个命名范围的前面,这样它们就可以作为一个类一起对待,并可以循环使用。 例如:
Office_Employee_Names
变
GroupClass.Office_Employee_Names
然后代码可以遍历GroupClass
所有GroupClass
我将在您的模板中创build一个新的工作表,列出所有这些命名的范围; 从VBA读取列表并循环访问它们。
如果VBA中存在MVC模式,则命名范围可以表示一个View对象。
我个人有一些MV *模式的经验,其中视图也实现事件(通常委派给控制器对象)。
使用这种方法的好处是,您将以更加模块化的方式开始编程。
我在下面提供一个例子:
简单命名范围“persons”的MV *实现的结构可以具有以下类结构:
- cls_view_persons
- cls_model_person
想象一下, cls_view_persons
代表一个视图对象,那么这意味着你必须从一个基本子实例化,它将简单地为:
dim view_persons as cls_view_persons set cls_view_persons = new cls_view_persons
1.人的观点(例子)
cls_view_persons类将有一个属性来定义类的范围。 例如:
private pRange as new Range
您可以在类构造函数中定义私有的pRange属性。
导致Excel出错的一个原因是,事先并不知道范围的大小,以及错误发生的事实,比如上一次没有正确清理的范围。
这就是为什么重要的是还要定义以下属性:
- _oRange作为Excel.Range
- _snamed_range作为string;
- _lNr_rows一样长;
- _iNr_cols为整数;
- _iOffset_x只要;
- _lOffset_y为整数;
- oCollection作为集合(你也可以使用这个字典)
注意:oCollection是一个由不同的cls_view_persons实例组成的对象;
和方法:
- 初始化:类构造函数:定义一个默认的范围对象,或者如果你愿意的话,你可以在创build时传递一个范围;
- get_named_range:返回一个范围对象;
- set_named_range:设置范围对象属性并在表单对象中创build命名的范围;
- collection_to_array:将集合对象转换为数组;
- clear_range:清除范围;
-
一种使用前三种方法的
render
方法,并将创build的数组中的数据写入一个语句中的范围:set pRange = vPersons
vPersons是一个数组,包含不同的人(见后面)。
-
(从范围读取的“读取”方法也是有用的)。
2人模特(例子)
模型表示应用程序的数据逻辑,并且本身不一定与某个特定视图相关。 在这种情况下,它是,但模型(或模型集合)原则上是独立的)。
人员模型可以是定义以下属性的类:
- 名字
- 姓
- 地址
- 国家
无论是从数据库,从一个Excel工作表(后者是最糟糕的情况,这不幸发生最多)或任何其他来源提取这些模型。
不pipe你做什么,你都需要看到你最终得到一个可以提供给View对象的Collection对象。
一旦完成,View对象应该自己pipe理。 从那一刻起,所有的解释和渲染都被委托给这个对象。
意即:
- validation尺寸;
- 清除以前的结果;
- 在屏幕上渲染范围(即设置新维度,在工作表中创build命名范围,将集合转换为数组,并将数组写入屏幕)。
您会看到这种方法在以下方面有很多好处:
- 保养;
- 更less的错误;
- 模块化(和可转移)/封装的属性/方法;
- dynamic适应性;
- 你可以从任何数据源读取,如果你只写一个中介“翻译”模块。
我经常通过以下方式从名称检索数据
Workbook.Names包含所有的Name对象,每个Name对象的属性
Dim WBook As Workbook Dim WName As Name Set WBook = ActiveWorkbook For Each WName In WBook.Names Debug.Print WName.Name, WName.RefersToLocal Next WName