Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 如何在VBA中创建适当的集合?_Excel_Vba_Collections - Fatal编程技术网

Excel 如何在VBA中创建适当的集合?

Excel 如何在VBA中创建适当的集合?,excel,vba,collections,Excel,Vba,Collections,我试图将一个大的三维数组转换成一系列的类模块。我将下一个类存储为上一个类中的数组。它就像品牌->产品->很多 我已成功创建了此交互,并可以通过以下名称访问它们: 子测试() 把我的品牌当作品牌 设置MyBrand=新品牌 MyBrand.Name=“公司1” MyBrand.AddProduct“鞋” MyBrand.产品(“鞋”).AddLot“240502” MsgBox MyBrand.Products(“鞋”).Lots(0)”正确显示“240502” 端接头 但后来我想创建一个对象组

我试图将一个大的三维数组转换成一系列的类模块。我将下一个类存储为上一个类中的数组。它就像品牌->产品->很多

我已成功创建了此交互,并可以通过以下名称访问它们:

子测试()
把我的品牌当作品牌
设置MyBrand=新品牌
MyBrand.Name=“公司1”
MyBrand.AddProduct“鞋”
MyBrand.产品(“鞋”).AddLot“240502”
MsgBox MyBrand.Products(“鞋”).Lots(0)”正确显示“240502”
端接头
但后来我想创建一个对象组,它可以保存多个
品牌
对象,并像
品牌(“公司1”)
一样访问它们

如果我在类模块中使用数组,最终会得到
Brands.Brand(“Company1”)
。 如果我使用的是
集合
,我必须使用像
品牌(1)
这样的索引


有没有办法创建一个合适的对象组,这样我就可以模仿组的语法,比如Application.workbook和按名称引用成员?

您可以使用
脚本。字典
名称作为键:

子测试()
把我的品牌当作品牌
以模糊品牌为对象
Set Brands=CreateObject(“scripting.dictionary”)
设置MyBrand=新品牌
MyBrand.Name=“公司1”
MyBrand.AddProduct“鞋”
MyBrand.产品(“鞋”).AddLot“240502”
品牌。添加我的品牌。名称,我的品牌
MsgBox品牌(“公司1”)。产品(“鞋”)。批次(0)
端接头

自定义集合背后的许多魔力取决于无法在VBE中编辑的隐藏属性;您需要导出(并在提示时从项目中删除)类模块,在Notepad/Notepad++中编辑其magic member属性,保存更改,然后将模块重新导入到项目中

这显然是乏味和容易出错的,但有一个更好的方法

为了支持这一点:

Set shoesProduct=MyBrand.Products(“鞋”)
您可以将
产品
定义为一个
字典
,并称之为一天,但随后将封装作为一个概念。。。好吧,在这里进行测试(无论内部集合是
字典
集合
、还是.NET
ArrayList
,通常都应该是代码其余部分不需要关心的实现细节)

我怀疑
品牌
类的责任太多,“是”产品集合;最佳做法是将
品牌产品
属性定义如下:

公共属性获取产品()作为产品
因此,您需要一个
Products
类(非常类似于
Workbook.Worksheets
Workbook.Sheets
属性都返回一个
Sheets
collection对象),它封装了一个私有的模块级
VBA.collection
字段(可能已设置密钥,但无法访问或迭代集合的密钥)

Products
自定义集合类需要一个
Item
默认属性(名称
Item
是一个约定);实现只需从私有封装的
集合中提取该项即可:

”@DefaultMember
公共属性获取项(ByVal索引作为变量)作为产品
Set Item=privateCollection.Item(索引)
端属性
如果您正在使用,此
@DefaultMember
注释/注释将触发有关注释和相应隐藏属性“不同步”的检查结果;右键单击该检查结果并选择“调整属性值”让Rubberduck为您生成隐藏代码,并处理恼人的导出/删除-编辑-重新导入循环

否则,您将需要手动编辑隐藏的
VB\u UserMemId
成员属性,该属性使其成为类的默认成员:

Public属性获取项(ByVal索引作为变量)作为产品
属性Item.VB\u UserMemId=0
Set Item=privateCollection.Item(索引)
端属性
这样,
MyBrand.Products(“Shoes”)
就等同于
MyBrand.Products.Item(“Shoes”)

也许您也想迭代集合中的所有产品

MyBrand.Products中每个产品的

调试。打印产品。名称
下一个
为此,您需要一个特殊的“enumerator”成员,用于转发封装集合中的枚举数:

”@枚举器
公共属性获取NewEnum()作为IUnknown
Set NewEnum=privateCollection.[u NewEnum]
端属性
同样,Rubberduck注释大大简化了这一过程,但Rubberduck所做的一切,如果您愿意,也可以手动进行:

Public属性获取NewEnum()作为IUnknown
属性NewEnum.VB_UserMemId=-4
Set NewEnum=privateCollection.[u NewEnum]
端接头
现在,
对于每个
迭代都适用于您的自定义对象集合

如果
批次
不仅仅是
字符串
值(即实际的对象类型),那么
产品
类也可以使用
批次
自定义集合-但是因为
批次
实际上只是
字符串
值(或者是吗?),则
产品
可以简单地封装一个
字典
,并具有一个
Lots
属性,该属性公开
数组:

公共属性Get Lots()作为变量
Lots=私人物品目录。物品
端属性
注意,这比使用
集合
更简单,因为对于集合,您需要迭代它并将每个项复制到一个数组中,以便返回项而不公开集合本身(将
Lots()暴露为集合
会使
AddLot
成员完全冗余)

至于
品牌
收集