使用VBA在列和行上拆分数据字符串

时间:2014-08-05 09:56:56

标签: excel vba split simplify

我正在努力加快当前正在运行的自动化工作簿。

PHP将类似于下面的字符串发送到VBA:

1[|:#:|]text-one[|:#:|]code-one[|:#:|]qty-one[{:#:}]
2[|:#:|]text-two[|:#:|]code-two[|:#:|]qty-two[{:#:}]

,其中

  • [|:#|]代表“新专栏”
  • [{:#:}]代表“新行”

当VBA解析它时,这是输出:

我目前使用以下VBA代码将其解析为工作簿:

myArray = Split(myReply, "[{:#:}]")
myRow = 1
For Each element In myArray
    myRow = myRow + 1
    subArray = Split(element, "[|:#:|]")
    myCol = 2
    For Each subelement In subArray
        myCol = myCol + 1
        Cells(myRow, myCol).Value = subelement
    Next subelement
Next element

我即将开始优化此工作簿中的代码,我知道我可以执行类似(伪代码)的操作:

for each element....
    Range("C2:F2").Value = Split(element, "[|:#:|]") 'Example row number would be incremental

但是有没有办法让我可以分成整个范围?

例如,如果我知道返回的数据中有29个“行”,我希望能够使用split将数据放入所有行。

我认为语法类似于下面的内容,但这似乎不起作用:

Range("C2:F29").Value = Split(Split(element, "[|:#:|]"),"[{:#:}]")

2 个答案:

答案 0 :(得分:2)

最佳方法是在本机VBA代码中执行所有操作,并且不要与Excel工作表交互直到结束。写入工作表是一项耗时的操作,因此这个程序只执行一次,一次写入整个二维数组,而不是逐行编写。因此,无需禁用屏幕更新,计算或其他任何操作。

Function phpStringTo2DArray(ByVal phpString As String) As Variant
    Dim iRow As Long
    Dim iCol As Long
    Dim nCol As Long
    Dim nRow As Long
    Dim nColMax As Long
    Dim lines() As String
    Dim splitLines() As Variant
    Dim elements() As String

    lines = Split(phpString, "[{:#:}]")
    nRow = UBound(lines) - LBound(lines) + 1

    ReDim splitLines(1 To nRow)
    For iRow = 1 To nRow
        splitLines(iRow) = Split(lines(iRow - 1), "[|:#:|]")
        nCol = UBound(splitLines(iRow)) - LBound(splitLines(iRow)) + 1
        ' in case rows have different number of columns:
        If nCol > nColMax Then nColMax = nCol 
    Next iRow
    Erase lines

    'We now have a (Variant) array of arrays. Convert this to a regular 2D array.
    ReDim elements(1 To nRow, 1 To nColMax)
    For iRow = 1 To nRow
        nCol = UBound(splitLines(iRow)) - LBound(splitLines(iRow)) + 1
        For iCol = 1 To nCol
            elements(iRow, iCol) = splitLines(iRow)(iCol - 1)
        Next iCol
    Next iRow
    Erase splitLines

    phpStringTo2DArray = elements
End Function

使用示例:

Dim s As String
Dim v As Variant
s = "1[|:#:|]text-one[|:#:|]code-one[|:#:|]qty-one[{:#:}]2[|:#:|]text-two[|:#:|]code-two[|:#:|]qty-two[{:#:}]"
v = phpStringTo2DArray(s)
'Write to sheet
Range("A1").Resize(UBound(v, 1), UBound(v, 2)) = v

如果你想忽略最后的换行符[{:#:}],可以在函数的顶部添加这一行:

If Right(phpString, 7) = "[{:#:}]" Then phpString = Left(phpString, Len(phpString) - 7)

答案 1 :(得分:1)

这并不像我原先想象的那么容易。我可以轻松摆脱一个循环。但是还有一个if测试,所以它不会打破空字符串等。我觉得一个大师可以使这个更有效率。

我担心的是,这个过程需要花费很多时间。如果你想加快速度,那么你的代码看起来效率太低了。 更有可能的是,如果它运行缓慢,那就是application.calculation& application.screenUpdating设置设置不正确。

Sub takePHP(myString As String)
'This sub takes specially formatted strings from a PHP script,
'and parses into rows and columns
Dim myRows As Variant
Dim myCols As Variant
Dim subRow As Variant
Application.ScreenUpdating = False
Application.Calculation = xlCalculateManual
myRows = Split(myString, "[{:#:}]")
x = 1
For Each subRow In myRows
    bob = Split(subRow, "[|:#:|]")
    If UBound(bob) <> -1 Then
        Range(Cells(x, 1), Cells(x, UBound(bob) + 1)).Value = bob
    x = x + 1
    End If
Next
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub