5

我在使用 split 命令填充数组时遇到了一些问题。

我目前拥有的字符串如下

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"

我有一个数组,我希望它是多维的,并且希望每个 Row# Column# 根据其数量位于数组的正确部分。

例如

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"

现在我了解了如何使用 split 命令填充一维数组

MyArray = Split(MyString, vbNewLine)

这将意味着

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"

但我不知道如何使用拆分命令来填充第二个维度。

这是可能的吗?如果是这样的话?
如果不可能,任何人都可以建议如何实际填充它吗?

4

3 回答 3

5

除了 String 或包含 String 的 Variant 之外,您不能对任何东西使用 Split()。如果要生成二维字符串数组,您将遍历 Split() 返回的数组,并对每个字符串运行 Split()。以下功能应该做你想做的事:

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

例子:

Dim asCells() As String

asCells() = SplitTo2DArray(MyString, vbNewline, "~")
于 2012-05-16T09:30:33.980 回答
4

这是一个更快的 hack,它只是交换 1D 和 2D 数组而没有循环:

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
于 2012-05-16T09:45:58.073 回答
0

这是基于 Variant 类型包含数组的能力的另一种方法。我们有一个“数组数组”,而不是二维数组。

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

这里的好处是“参差不齐的数组”,其中每一行可以有不同数量的列。

于 2012-05-19T18:45:42.257 回答