是一个stringVBA中的数组,可以通过迭代?

在VBA中是一个string数组?

例如,我可以像在C / C ++中一样遍历它吗?

做这样的事情:

char myArray[10]; for (int i = 0; i < length; i++) { cout << myArray[i]; } 

在VBA中相当于什么? 这不是我所期望的。 从来没有真正尝试在VBA之前操纵很多string! 🙂

这不是一个数组,但你想要什么可以使用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 

另请参阅Mat's Mug的答案,以获得更多的好处。

编辑

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

 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 

出于好奇,我比较了两种方法(使用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 

结果:

 Time Mid: 4.62962998426519e-05 Time Split: 1.15740767796524e-05 

所以看来Split方法有点快。


一个VBAstring被实现为一个BSTR数据types 。 这种数据types的更多信息可以在这里和这里find。

一个string是一个字节数组,如果你知道围绕一个string的双字节实现(或者Unicode,通常每个字符2字节,但是可以更多的话),你可以遍历它。 2字节,如果你的string起源于VBA)。

当我说的 ,我的意思是:没有必要进行types转换,这将工作得很好:

 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 

您的输出将如下所示:

快速的布朗福克斯 

T字节0 = 84
h字节2 = 104
e字节4 = 101
字节6 = 32
q字节8 = 113
u字节10 = 117
我字节12 = 105
c字节14 = 99
k字节16 = 107
字节18 = 32
B字节20 = 66
r字节22 = 114
o字节24 = 111
字节26 = 119
n字节28 = 110
字节30 = 32
字节32 = 70
o字节34 = 111
x字节36 = 120

快!布朗福克斯

请注意循环中的“第2步”:我丢弃了其他所有字节,因为我知道它是简单的香草拉丁字符 – 对于未经启动的“ASCII”文本。

当你不得不处理阿拉伯文和拼音文本时,它会变得很有趣:你不应该在现实世界的工作表中假设你总是要处理纯粹的美国ASCII,就像我在那个演示文稿中所做的那样。

为了更全面的例子,更详细的解释,从Excellerando:

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

字节数组优化是在底部,在这个标题下:

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

string的基本性质似乎不像应该那样广为人知:在代码中经常使用的不是一个东西,而是人们在Unicode和非拉丁字母上遇到的很多问题当他们对代码中的variables有更深入的了解时更容易。

Mid可以获取任何string中的 n 字符,但会返回一个Variant ,这会导致向String隐式转换。

使用“强types”版本: Mid$代替。

我不认为VBA可以让你把一个string当作一个数组来处理,而不用转换它。

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

代码是OTTOMH

 declare i as integer declare strlen as int strlen = Len (YourIncomingString) for i = 0 to strlen print Mid (YourIncomingString, i, 1) 

简单的回答:不,string不是VBA中的对象。 在使用mid和len函数的时候,你将不得不在字符上select它。

仍然可以创build自己的自定义可枚举string。

Enumerablestring可以像这样使用:

 Dim es As EnumerableString Set es = New EnumerableString es.Value = ActiveCell.Value Dim ch As Variant For Each ch In es ActiveCell.Offset(1, 0).Activate ActiveCell.Value = ch Next ch 

将此代码保存在名为EnumerableString.cls的文件中,并将其导入到VBA项目中。

 VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "EnumerableString" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit Private m_characters As Collection Public Property Get NewEnum() As IUnknown Attribute NewEnum.VB_UserMemId = -4 Attribute NewEnum.VB_MemberFlags = "40" Set NewEnum = m_characters.[_NewEnum] End Property Public Property Let Value(ByVal newValue As String) Dim pos As Integer Set m_characters = New Collection For pos = 1 To Len(newValue) m_characters.Add Mid$(newValue, pos, 1) Next pos End Property Public Function Length() As Long Length = m_characters.Count End Function Public Function Item(ByVal index As Variant) As String Attribute Item.VB_UserMemId = 0 Item = m_characters(index) End Function Private Sub Class_Initialize() Set m_characters = New Collection End Sub 

Excel中的结果,带有ASCII,ANSI和Unicode UTF-8字符的示例:

在这里输入图像说明