Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.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
在VBA中传递队列对象byval-调用函数对象';不能在被调用函数中更改_Vba_Excel - Fatal编程技术网

在VBA中传递队列对象byval-调用函数对象';不能在被调用函数中更改

在VBA中传递队列对象byval-调用函数对象';不能在被调用函数中更改,vba,excel,Vba,Excel,我试图将队列传递给VBA中的函数,并使该函数的操作不影响调用函数中的队列对象 例如,在下面的代码中,队列以5000大小开始。然后队列被传递到RemoveOneFromQueue,其大小减小到4999。我希望Main_测试中的队列不受RemoveOneFromQueue中操作的影响。我认为在函数参数中使用ByVal可以实现这一点,但似乎没有帮助。如果可能的话,有什么想法吗 我不想每次都重新生成队列,因为真正的版本需要很长时间才能完成 Sub Main_Test() Dim queue As

我试图将队列传递给VBA中的函数,并使该函数的操作不影响调用函数中的队列对象

例如,在下面的代码中,队列以5000大小开始。然后队列被传递到RemoveOneFromQueue,其大小减小到4999。我希望Main_测试中的队列不受RemoveOneFromQueue中操作的影响。我认为在函数参数中使用ByVal可以实现这一点,但似乎没有帮助。如果可能的话,有什么想法吗

我不想每次都重新生成队列,因为真正的版本需要很长时间才能完成

Sub Main_Test()
    Dim queue As Object
    Dim i As Long
    Set queue = GenerateQueue()
    Debug.Print queue.Count

    i = RemoveOneFromQueue(queue)
    Debug.Print queue.Count
End Sub

Function GenerateQueue() As Object
    Dim i As Long
    Dim queue As Object
    Set queue = CreateObject("System.Collections.Queue")
    For i = 1 To 5000
        queue.Enqueue i
    Next i
    Set GenerateQueue = queue
End Function

Function RemoveOneFromQueue(ByVal queue As Object) As Double
    Dim i As Long
    i = queue.Dequeue()
    RemoveOneFromQueue = i
End Function

在VBA中,对象本身不会被传递。 您总是传递对实际对象的引用,因此在此场景中放置ByVal还是ByRef并不重要,因为两个引用都指向同一个对象。调用引用对象上的成员将影响该对象的所有位置

但是,为了修复您的特定场景,您可以实例化第二个队列并将其设置为queue.clone(),因为queue类实现了System.IClonable接口,所以您很幸运。。。试试这个:

Sub Main_Test()
    Dim queue As Object
    Set queue = GenerateQueue()
    Debug.Print queue.Count '5000
    RemoveOneFromQueue queue
    Debug.Print queue.Count '5000
End Sub

Sub GenerateQueue() As Object
    Dim i As Long
    Dim queue As Object
    Set queue = CreateObject("System.Collections.Queue")
    For i = 1 To 5000
        queue.Enqueue i
    Next i
    Set GenerateQueue = queue
End Function

Sub RemoveOneFromQueue(ByVal q As Object)
    Dim q2 As Object
    Set q2 = q.Clone()
    q2.Dequeue
    Debug.Print q2.Count '4999
End Sub
请记住,在RemoveOneFromQueue完成执行后,q2将不再存在

但是,不管您是通过val还是通过ByRef传递引用本身,这仍然很重要,如本例所示:

Sub MainTest()
   Dim queue as Object
   Set queue = GenerateQueue()
   Debug.Print queue.Count '5000
   ChangeByVal queue
   Debug.Print queue.Count '5000
   ChangeByRef queue
   Debug.Print queue.Count '4999
End Sub

Sub ChangeByVal(ByVal q as Object)
    Dim q2 As Object
    Set q2 = q.Clone()
    q2.Dequeue
    Debug.Print q2.Count '4999
    Set q = q2
End Sub


Sub ChangeByRef(ByRef q as Object)
    Dim q2 As Object
    Set q2 = q.Clone()
    q2.Dequeue
    Debug.Print q2.Count '4999
    Set q = q2
End Sub

在VBA中,对象本身不会被传递。 您总是传递对实际对象的引用,因此在此场景中放置ByVal还是ByRef并不重要,因为两个引用都指向同一个对象。调用引用对象上的成员将影响该对象的所有位置

但是,为了修复您的特定场景,您可以实例化第二个队列并将其设置为queue.clone(),因为queue类实现了System.IClonable接口,所以您很幸运。。。试试这个:

Sub Main_Test()
    Dim queue As Object
    Set queue = GenerateQueue()
    Debug.Print queue.Count '5000
    RemoveOneFromQueue queue
    Debug.Print queue.Count '5000
End Sub

Sub GenerateQueue() As Object
    Dim i As Long
    Dim queue As Object
    Set queue = CreateObject("System.Collections.Queue")
    For i = 1 To 5000
        queue.Enqueue i
    Next i
    Set GenerateQueue = queue
End Function

Sub RemoveOneFromQueue(ByVal q As Object)
    Dim q2 As Object
    Set q2 = q.Clone()
    q2.Dequeue
    Debug.Print q2.Count '4999
End Sub
请记住,在RemoveOneFromQueue完成执行后,q2将不再存在

但是,不管您是通过val还是通过ByRef传递引用本身,这仍然很重要,如本例所示:

Sub MainTest()
   Dim queue as Object
   Set queue = GenerateQueue()
   Debug.Print queue.Count '5000
   ChangeByVal queue
   Debug.Print queue.Count '5000
   ChangeByRef queue
   Debug.Print queue.Count '4999
End Sub

Sub ChangeByVal(ByVal q as Object)
    Dim q2 As Object
    Set q2 = q.Clone()
    q2.Dequeue
    Debug.Print q2.Count '4999
    Set q = q2
End Sub


Sub ChangeByRef(ByRef q as Object)
    Dim q2 As Object
    Set q2 = q.Clone()
    q2.Dequeue
    Debug.Print q2.Count '4999
    Set q = q2
End Sub

不幸的是,这是不可能的;(

VBA将COM对象作为引用处理

现在,您必须检查出队列后重新排队更快的方法,或者创建一个副本,或者使用一些本机VBA数组或其他方法代替集合对象,因为它可以通过val传递(实际上是对象的副本)


不幸的是,这是不可能的(

VBA将COM对象作为引用处理

现在,您必须检查出队列后重新排队更快的方法,或者创建一个副本,或者使用一些本机VBA数组或其他方法代替集合对象,因为它可以通过val传递(实际上是对象的副本)


如果您不想从队列中删除该项,那么为什么要使用队列?或者使用Peek而不是Dequeue,但现在还不清楚您真正想在这里做什么…我首先要重命名您的变量,因为队列是类的名称,因此不能用作变量。这是因为您传递了对
对象的引用其中一个类似于C/C++指针。你可以传递一个新指针,但它仍然指向同一个内存块。这与传递一个指定的长、字符串甚至变量不同,因为这些都是独立的分配内存块。你可以只生成两个队列,然后将一个队列传递给
RemoveOneeFromQueue
函数。但我不确定这是否是您想要的,但您到底想要什么也不清楚。如果您不想从队列中删除该项目,那么为什么要使用队列?或者使用Peek而不是Dequeue,但不清楚您在这里真正想要做什么…我首先要重命名您的变量,因为队列是类因此不能用作变量。这是因为您传递了对
对象的引用。我认为这些类似于C/C++指针。您可以传递一个新指针,但它仍然指向同一内存块。这与传递指定的长、字符串甚至变量不同,因为它们是独立的l和独立分配的内存块。您可以只生成两个队列,然后将一个队列传递给
removeonefromqueue
函数。但我不确定这是您想要的,但您到底想要什么也不清楚。太好了!使用clone()更好,不会出现速度损失。太好了!使用clone()更好显示没有速度损失。