2012-05-16 32 views
5

Tôi gặp sự cố khi điền một mảng bằng lệnh chia tách.Lệnh Mảng và Tách để tạo mảng 2 chiều

Chuỗi Tôi hiện đang có là dưới

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" 

Tôi có một mảng mà tôi muốn trở thành đa chiều và muốn mỗi Row # Cột # để được ở phần đúng của mảng dựa trên nó con số.

Ví dụ

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" 

Bây giờ tôi hiểu làm thế nào để cư một mảng không gian đơn lẻ sử dụng sự chia rẽ lệnh

MyArray = Split(MyString, vbNewLine) 

Điều này có nghĩa rằng

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" 

Nhưng tôi không biết cách sử dụng lệnh tách để điền thứ nguyên thứ hai.

Điều này có thể và nếu đó là cách thực hiện?
Nếu không thể, bất kỳ ai cũng có thể đề xuất cách thực sự phổ biến điều này?

Trả lời

5

Bạn không thể sử dụng Split() trên bất kỳ thứ gì khác ngoài Chuỗi, hoặc Biến thể chứa chuỗi. Nếu bạn muốn tạo một mảng chuỗi hai chiều, bạn sẽ lặp qua mảng được trả về bởi Split() và chạy Split() trên mỗi chuỗi. Các chức năng sau đây nên làm những gì bạn muốn:

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 

Ví dụ:

Dim asCells() As String 

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

Tôi nghĩ rằng có thể là trường hợp, và tôi sẽ cần một phương pháp khác. Cảm ơn bạn rất nhiều, chức năng của bạn hoạt động hoàn hảo. –

+0

Nếu bạn muốn sự phấn khích, và không nhớ có chỉ số cột và hàng theo cách khác, hãy thử câu trả lời của wqw! –

4

Dưới đây là một hack nhanh hơn mà chỉ giao dịch hoán đổi 1D và 2D mảng không có vòng:

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! Nice hack! Tuy nhiên, nếu tôi sử dụng nó, tôi sẽ muốn có một lời giải thích dài hơn về những gì bạn đang làm. Ngoài ra, làm theo cách của bạn, bạn buộc phải đánh số các chỉ mục mảng (Cột, Hàng). –

+0

@MarkBertenshaw: biểu diễn mảng bên trong buộc các giới hạn dưới đi trước khi lập chỉ mục. Nếu bạn sử dụng 'For Each' trên một mảng 2D thì các phần tử thứ tự sẽ được lặp lại. Cả hai mảng tổng kích thước phải phù hợp với quá hoặc rủi ro AV trên tear-down. Tất cả những ràng buộc này được bù đắp bằng cách thiếu các vòng lặp và không sao chép chuỗi. – wqw

+0

Tôi biết về cách SAFEARRAY hoạt động, nhưng tôi chưa bao giờ nghĩ đến việc sử dụng For..Each..Tiếp theo với mảng không phải 1D! Ngay cả trong một ngôn ngữ không được hỗ trợ, vẫn còn nhiều điều cần học. –

0

Đây là một cách tiếp cận khác dựa trên khả năng của loại biến thể chứa một mảng. Thay vì mảng 2D, chúng ta có một mảng mảng.

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 

Phần thưởng ở đây là "mảng rách" nơi mỗi hàng có thể có số cột khác nhau.

Các vấn đề liên quan