VBA何时更改变量类型而不被要求?

时间:2016-04-11 22:36:23

标签: excel vba excel-vba

我在OS X 10.7.5下的Excel 2011 for Mac中遇到运行时错误。以下是代码摘要:

Dim h, n, k as Integer
Dim report as Workbook
Dim r1 as Worksheet
Dim t, newline as String
Dim line() as String

newline = vbCr
'
' (code to get user input from a text box, to select a worksheet by number)
'
ReDim line(report.Sheets.Count + 10)
MsgBox "Array line has " & UBound(line) & " elements."   '----> 21 elements
line = split(t, newline)
h = UBound(line)
MsgBox "Array line has " & h & " elements."              '----> 16 elements
n = 0
MsgBox TypeName(n)              '----> Integer
For k = h To 1 Step -1
    If IsNumeric(line(k)) Then
        n = line(k)
        Exit For
    End If
Next k
If n > 0 Then
    MsgBox n                    '----> 7
    MsgBox TypeName(n)          '----> String
    Set r1 = report.Sheets(n)   '----> Runtime error "Subscript out of bounds"

因此n被声明为整数,但现在VBA认为它是一个字符串并查找名为“7”的工作表。这是一个平台错误,还是有一些我还没有学到的东西?

令我惊讶的是,将数据放入动态数组会减少其维度,但也许这是正常的,或者可能是动态数组Ubound返回最后使用的元素而不是维度,尽管我还没有看到记录。

1 个答案:

答案 0 :(得分:3)

The first part of your question is answered by @ScottCraner in the comments - the correct syntax for declaring multiple strongly typed variables on one line is:

Dim h As Integer, n As Integer, k As Integer
'...
Dim t As String, newline As String

So, I'll address the second part of your question specific to UBound - unless you've declared Option Base 1 at the top of the module, your arrays start at element 0 by default, not element 1. However, the Split function always returns a 0 based array (unless you split a vbNullString, in which case you get a LBound of -1):

Private Sub ArrayBounds()
    Dim foo() As String

    'Always returns 3, regardless of Option Base:
    foo = Split("zero,one,two,three", ",")
    MsgBox UBound(foo)

    ReDim foo(4)
    'Option Base 1 returns 1,4
    'Option Base 0 (default) returns 0,3
    MsgBox LBound(foo) & "," & UBound(foo)
End Sub

That means this line is extremely misleading...

h = UBound(line)
MsgBox "Array line has " & h & " elements."

...because the Array line actually has h + 1 elements, which means that your loop here...

For k = h To 1 Step -1
    If IsNumeric(line(k)) Then
        n = line(k)
        Exit For
    End If
Next k

...is actually skipping element 0. You don't really even need the h variable at all - you can just make your loop parameter this...

For k = UBound(line) To LBound(line) Step -1
    If IsNumeric(line(k)) Then
        n = line(k)
        Exit For
    End If
Next k

...and not have to worry what the base of the array is.

BTW, not asked, but storing vbCr as a variable here...

newline = vbCr

...isn't necessary at all, and opens the door for all kinds of other problems if you intend that a "newline" is always vbCr. Just use the pre-defined constant vbCr directly.