繁体   English   中英

命名范围的类别-Excel VBA

[英]Class of Named Ranges - Excel VBA

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

我是模板的“管理员”,而其他用户只是使用该文档。 每当我需要向所有人推送更新时,都会造成问题,因为他们已经在模板的较旧版本中创建了预算,而在新模板中重新创建预算将花费大量时间。

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

有没有一种方法可以将一组命名范围聚合到一个类中,以便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

每个命名范围都有十几行与此类似的代码行。 在模板内部,范围是指职员姓名,ID号,工作时间等的列表,它们还跨越工作簿中的多个工作表,每个范围的大小各不相同。

我想知道在定义它时是否可以在每个命名范围的前面放置某种类,以便将它们一起视为一个类并可以循环通过。 例如:

Office_Employee_Names

变成

GroupClass.Office_Employee_Names

然后代码可以遍历GroupClass所有GroupClass

如果VBA中将存在MVC模式,则命名范围可以表示View对象。
我个人对MV *模式有一些经验,在该模式中,视图还实现了事件(通常将事件委托给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 

您可以在类构造函数中定义private pRange属性。

导致Excel出现错误的原因之一是您不预先知道范围的大小,并且发生了错误(例如上次未正确清除的范围)这一事实。
这就是为什么还要定义以下属性很重要的原因:

  • _oRange作为Excel.Range
  • _sNamed_range作为字符串;
  • _lNr_rows;
  • _iNr_cols为整数;
  • _iOffset_x长;
  • _lOffset_y为整数;
  • oCollection作为Collection(您也可以为此使用字典)

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

和方法:

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

    set pRange = vPersons

vPersons是一个数组,其中包含不同的人(请参阅下文)。

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

    2人模型(示例)

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

  • 名字
  • 地址
  • 国家

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

无论您做什么,都需要确保最终得到一个Collection对象,您可以将其提供给View对象。
完成此操作后,View对象应自行管理。 从那时起,所有解释和渲染都委托给该对象。
这意味着:

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

您将看到此方法在以下方面有很多好处:

  • 保养;
  • 错误更少;
  • 模块化(可转让)/封装的属性/方法;
  • 动态适应
  • 如果您仅编写中间“翻译器”模块,则可以从任何数据源读取。

我将在您的模板中创建一个新的工作表,其中列出了所有这些命名范围; 从VBA中读取列表,然后遍历它们。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM