Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.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 - Fatal编程技术网

Excel 递归VBA函数未正确返回

Excel 递归VBA函数未正确返回,excel,vba,Excel,Vba,使用下面这个简单的测试对递归函数进行测试,以了解函数没有正确返回预期值的原因。这是通话程序 Public Sub TestRecursive() m_count = 0 Debug.Print Recursive End Sub 这是递归函数 Private Function Recursive() As String Recursive = "start" m_count = m_count + 1 If m_count < 5 Then 'Debug

使用下面这个简单的测试对递归函数进行测试,以了解函数没有正确返回预期值的原因。这是通话程序

Public Sub TestRecursive()
   m_count = 0
   Debug.Print Recursive
End Sub
这是递归函数

Private Function Recursive() As String
  Recursive = "start"
  m_count = m_count + 1
  If m_count < 5 Then

    'Debug.Print "counting " & CStr(m_count)
    Recursive
  Else

    'Debug.Print "ended count "
    Recursive = "ended"
    Exit Function
  End If
  'Debug.Print "should never reach here"
End Function
Private Function Recursive()作为字符串
Recursive=“开始”
m_计数=m_计数+1
如果m_计数小于5,则
'Debug.Print“计数”和CStr(m_计数)
递归的
其他的
“Debug.Print”结束计数
Recursive=“结束”
退出功能
如果结束
“Debug.Print”不应到达此处
端函数

不确定发生了什么,但函数递归返回“开始”而不是“结束”。有什么想法或建议吗?

啊,关于递归的非常有趣的问题。下面是调用
Debug.Print Recursive
时发生的情况。这就是第一次通过的时间,指定如下[1]

[1] -> Recursion is "start" -> m_count is 1 -> calls second
[2] -> Recursion is "start" -> m_count is 2 -> calls third
[3] -> Recursion is "start" -> m_count is 3 -> calls fourth
[4] -> Recursion is "start" -> m_count is 4 -> calls fifth
[5] -> Recursion is "start" -> m_count is 5 -> Recursion is  "end" -> returns to 4
[4] -> doesn't do anything with returned value -> returns "start" to 3
[3] -> doesn't do anything with returned value -> returns "start" to 2 and so on
因此,您会看到
start
printed

这里有一个稍加修改的版本,有助于打印
结束

' make global variables that will remember information
Option Explicit
Dim m_count As Integer
Dim m_finalword As String

Public Sub TestRecursive()
   m_count = 0
   Recursive  ' run recursive here 
   Debug.Print m_finalword
End Sub

Private Function Recursive() As String
  Recursive = "start"
  m_count = m_count + 1
  If m_count < 5 Then
    m_finalword = Recursive ' remember Recursive's value in m_finalword
    Recursive               ' run recursive again because our count is below 5
  Else
    m_finalword = "ended"   ' if count went above 5, no need to do recursion
    Exit Function           ' just set m_finalword's value and exit to parent
  End If
End Function
'生成将记住信息的全局变量
选项显式
Dim m_计数为整数
将m_finalword变暗为字符串
公共子TestRecursive()
m_计数=0
Recursive'在这里运行Recursive
调试。打印m_finalword
端接头
私有函数Recursive()作为字符串
Recursive=“开始”
m_计数=m_计数+1
如果m_计数小于5,则
m_finalword=Recursive'记住m_finalword中递归的值
Recursive'再次运行Recursive,因为我们的计数低于5
其他的
m_finalword=“end”'如果计数超过5,则无需执行递归
退出函数“只需设置m_finalword的值并退出到父级
如果结束
端函数

您应该检查VBA中的调试和设置断点。它将在将来的调试中起到极大的帮助。

正如zedfoxus所提到的,您看到结果的原因是您的代码没有使用递归的返回值。然而,除非确实需要,否则使用模块范围变量通常是不好的做法

这个版本避免了这种情况

Option Explicit
Dim m_count As Long

Public Sub TestRecursive()
   m_count = 0
   Debug.Print Recursive
End Sub

Private Function Recursive() As String 
  Recursive = "start"
  m_count = m_count + 1
  If m_count < 5 Then

    'Debug.Print "counting " & CStr(m_count)
    Recursive = Recursive() ' <~~~ here's the change!
  Else

    'Debug.Print "ended count "
    Recursive = "ended"
    Exit Function
  End If
End Function

感谢提供的任一解决方案现在返回正确的值。添加一些debug.print语句后,递归例程在退出函数counting 1 counting 2 counting 3 counting 4 end count at 5不应到达此处5不应到达此处5不应到达此处5不应到达此处5不应到达此处5结束后继续调用自身。知道为什么吗?很高兴知道这些解决方案提供了适当的价值。克里斯的答案比我的好得多,因为他避免使用globals。如果您觉得其中一个答案为您提供了所需的解决方案,请随意标记一个答案为已接受,以便更接近您的问题。
Option Explicit

Public Sub TestRecursive()
   Dim m_count As Long
   m_count = 0
   Debug.Print Recursive(m_count)
End Sub

Private Function Recursive(ByRef m_count As Long) As String
  Recursive = "start"
  m_count = m_count + 1
  If m_count < 5 Then

    'Debug.Print "counting " & CStr(m_count)
    Recursive = Recursive(m_count)
  Else

    'Debug.Print "ended count "
    Recursive = "ended"
    Exit Function
  End If
End Function