2014-02-25 34 views
0

我在不断更新和改善内置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 

还有的多行代码类似于这样每个命名范围打。在模板内部,范围是指工作人员姓名,身份证号码,工作时间等列表,并且它们还跨越工作簿中的多个工作表,每个工作簿的大小都不同。

我想知道是否有某种类的,我可以在每个命名范围的前面放置时,我把它定义使他们作为一个阶级一起处理,并可通过环接的。例如:

Office_Employee_Names 

成为

GroupClass.Office_Employee_Names 

然后代码可以通过一切GroupClass

+2

证明你目前如何做。显示一些代码,我们将帮助你改进它。同样,你谈论的东西的视觉示例也不会受到伤害,因为很难想象出某些模板。 – 2014-02-25 15:30:25

+0

你是否想要维护一个所有范围的列表作为你可以循环的东西?如果是这样,你可以做到这一点......创建一个过程,该过程定义了一个包含所有命名范围的字符串数组。然后,你总是可以根据需要添加新元素到数组中,并在你的代码中引用该数组......我不理解你的问题吗? –

+0

使用示例代码查看我对上面原始帖子的编辑。 – Michael

回答

1

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

+0

+1我的最爱,最简单的解决方案 –

+0

确实是一个很好的解决方案。我是否需要引用命名范围所在的工作表名称?出于某种原因,它似乎给我提供了一些问题,尽管我认为Excel可以在工作簿中找到指定的范围。 – Michael

1

循环,如果一个MVC模式将存在于VBA,然后命名范围可以代表查看目的。
我个人有一些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 

可以定义在类的构造函数的私有财产普兰奇。

其中一个导致Excel错误的原因是事实上,您事先并不知道范围的大小以及发生错误的事实,例如上次没有正确清除的范围。
这就是为什么它是重要的还定义了以下属性:

  • _oRange为Excel。范围
  • _sNamed_range as string;
  • _lNr_rows as long;
  • _iNr_cols as integer;
  • _iOffset_x只要;
  • _lOffset_y as integer;
  • oCollection作为收藏(你也可以使用字典这个)

注:oCollection是一个对象,将包括不同cls_view_persons实例;

和方法:

  • 初始化:类构造函数:定义了默认的范围对象,或者如果你愿意的话,你可以通过对创建时间的范围;
  • get_named_range:返回一个范围对象;
  • set_named_range:设置范围对象属性并在工作表对象中创建命名范围;
  • collection_to_array:将集合对象转换为数组;
  • clear_range:清除范围;
  • 使用先前的三种方法和从所创建的阵列中的一个语句将数据写入范围A render方法:

    set pRange = vPersons

凡vPersons是一个数组,含有不同的人(见后面)。

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

    2人模型(实施例)

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

  • 姓氏
  • 地址
  • 国家

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

无论你做什么,你都需要看到你最终得到一个Collection对象,你可以将它提供给View对象。
一旦完成,View对象应该管理它自己的。从那时起,所有的解释和渲染都被委托给这个对象。
这意味着:

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

你会看到,这种方法在以下方面有很多好处:

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

我意识到这看起来很复杂,但当我告诉你它不是时,请相信我。一旦你习惯了使用MVC或MV *工作流程,你将很快习惯这些惯例,并发现与它合作会更愉快。出于简单的原因,您将能够更快速地进行调试(封装对象),更快地编写扩展,更容易地查找和解决错误(而不是意大利式面条编码您的模块,不知道变化的后果),也许最重要的是,开发可重用的代码,同时你知道它会使你的对象和方法稳定。 – Trace

+1

你应该添加这个作为一个问题的规范答案,因为在这里它可能得不到许多意见,但是在你自己构思的一个写得很好的问题上,它可能更有用...... + 1 –

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