命名范围类 - Excel VBA

时间:2014-02-25 15:27:17

标签: excel vba excel-vba

我正在不断更新和改进在Excel中构建的财务模型,其中启用了VBA宏,该宏已被多人主动使用。这些模板主要用作不同项目的预算,因此在重新访问较旧预算时会创建许多模板。

我是模板的“守护者”,而其他用户只是使用该文档。每当我需要向所有人推出更新时,它都会产生问题,因为他们已经在旧版本的模板中创建了预算,并且在新模板中重新创建预算会花费过多的时间。

我通过命名范围,然后将这些命名范围应用于旧版本,然后使用命名范围复制到新版本模板中的相同命名范围,解决了小规模模板上的此问题。但是,这是通过单独的代码行来复制每个命名范围。

有没有办法将一组命名范围聚合到一个类中,以便Excel可以循环遍历类中的所有项目并复制数据而不是我需要编写每行代码来执行复制?< / p>

以下是我目前正在运行的代码示例:

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

中的所有内容

3 个答案:

答案 0 :(得分:2)

如果VBA中存在MVC模式,则命名范围可以表示View对象。
我个人对MV *模式有一些经验,其中Views也实现事件(通常委托给Controller对象)。

使用这种方法的好处是,您将以更加模块化的方式开始编程。

我在下面提供了一个例子:

简单命名范围“人员”的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 as Excel.Range
  • _sNamed_range为字符串;
  • _lNr_rows一样长;
  • _iNr_cols为整数;
  • _iOffset_x一样长;
  • _lOffset_y为整数;
  • oCollection as Collection(你也可以使用字典)

注意:oCollection是一个由不同cls_view_persons实例组成的对象;

和方法:

  • 初始化:类构造函数:定义默认范围对象,或者如果您希望这样做,可以在创建时传递范围;
  • get_named_range:返回一个范围对象;
  • set_named_range:设置范围对象属性并在工作表对象中创建命名范围;
  • collection_to_array:将集合对象转换为数组;
  • clear_range:清除范围;
  • 使用前三种方法的render方法,并将创建的数组中的数据写入单个语句中的范围:

    set pRange = vPersons

其中vPersons是一个数组,包含不同的人(见后文)。

  • (从该范围读取的“读取”方法也是有用的)。

    2人模特(示例)

模型表示应用程序的数据逻辑,并且本身不一定与某个特定视图相关。在这种情况下,它是,但模型(或模型集合)原则上是独立的 人物模型可以是定义以下属性的类:

  • 姓名
  • 姓氏
  • 地址
  • country

这些模型是从数据库,Excel工作表(后者是最糟糕的情况,不幸发生的最多)或任何其他来源获取的。

无论你做什么,你都需要看到最终得到一个可以提供给View对象的Collection对象。
完成此操作后,View对象应该自行管理。从那一刻开始,所有的解释和渲染都被委托给这个对象 这意味着:

  • 验证尺寸;
  • 清除以前的结果;
  • 在屏幕上渲染范围(即设置新尺寸,在工作表中创建命名范围,将集合转换为数组,并将数组写入屏幕)。

你会发现这种方法在以下方面有很多好处:

  • 维护;
  • 减少错误;
  • 模块化(和可转移)/封装的属性/方法;
  • 动态适应性;
  • 如果您只编写中间“翻译”模块,则可以从任何数据源读取。

答案 1 :(得分:1)

我会在你的模板中创建一个新工作表,列出所有这些命名范围;从VBA读取列表并循环遍历它们。

答案 2 :(得分:0)

我经常通过以下方式从姓名中检索数据:

Workbook.Names包含所有名称对象,每个名称对象包含其属性

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