2012-05-16 13 views
5

Bölme komutunu kullanarak bir diziyi doldurmakta sorun yaşıyorum.2 boyutlu dizi oluşturmak için Array ve Bölme komutları

Şu anda var dizedir ben çok boyutlu olmasını istediğiniz bir dizi var ve esas dizinin doğru parçası olmak için her Satır # Sütun # istiyoruz

MyString = "Row1 Column1[~]Row1 Column2[~]Row1 Column3" & vbNewLine & _ 
"Row2 Column1[~]Row2 Column2[~]Row2 Column3" & vbNewLine & _ 
"Row3 Column1[~]Row3 Column2[~]Row3 Column3" & vbNewLine & _ 
"Row4 Column1[~]Row4 Column2[~]Row4 Column3" 

altında onun numara. Örneğin

MyArray(1,1) = "Row1 Column1" 
MyArray(2,1) = "Row2 Column1" 
MyArray(3,1) = "Row3 Column1" 
MyArray(4,1) = "Row4 Column1" 

MyArray(1,2) = "Row1 Column2" 
MyArray(2,2) = "Row2 Column2" 
MyArray(3,2) = "Row3 Column2" 
MyArray(4,2) = "Row4 Column2" 

MyArray(1,3) = "Row1 Column3" 
MyArray(2,3) = "Row2 Column3" 
MyArray(3,3) = "Row3 Column3" 
MyArray(4,3) = "Row4 Column3" 

Şimdi bu

MyArray(1) = "Row1 Column1[~]Row1 Column2[~]Row1 Column3" 
MyArray(2) = "Row2 Column1[~]Row2 Column2[~]Row2 Column3" 
MyArray(3) = "Row3 Column1[~]Row3 Column2[~]Row3 Column3" 
MyArray(4) = "Row4 Column1[~]Row4 Column2[~]Row4 Column3" 

Ama bende olmayan anlamına gelecektir bölünmüş komutunu

MyArray = Split(MyString, vbNewLine) 

kullanarak tek boyut diziyi yerleştirmek için nasıl çalıştığını anlamak İkinci boyutu doldurmak için bölünmüş bir komutun nasıl kullanılacağını bilmek.

Bu nasıl olur, eğer nasıl yapılır?
Eğer bu mümkün değilse, bunu gerçekten nasıl dolduracağınızı önerebilir misiniz?

cevap

5

Split() öğesini String dışında bir dizede veya String içeren bir Varyant üzerinde kullanamazsınız. İki boyutlu bir dize dizisi oluşturmak istiyorsanız, Split() ile döndürülen dizi boyunca yinelemeniz ve her dizede Split() komutunu çalıştırmanız gerekir. Aşağıdaki fonksiyonu istediğini yapmalıdır:

Private Function SplitTo2DArray(ByRef the_sValue As String, ByRef the_sRowSep As String, ByRef the_sColSep As String) As String() 

    Dim vasValue     As Variant 
    Dim nUBoundValue    As Long 
    Dim avasCells()     As Variant 
    Dim nRowIndex     As Long 
    Dim nMaxUBoundCells    As Long 
    Dim nUBoundCells    As Long 
    Dim asCells()     As String 
    Dim nColumnIndex    As Long 

    ' Split up the table value by rows, get the number of rows, and dim a new array of Variants. 
    vasValue = Split(the_sValue, the_sRowSep) 
    nUBoundValue = UBound(vasValue) 
    ReDim avasCells(0 To nUBoundValue) 

    ' Iterate through each row, and split it into columns. Find the maximum number of columns. 
    nMaxUBoundCells = 0 
    For nRowIndex = 0 To nUBoundValue 
     avasCells(nRowIndex) = Split(vasValue(nRowIndex), the_sColSep) 
     nUBoundCells = UBound(avasCells(nRowIndex)) 
     If nUBoundCells > nMaxUBoundCells Then 
      nMaxUBoundCells = nUBoundCells 
     End If 
    Next nRowIndex 

    ' Create a 2D string array to contain the data in <avasCells>. 
    ReDim asCells(0 To nUBoundValue, 0 To nMaxUBoundCells) 

    ' Copy all the data from avasCells() to asCells(). 
    For nRowIndex = 0 To nUBoundValue 
     For nColumnIndex = 0 To UBound(avasCells(nRowIndex)) 
      asCells(nRowIndex, nColumnIndex) = avasCells(nRowIndex)(nColumnIndex) 
     Next nColumnIndex 
    Next nRowIndex 

    SplitTo2DArray = asCells() 

End Function 

Örnek:

İşte
Dim asCells() As String 

asCells() = SplitTo2DArray(MyString, vbNewline, "~") 
+0

Durumun böyle olabileceğini düşündüm ve farklı bir yönteme ihtiyacım var. Çok teşekkür ederim, fonksiyonunuz mükemmel çalışıyor. –

+0

Heyecan istiyorsanız ve diğer yolla sütun ve satır dizinine sahip olmanıza gerek yok, wqw'nin cevabını deneyin! –

4

o sadece hayır döngüler ile 1D ve 2D diziler birbiriyle değiştiren bir hızlı kesmek olduğunu:

Option Explicit 

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) 

Private Sub Form_Load() 
    Dim MyString  As String 
    Dim MyFlatArray  As Variant 
    Dim MyArray   As Variant 

    '--- split source string by column&row separator 
    MyString = "Row1 Column1[~]Row1 Column2[~]Row1 Column3" & vbNewLine & _ 
     "Row2 Column1[~]Row2 Column2[~]Row2 Column3" & vbNewLine & _ 
     "Row3 Column1[~]Row3 Column2[~]Row3 Column3" & vbNewLine & _ 
     "Row4 Column1[~]Row4 Column2[~]Row4 Column3" 
    MyFlatArray = Split(Replace(MyString, "[~]", vbCrLf), vbCrLf) 
    '--- convert to 2D array 
    ReDim MyArray(1 To 3, 1 To 4) As String 
    pvSwapArrays MyArray, MyFlatArray 
    '--- access row 2 
    Debug.Print MyArray(1, 2) 
    Debug.Print MyArray(2, 2) 
    Debug.Print MyArray(3, 2) 
End Sub 

Private Sub pvSwapArrays(vDst As Variant, vSrc As Variant) 
    Dim nDstType  As Integer 
    Dim nSrcType  As Integer 
    Dim pSrcArray  As Long 
    Dim pDstArray  As Long 
    Dim lTemp   As Long 

    '--- sanity check types (VARIANT.vt) 
    Call CopyMemory(nDstType, vDst, 2) 
    Call CopyMemory(nSrcType, vSrc, 2) 
    Debug.Assert (nSrcType And &H2000) <> 0 '--- check if VT_ARRAY 
    Debug.Assert nDstType = nSrcType '--- check if dest type matches src (&H2008 = VT_ARRAY | VT_BSTR) 
    '--- get VARIANT.parray 
    Call CopyMemory(pSrcArray, ByVal VarPtr(vSrc) + 8, 4) 
    Call CopyMemory(pDstArray, ByVal VarPtr(vDst) + 8, 4) 
    '--- swap SAFEARRAY.pvData 
    Call CopyMemory(lTemp, ByVal pSrcArray + 12, 4) 
    Call CopyMemory(ByVal pSrcArray + 12, ByVal pDstArray + 12, 4) 
    Call CopyMemory(ByVal pDstArray + 12, lTemp, 4) 
End Sub 
+0

Ha! Güzel hack! Ancak bunu kullanacak olsaydım, yaptığınız şey hakkında daha uzun bir açıklama isterdim. Ayrıca, yolunuzu yaparken, dizi endekslerini (Sütun, Satır) numaralandırmaya zorlanırsınız. –

+0

@MarkBertenshaw: iç dizi gösterimi, indeksleme sırasında önce gelmek için alt sınırları zorlar. Bir 2D dizisinde 'Her 'için kullanırsanız, sipariş öğeleri döngüdür. Her iki dizinin toplam boyutları da eşleşmeli ya da yırtılarak AV'yi yıpratmalıdır. Bütün bu kısıtlamalar, herhangi bir döngüsünün olmaması ve kopya kopyalama olmaması nedeniyle telafi edilir. – wqw

+0

SAFEARRAY'lerin nasıl çalıştığını biliyordum, ama daha önce hiç bir ford kullanmıyordum. Desteklenmeyen bir dilde bile, öğrenecek daha çok şey var. –

0

İşte Varyant türünün bir dizi içerme yeteneğine dayanan başka bir yaklaşım. 2B dizi yerine bir dizi dizi var.

Option Explicit 

Private Function SplitSplit(ByRef Delimited As String) As Variant 
    Dim Rows() As String 
    Dim AryOfArys As Variant 
    Dim I As Long 

    Rows = Split(Delimited, vbNewLine) 
    ReDim AryOfArys(UBound(Rows)) 
    For I = 0 To UBound(Rows) 
     AryOfArys(I) = Split(Rows(I), "[~]") 
    Next 
    SplitSplit = AryOfArys 
End Function 

Private Sub Form_Load() 
    Dim MyString As String 
    Dim MyAry As Variant 

    MyString = "Row1 Column1[~]Row1 Column2[~]Row1 Column3" & vbNewLine _ 
      & "Row2 Column1[~]Row2 Column2[~]Row2 Column3" & vbNewLine _ 
      & "Row3 Column1[~]Row3 Column2[~]Row3 Column3" & vbNewLine _ 
      & "Row4 Column1[~]Row4 Column2[~]Row4 Column3" 

    MyAry = SplitSplit(MyString) 

    AutoRedraw = True 
    DumpAry MyAry 
End Sub 

Private Sub DumpAry(ByRef AryOfArys As Variant) 
    Dim Row As Long, Col As Long 

    For Row = 0 To UBound(AryOfArys) 
     For Col = 0 To UBound(AryOfArys(Row)) 
      Print AryOfArys(Row)(Col), 
     Next 
     Print 
    Next 
End Sub 

Buradaki bonus, her satırın farklı sayıda sütun içerebileceği "düzensiz diziler" dir.