是一个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字符的示例: