Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.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集合不断重复上一个对象_Vba_Excel - Fatal编程技术网

Excel VBA集合不断重复上一个对象

Excel VBA集合不断重复上一个对象,vba,excel,Vba,Excel,我在尝试填充对象集合时遇到了一个奇怪的问题。当我为PromptsRange.Rows执行for-each循环时,一切都很完美。您可以单步通过NewPrompt区域,观察每一行的经过,并最终添加到末尾的PromptsCollection。我的问题是在这一点之后。如果尝试在PromptsCollection上执行for each循环,则每个对象(36)都是完全相同的,并且是可查找表中的最后一个值。我被难住了。也许其中一位学者可以帮我 这是我的手表 以下代码位于userform模块内。 选项显式 P

我在尝试填充对象集合时遇到了一个奇怪的问题。当我为
PromptsRange.Rows
执行for-each循环时,一切都很完美。您可以单步通过
NewPrompt
区域,观察每一行的经过,并最终添加到末尾的
PromptsCollection
。我的问题是在这一点之后。如果尝试在
PromptsCollection
上执行for each循环,则每个对象(36)都是完全相同的,并且是可查找表中的最后一个值。我被难住了。也许其中一位学者可以帮我

这是我的手表

以下代码位于userform模块内。 选项显式

Private pPromptsCollection As New Collection
Private pProductPromptMapping As New clsOrderPromptRow
Private pOrderPrompts As New clsOrderPromptRow
Private pTarget As Range
Private pSKU As String

Public Property Get PromptsCollection() As Collection
    Set PromptsCollection = pPromptsCollection
End Property

Public Property Let PromptsCollection(Value As Collection)
    Set pPromptsCollection = Value
End Property

Private Sub SetPromptControls()
Dim PromptsRange As Range
Dim PromptRow As Range

Set PromptsRange = Range("LookUpTablePrompts")

For Each PromptRow In PromptsRange.Rows
    Dim NewPrompt As New clsPrompt
    NewPrompt.Name = PromptRow.Cells(1, 1)
    NewPrompt.ControlType = PromptRow.Cells(1, 2)
    NewPrompt.ComboboxValues = PromptRow.Cells(1, 3)
    NewPrompt.HelpText = PromptRow.Cells(1, 4)
    NewPrompt.TabIndex = PromptRow.Cells(1, 5)
    NewPrompt.ColumnIndex = PromptRow.Cells(1, 6)
    NewPrompt.TableIndex = PromptRow.Cells(1, 7)
    NewPrompt.ControlName = PromptRow.Cells(1, 8)

    PromptsCollection.Add NewPrompt, CStr(NewPrompt.Name)
Next
PromptsCollection.Count
End Sub
这就是我的问题所在。这将产生36个相同的对象

Dim Prompt As New clsPrompt

For Each Prompt In PromptsCollection
    MsgBox (Prompt.Name)

Next
我甚至把它推到了手表窗口,以确认所有的物体都是相同的。它总是以桌子底部抽屉前面最后一行的高度为准


希望这足够清楚。提前感谢。

用作新对象时,VBA将在第一次使用对象时创建新实例。您应该避免将
用作新的
,而是使用此模式:

Dim NewPrompt As clsPrompt

For Each PromptRow In PromptsRange.Rows
    Set NewPrompt = New clsPrompt

用作新对象时
,VBA将在第一次使用对象时创建该对象的新实例。您应该避免将
用作新的
,而是使用此模式:

Dim NewPrompt As clsPrompt

For Each PromptRow In PromptsRange.Rows
    Set NewPrompt = New clsPrompt

通过简单的图片,我想解释为什么声明
为New
不适用于集合。嗯


对于简单的图像,我想解释为什么声明为新的
不适用于集合。嗯


问题在于,同一个对象实例被多次添加到集合中。 每个循环基本上更新同一对象的值,从而更新集合中已经存在的每个元素,因为它们都引用同一对象。 最后,集合中的所有元素都将具有来自最后一行数据的值

如前所述,在每个循环的开始处显式地创建一个新对象

For Each PromptRow In PromptsRange.Rows
    Set NewPrompt = New clsPrompt
或在添加对象后销毁该对象:

....
        set NewPrompt = Nothing
    Next 
两者都将确保为数据的每一行创建一个新对象

对于调试,请将以下行添加到类:

Private Sub Class_Initialize()
    Debug.Print "Init"
End Sub

Private Sub Class_Terminate()
    Debug.Print "Term" & Me.Name
End Sub

这将让您在调试窗口中看到创建/终止的对象实例。

问题在于,同一个对象实例被多次添加到集合中。 每个循环基本上更新同一对象的值,从而更新集合中已经存在的每个元素,因为它们都引用同一对象。 最后,集合中的所有元素都将具有来自最后一行数据的值

如前所述,在每个循环的开始处显式地创建一个新对象

For Each PromptRow In PromptsRange.Rows
    Set NewPrompt = New clsPrompt
或在添加对象后销毁该对象:

....
        set NewPrompt = Nothing
    Next 
两者都将确保为数据的每一行创建一个新对象

对于调试,请将以下行添加到类:

Private Sub Class_Initialize()
    Debug.Print "Init"
End Sub

Private Sub Class_Terminate()
    Debug.Print "Term" & Me.Name
End Sub

这将让您在调试窗口中看到创建/终止对象的实例。

“作为新对象”不是真正的问题。真正的问题是循环的每个迭代都在写入同一个对象实例。每个迭代都需要创建一个新的对象实例,正如您的示例代码所做的那样。您仍然可以将变量声明为“New”,并在每个循环迭代开始时创建一个新实例。但最好做一个或另一个,因此在这种情况下,您的示例代码将是我首选的解决方案。@Joeburne说得很好。@Joeburne我今天看到您的评论,您能否解释一下如何做到这一点:
您仍然可以将变量声明为“New”,并在每次循环迭代开始时创建一个新实例。
?我认为这正是用户在这里所做的:
对于PromptsRange.Rows.NewPrompt中的每个PromptRow作为New clsPrompt。。。下一步
但它不起作用,因为我假设“as New”确实是这里的真正问题。@DanielDušek问题在于,将循环中的对象变量“as New”暗显并不像您所期望的那样为每个循环创建一个新对象-它创建一个实例,所有循环迭代都写入同一个对象实例。您需要显式地将变量设置为循环内的新实例,代码才能工作。只要在每次循环迭代中将变量设置为一个新实例,它在循环外是否变暗为“新”并不重要。@Joeburne好的,现在我明白你的意思了,说得好!但是,将变量声明为New,然后显式地将其设置为New instance对我来说没有多大意义,因为As New允许隐式创建对象,所以您不必使用set语句来分配对象引用。但是,这也将有助于解决问题。“新”并不是真正的问题。真正的问题是循环的每个迭代都在写入同一个对象实例。每个迭代都需要创建一个新的对象实例,正如您的示例代码所做的那样。您仍然可以将变量声明为“New”,并在每个循环迭代开始时创建一个新实例。但最好做一个或另一个,因此在这种情况下,您的示例代码将是我首选的解决方案。@Joeburne说得很好。@Joeburne我今天看到您的评论,您能否解释一下如何做到这一点:
您仍然可以将变量声明为“New”,并在每次循环迭代开始时创建一个新实例。
?我认为这正是用户在这里所做的:
对于PromptsRange.Rows.NewPrompt中的每个PromptRow作为New clsPrompt。。。下一步
但它不起作用,因为我假设“as New”确实是这里的真正问题。@DanielDušek问题在于,将循环中的对象变量“as New”暗显并不像您所期望的那样为每个循环创建一个新对象-它创建一个实例,所有循环迭代都写入同一个对象实例。您需要显式地将变量设置为新实例