Die Übergabe eines nicht dimensionierten Arrays an die Ubound-Funktion von VB6 führt zu einem Fehler. Ich möchte also überprüfen, ob das Array bereits dimensioniert wurde, bevor ich versuche, seine obere Grenze zu überprüfen. Wie kann ich dies tun?
Antworten
Zu viele Anzeigen?Für jede Variable, die als Array deklariert ist, können Sie leicht überprüfen, ob das Array initialisiert ist, indem Sie die API SafeArrayGetDim aufrufen. Wenn das Array initialisiert ist, ist der Rückgabewert ungleich Null, andernfalls gibt die Funktion Null zurück.
Beachten Sie, dass Sie diese Funktion nicht mit Varianten verwenden können, die Arrays enthalten. Dies führt zu einem Kompilierfehler (Type mismatch).
Public Declare Function SafeArrayGetDim Lib "oleaut32.dll" (psa() As Any) As Long
Public Sub Main()
Dim MyArray() As String
Debug.Print SafeArrayGetDim(MyArray) ' zero
ReDim MyArray(64)
Debug.Print SafeArrayGetDim(MyArray) ' non-zero
Erase MyArray
Debug.Print SafeArrayGetDim(MyArray) ' zero
ReDim MyArray(31, 15, 63)
Debug.Print SafeArrayGetDim(MyArray) ' non-zero
Erase MyArray
Debug.Print SafeArrayGetDim(MyArray) ' zero
ReDim MyArray(127)
Debug.Print SafeArrayGetDim(MyArray) ' non-zero
Dim vArray As Variant
vArray = MyArray
' If you uncomment the next line, the program won't compile or run.
'Debug.Print SafeArrayGetDim(vArray) ' <- Type mismatch
End Sub
Basierend auf alle Informationen, die ich in diesem vorhandenen Beitrag lesen, funktioniert dies am besten für mich beim Umgang mit einem typisierten Array, das als uninitialized beginnt.
Es hält den Testcode konsistent mit der Verwendung von UBOUND und erfordert keine Fehlerbehandlung für den Test.
Es IST abhängig von Zero Based Arrays (was bei den meisten Entwicklungen der Fall ist).
Verwenden Sie nicht die Funktion "Löschen", um das Feld zu löschen, sondern verwenden Sie die unten aufgeführten Alternativen.
Dim data() as string ' creates the untestable holder.
data = Split(vbNullString, ",") ' causes array to return ubound(data) = -1
If Ubound(data)=-1 then ' has no contents
' do something
End If
redim preserve data(Ubound(data)+1) ' works to increase array size regardless of it being empty or not.
data = Split(vbNullString, ",") ' MUST use this to clear the array again.
Der Titel der Frage fragt, wie man feststellt, ob ein Array initialisiert ist, aber nachdem ich die Frage gelesen habe, sieht es so aus, als ob das eigentliche Problem darin besteht, wie man die UBound
eines Arrays, das nicht initialisiert ist.
Hier ist meine Lösung (für das eigentliche Problem, nicht für den Titel):
Function UBound2(Arr) As Integer
On Error Resume Next
UBound2 = UBound(Arr)
If Err.Number = 9 Then UBound2 = -1
On Error GoTo 0
End Function
Diese Funktion funktioniert in den folgenden vier Szenarien, von denen ich die ersten drei gefunden habe, wenn Arr
von einer externen DLL COM erstellt wird und die vierte, wenn die Arr
ist nicht ReDim
-ed (das Thema dieser Frage):
UBound(Arr)
funktioniert, so dass der Aufruf vonUBound2(Arr)
fügt ein wenig Overhead hinzu, schadet aber nicht sehrUBound(Arr)
scheitert in der Funktion, die definiertArr
aber im Inneren gelingt esUBound2()
UBound(Arr)
scheitert sowohl in der Funktion, die dieArr
und inUBound2()
so dass die Fehlerbehandlung die Aufgabe erfüllt- Nach
Dim Arr() As Whatever
, vorReDim Arr(X)
Am einfachsten ist es, dafür zu sorgen, dass das Array im Voraus initialisiert wird, bevor man nach dem Ubound suchen muss. Ich brauchte ein Array, das im (allgemeinen) Bereich des Formularcodes deklariert wurde. d.h..
Dim arySomeArray() As sometype
In der Routine zum Laden des Formulars wird dann das Array redimiert:
Private Sub Form_Load()
ReDim arySomeArray(1) As sometype 'insure that the array is initialized
End Sub
Auf diese Weise kann das Array zu einem späteren Zeitpunkt im Programm neu definiert werden. Wenn Sie herausfinden, wie groß das Array sein muss, können Sie es einfach neu definieren.
ReDim arySomeArray(i) As sometype 'i is the size needed to hold the new data
' Function CountElements return counted elements of an array.
' Returns:
' [ -1]. If the argument is not an array.
' [ 0]. If the argument is a not initialized array.
' [Count of elements]. If the argument is an initialized array.
Private Function CountElements(ByRef vArray As Variant) As Integer
' Check whether the argument is an array.
If (VarType(vArray) And vbArray) <> vbArray Then
' Not an array. CountElements is set to -1.
Let CountElements = -1
Else
On Error Resume Next
' Calculate number of elements in array.
' Scenarios:
' - Array is initialized. CountElements is set to counted elements.
' - Array is NOT initialized. CountElements is never set and keeps its
' initial value of zero (since an error is
' raised).
Let CountElements = (UBound(vArray) - LBound(vArray)) + 1
End If
End Function
' Test of function CountElements.
Dim arrStr() As String
Dim arrV As Variant
Let iCount = CountElements(arrStr) ' arrStr is not initialized, returns 0.
ReDim arrStr(2)
Let iCount = CountElements(arrStr) ' arrStr is initialized, returns 3.
ReDim arrStr(5 To 8)
Let iCount = CountElements(arrStr) ' arrStr is initialized, returns 4.
Let arrV = arrStr
Let iCount = CountElements(arrV) ' arrV contains a boxed arrStr which is initialized, returns 4
Erase arrStr
Let iCount = CountElements(arrStr) ' arrStr size is erased, returns 0.
Let iCount = CountElements(Nothing) ' Nothing is not an array, returns -1.
Let iCount = CountElements(Null) ' Null is not an array, returns -1.
Let iCount = CountElements(5) ' Figure is not an array, returns -1.
Let iCount = CountElements("My imaginary array") ' Text is not an array, returns -1.
Let iCount = CountElements(Array(1, 2, 3, 4, 5)) ' Created array of Integer elements, returns 5.
Let iCount = CountElements(Array("A", "B", "C")) ' Created array of String elements, returns 3.