字符串是VBA中可以迭代的数组吗?

tim*_*ram 14 arrays excel vba excel-vba

字符串是VBA中的数组吗?

例如,我可以像在C/C++中那样迭代它吗?

做这样的事情:

char myArray[10]; 

for (int i = 0; i < length; i++)
{
    cout << myArray[i];
}
Run Code Online (Sandbox Code Playgroud)

VBA中的等价物会是什么?它没有像我期望的那样表现.在VBA之前从未尝试过操纵过很多字符串!:)

Nig*_*nan 13

字符串是一个字节数组,如果您知道绕过字符串的双字节实现(或者Unicode,通常每个字符2个字节,但可以更多),您可以遍历它,并且它总是会是如果您的字符串来自VBA,则为2字节).

当我说,我的意思是:不需要类型转换,这将工作得很好:

Public Sub TestByteString()

    Dim strChars As String
    Dim arrBytes() As Byte
    Dim i As Integer


    strChars = "The quick Brown Fox"
    arrBytes = strChars

    Debug.Print strChars
    Debug.Print

    For i = LBound(arrBytes) To UBound(arrBytes) Step 2 

        Debug.Print Chr(arrBytes(i)) & vbTab & "Byte " & i & " = " & arrBytes(i)

    Next i

    arrBytes(0) = Asc("?")
    arrBytes(2) = Asc("!")
    arrBytes(4) = Asc("*")

    strChars = arrBytes

    Debug.Print
    Debug.Print strChars

    Erase arrBytes

End Sub
Run Code Online (Sandbox Code Playgroud)

您的输出将如下所示:

Public Sub TestByteString()

    Dim strChars As String
    Dim arrBytes() As Byte
    Dim i As Integer


    strChars = "The quick Brown Fox"
    arrBytes = strChars

    Debug.Print strChars
    Debug.Print

    For i = LBound(arrBytes) To UBound(arrBytes) Step 2 

        Debug.Print Chr(arrBytes(i)) & vbTab & "Byte " & i & " = " & arrBytes(i)

    Next i

    arrBytes(0) = Asc("?")
    arrBytes(2) = Asc("!")
    arrBytes(4) = Asc("*")

    strChars = arrBytes

    Debug.Print
    Debug.Print strChars

    Erase arrBytes

End Sub
Run Code Online (Sandbox Code Playgroud)

注意循环中的"步骤2":我丢弃了所有其他字节,因为我知道它是普通的拉丁字符 - "ASCII"文本给不熟悉的人.

当你必须处理阿拉伯语和拼音文本时,它会变得很有趣:你永远不应该在现实世界的工作表中假设你总是要处理普通的美国ASCII,正如我在那个演示文章中所做的那样.

有关更全面的示例,有更详细的解释,请从Excellerando试试:

将Excel范围写入csv文件:优化和unicode兼容性

在此标题下,字节数组优化位于底部:

Adler-32校验和的VBA实现,在字节数组上运行,而不是使用VBA字符串处理.

字符串的基本特性似乎并不像它应该的那样广为人知:它不是你经常在你的代码中使用的东西,而是人们已经获得的Unicode和非拉丁字母表的许多问题当他们更深入地了解代码中的变量时更容易.


Ioa*_*nis 12

它不是一个数组,但你想要的可以使用 MID

Sub test()
    Dim strSentence As String
    Dim lngCount As Long    

    strSentence = "This is a string"

    For lngCount = 1 To Len(strSentence)
        Debug.Print Mid(strSentence, lngCount, 1)
    Next lngCount             
End Sub
Run Code Online (Sandbox Code Playgroud)

另请参阅Mat的Mug答案以获得额外的好处.

编辑

实际上,有第二种方法来遍历字符串,即将字符串转换为单位数字符串数组,然后遍历它们.为此,我们必须将原始字符串转换为unicode格式,以便可以将Null字符作为分隔符.这是一个可重复的例子:

Sub test2()
    Dim strSentence As String
    Dim lngCount As Long
    Dim strArray() As String

    strSentence = "This is a string"
    strSentence = StrConv(strSentence, vbUnicode)

    strArray = Split(strSentence, vbNullChar)

    For lngCount = 0 To UBound(strArray)
        Debug.Print strArray(lngCount)
    Next lngCount
End Sub
Run Code Online (Sandbox Code Playgroud)

出于好奇,我比较了两种方法(使用Mat的Mid版本,速度更快):

Sub test_sub()
    Dim strTest(1 To 5000) As String
    Dim lngStringIter As Long
    Dim lngChars As Long, dblTick As Double

    ' Generate  some long strings first
    For lngStringIter = 1 To 5000
        strTest(lngStringIter) = vbNullChar
        For lngChars = 1 To 10
            strTest(lngStringIter) = strTest(lngStringIter) & _
                Chr(Int((90 - 65 + 1) * Rnd + 65)) & strTest(lngStringIter)
        Next lngChars
    Next lngStringIter

    ' Lets see what happens..
    dblTick = CDbl(Now())
    For lngStringIter = 1 To 5000
      test strTest(lngStringIter)
    Next lngStringIter
    Debug.Print "Time Mid: ", CDbl(Now()) - dblTick

    dblTick = CDbl(Now())
    For lngStringIter = 1 To 5000
      test2 strTest(lngStringIter)
    Next lngStringIter
    Debug.Print "Time Split: ", CDbl(Now()) - dblTick
End Sub
Run Code Online (Sandbox Code Playgroud)

结果:

Time Mid:     4.62962998426519e-05 
Time Split:    1.15740767796524e-05 
Run Code Online (Sandbox Code Playgroud)

所以看起来Split方法有点快.


VBA字符串实现为BSTR数据类型.有关此数据类型的更多信息,请访问此处此处.

  • 我建议谷歌搜索"VBA中的字符串优化".分配和重新分配字符串变量的任何函数都会很慢:拆分到数组是一种有效的优化,因为一个(非常低效)的分配已经结束并完成,并且你在循环中不再做任何更多的事情; 但是有很多更好的方法可以做到这一点.从这篇文章开始,并继续阅读:http://www.aivosto.com/vbtips/stringopt.html (2认同)

Mat*_*don 12

Mid用于获取任何字符串中的 n 字符,但返回a Variant,这会导致隐式转换String.

使用"强类型"版本:Mid$改为.


Raj*_*ore 5

我不认为VBA允许您将字符串视为数组而不转换它.

但是,您可以使用一次MID获取一个字符.

代码是OTTOMH

declare i as integer
declare strlen as int

strlen = Len (YourIncomingString)

for i = 0 to strlen
    print Mid (YourIncomingString, i, 1)
Run Code Online (Sandbox Code Playgroud)