函数调用另一个函数但被“卡住”

时间:2014-01-04 05:38:47

标签: excel vba excel-vba excel-2010 user-defined-functions

我是偶尔的VBA程序员,为了好玩(不是我的工作)。

我在MS Excel 2010中有一系列VBA模块。无法弄清楚我做错了什么。这个例程工作,然后我改变了一些东西,它停止了工作。我做的一件事是将代码从单个函数拆分为两个模块中的两个函数。在我把它分成两部分之后,我认为它已经工作了一段时间,但是现在我不记得这是否属实,因为我已经尝试了很多东西让它再次起作用。幸运的是,我将旧版本的所有代码保存在一个函数中,它仍然有效。它会向电子表格返回一个大数组。

从根本上说,我有一个调用函数的工作表。该函数调用另一个函数。使用Debug - Toggle Breakpoints结合一些MsgBox调用,我发现第一个函数运行到它调用第二个函数的点。然后第二个函数向下运行到“结束函数”命令。此时,工作表顶部的名称闪烁了几次......而且没有。在调试时,程序似乎没有返回第一个函数。应该在第一个函数中填充的数组用#Value填充。

我读了几个VBA可能已损坏的地方,因此关闭所有内容并重新启动可以修复它。它没有。然后我读到如果你将所有内容复制/粘贴到新工作表中,使用新模块(是的,很多复制/粘贴),可以清理它。它没有。

我还读到了一个问题,当维度是函数的输入变量时,维度数组有问题。所以我初始化了用于设置数组维度的变量,即使它们是函数的输入变量。也许那是个问题?

代码很长,所以我只包含对第二个函数的调用,第二个函数中变量的声明以及其他一些东西。也许我在传递变量时搞砸了一些语法?

第一个功能:

Option Explicit 'forces all variables to be explicitly declared

Function InputOutputDVL(InData As Variant)
'---------------------------------------------------------------------------------------------

Dim g, p, ng, np, ns, ID, count As Integer
Dim ngmax, npmax, nsmax, namax, nxmax, nymax As Integer
Dim row As Integer
Dim panelmax As Integer
Dim TLstyle As Integer
Dim Group(), Part(), Section(), Airfoil() As Variant
Dim ABP(), TV() As Double

ngmax = 20
npmax = 100
nsmax = 1000
namax = 10

ReDim Group(1 To ngmax, 1 To 4)
ReDim Part(1 To npmax, 1 To 6)
ReDim Section(1 To nsmax, 1 To 17)
ReDim Airfoil(0 To 100, 0 To 2 * namax + 1)

'missing code here

MsgBox ng & " " & np 'This msgbox works correctly and give the right value for np

ABP = Section2VL(nxmax, nymax, ns, panelmax, Group, Part, Section, Airfoil)

MsgBox "Completed Section2VL"  'The code never gets to this msgbox

InputOutputDVL = ABP 'I've tried setting this to = 1234 assuming there was a problem with 
                     'ABP, but the cells on the spreadsheet are still #Value

End Function

第二个功能:

Option Explicit 'forces all variables to be explicitly declared

Function Section2VL(nxmax, nymax, ns, panelmax, Group, Part, Section, Airfoil)

Dim i, j, k, l, c1, c2 As Integer
Dim g, p, s, ng, np, chord, span, panel, ID, count As Integer
Dim NX, NY As Integer
Dim station, panelID, panelIDref As Integer
Dim pi, Xstyle, Ystyle As Double
Dim angle, dist As Double
Dim sx(), sy() As Double
Dim Scoord(), ABP() As Double

ns = 6
nxmax = 12
nymax = 12
panelmax = 300


ReDim sx(0 To nxmax), sy(0 To nymax)
ReDim Scoord(1 To ns, 0 To nxmax, 1 To 3), ABP(1 To panelmax, 1 To 32)

MsgBox ABP(panelmax, 5) 'This call works, and provides the proper value in the msgbox

'return ABP vector
Section2VL = ABP 
    'I've also tried just returning an integer thinking there was something wrong with the
    'ABP array, like 987, but that doesn't work either 

End Function  'This is where it stops when debugging.  Doesn't return to first function

提前致谢。我已经吹了两个漫长的夜晚,无法弄明白。

2 个答案:

答案 0 :(得分:2)

您发出的问题是InputOutputDVL.ABPSection2VL.ABPSection2VL本身之间无法比较的类型

尝试声明所有这些() As Double

InputOutputDVL

Dim ABP() As Double

Section2VL

Dim ABP() As Double

Function Section2VL(...) As Double()

关于类型声明的注释

当你声明这样的变量时

Dim i, j, k, l, c1, c2 As Integer

除了最后一个之外的所有内容都被声明为Variant

您需要明确指定每个变量类型。

此外,除非您有特定原因,否则请勿使用Integer。请改用Long

答案 1 :(得分:1)

谢谢克里斯!你肯定让我朝着正确的方向前进。我还使用了这两个网站:

http://www.cpearson.com/excel/passingandreturningarrays.htm

http://www.cpearson.com/excel/vbaarrays.htm

不完整/不兼容的变量声明是我的问题的根源。

首先,我忘记了VBA在EACH变量之后需要“as Integer”或“as Double”,而不仅仅是在行尾。很多变量都是VARIANTS而不是整数,双打等等。再次感谢Chris!

其次,更具体地说,我只需要做出上面提到的Chris之一的更改,那就是在第一个调用函数中正确地声明ABP()为Double。 ABP()在第二个函数中已经正确地调用了Double,并且我没有将Function Section2VL声明为Double()。使用原始代码:

Dim ABP(), TV() as Double

这表明ABP是VARIANT ARRAY。后来调用ABP = Section2VL()然后尝试将VARIANT填充到VARIANT ARRAY中,这就是问题所在。我仍然感到失望的是编译器没有以某种方式说它有不兼容的数据类型或其他一些错误。这也解释了问题的来源。该代码以前在两个模块中作为两个函数工作。当我进行其他一些更改时,我注意到我没有将ABP声明为数组,所以我添加了“()”。我做了其他更改,它停止了工作。我专注于其他变化,而不是添加()标记的看似微小的“修正”。真正发生的事情是,在原始代码中,错误的组合导致了正确运行的代码!想象一下!

因此代码使用ABP作为变量,或ABP()作为双数组,但不使用ABP()作为变量数组。

当然,这里正确答案是克里斯建议的,而且正确而明确地声明了所有变量。一个有趣的说明是VARIANT(不是VARIANT ARRAY)基本上可以“接受”分配任何传入值,包括双重阵列。

所以在我的最终代码中,我将两个函数都保留为VARIANT,但我现在已经将它们特别声明为VARIANT以使其清晰。在第二个函数中,ABP被正确地声明为动态DOUBLE ARRAY,然后给出适当的尺寸来分配内存空间。在第一个函数中,ABP可以是VARIANT或DOUBLE ARRAY,也可以使用,但由于我总是希望它是一个双阵列,我已经指定了它。

Option Explicit 'forces all variables to be explicitly declared

Function InputOutputDVL(InData As Variant) as Variant
'---------------------------------------------------------------------------------------------

Dim ABP() as Double, TV() As Double 'This ABP was a variant array - which was incompatible

'code removed here

ABP = Section2VL(nxmax, nymax, ns, panelmax, Group, Part, Section, Airfoil)

InputOutputDVL = ABP 

End Function

第二个叫做函数:

Option Explicit 'forces all variables to be explicitly declared

Function Section2VL(nxmax as integer, nymax as integer... ) as Variant

Dim Scoord(), ABP() As Double 'This was already correctly declaring ABP as Double Array, but
                              'now I realize Scoord was incorrectly a Variant Array, but it
                              'wasn't actually causing a problem with my code.
                              'I fixed this in my own code, but left here as example of what
                              'not to do!

ReDim ABP(1 To panelmax, 1 To 32)

'Code removed here

'return ABP vector
Section2VL = ABP 

End Function