2011-08-17 26 views
5

Niektóre funkcje, takie jak Split() powróci tablicę z -1 dla górnej granicy i zera w dolnej granicy, gdy matryca nie ma pozycji, npVB6 tablicę z -1 dla górnej granicy

Dim s() As String 
s = Split("", ",") 
Debug.Print UBound(s) 
Debug.Pring LBound(s) 

W w tym przypadku UBound (s) będzie równa -1, a LBound (s) będzie równe 0. Mam sporo kodu sprawdzającego dla -1 w górnej granicy, aby sprawdzić, czy tablica ma wartości, czy nie. Działa to świetnie.

Problem polega na tym, że chcę teraz zmienić typ danych tablicy z ciągu na długi. Nie mogę utworzyć tablicy długich z górną granicą -1 i dolną granicą 0, a funkcje Split() i Join() działają tylko na tablicach ciągów.

Chciałbym móc zwrócić długą tablicę z górną granicą -1. czy to możliwe?

+2

Mogłem pominąć twój punkt tutaj, ale możesz stworzyć tablicę Long z 'górnymi granicami' -1:' Dim lngArray (-1 To -1) Tak długo' –

+0

@Matt @bugtussle Bugtussle, powinieneś prawdopodobnie wyjaśnić Twoje pytanie, które chcesz ** niższa granica zero **, a także górna granica -1! W przeciwnym razie musisz dobrze znać zachowanie 'Split'. Odpowiem odpowiednio na twoje pytanie – MarkJ

Odpowiedz

4

Nie sądzę, że możesz to zrobić w VB6. Jednakże, jeśli jesteś gotów użyć funkcji Windows API SafeArrayCreateVector można zrobić:

Private Declare Function LongSplitEmulator Lib "OLEAUT32.DLL" Alias "SafeArrayCreateVector" _ 
    (Optional ByVal vt As VbVarType = vbLong, _ 
    Optional ByVal low As Long = 0, _ 
    Optional ByVal count As Long = 0) As Long() 

Dim a() As Long 
a = LongSplitEmulator() 
MsgBox UBound(a) 

Jeśli musisz to zrobić dla innych typów danych można zmienić parametr VT.

Proszę zauważyć, myślę, że początkowo dowiedziałem się o tym z odpowiedzi Vi2 na to discussion.

+0

Bardzo fajny hack! – wqw

+0

Spowoduje to utworzenie tablicy z wartościami 0 i ubound -1, które zachowują się dokładnie tak samo, jak funkcja podziału, gdy 's = Split (" ",", ")'. Dzięki – bugtussle

0

Jednym z problemów z VB6 jest brak możliwości niezawodnego utworzenia lub wykrycia pustej (lub niezainicjowanej) tablicy. Czasami możliwe jest wykrycie niezainicjowanej tablicy poprzez sprawdzenie, czy górna granica jest większa niż dolna granica; nie jest to jednak ani eleganckie, ani udokumentowane. Najlepszym sposobem na poprawne wykonanie tego jest zamknięcie tablicy w wariancie i ustawienie wariantu Pusty na deinicjalizację tablicy. Możesz wtedy użyć czeku, takiego jak If VarType (v) = vbEmpty ...

+0

Uważam, że jest elegancki. Możesz uznać to za zerowy wzorzec obiektu – MarkJ

1

można napisać własną funkcję podziału, aby to zrobić:

Private Sub SplitLongs(ByVal strData As String, ByRef lng() As Long) 
    Dim i As Integer 
    Dim s() As String 
    s = Split(strData, ",") 
    If UBound(s) = -1 Then 
     ReDim lng(-1 To -1) 
    Else 
     ReDim lng(LBound(s) To UBound(s)) 
     For i = LBound(s) To UBound(s) 
      If IsNumeric(s(i)) Then lng(i) = s(i) 
     Next 
    End If 
End Sub 
+1

Szukałem 'redim lng (-1 do -1)'. Dzięki. Myślę, że próbowałem tylko 'ReDim (-1)' i 'ReDim (0 do -1)' i otrzymałem błąd: P – bugtussle

0

Innym sposobem jest silnie wpisana funkcja „Fabryka”:

Private Declare Function SafeArrayRedim Lib "oleaut32.dll" (ByVal ArrayPtr As Long, ByRef DataPtr As tagSAFEARRAYBOUND) As Long 

Private Type tagSAFEARRAYBOUND 
    cElements As Long 
    lLbound As Long 
End Type 

Public Type Feed 
    ID As String 
    Name As String 
    Active As Boolean 
    BasePath As String 
End Type 

Public Sub EmptyFeedArray(ByRef Arr() As Feed) 
Dim Data As tagSAFEARRAYBOUND 
Dim lngErr As Long 

    'Redim to one item 
    ReDim Arr(0 To 0) 
    'Reset the safe array to empty 
    lngErr = SafeArrayRedim(Not Not Arr, Data) 
    'Raise any errors 
    If lngErr <> 0 Then Err.Raise lngErr 
End Sub 

myślę, że to działa również z integralnymi typów.