Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 字符串是VBA中可以迭代的数组吗?_Arrays_Vba_Excel - Fatal编程技术网

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

Arrays 字符串是VBA中可以迭代的数组吗?,arrays,vba,excel,Arrays,Vba,Excel,字符串是VBA中的数组吗 例如,我可以像在C/C++中一样迭代它吗 这样做: char myArray[10]; for (int i = 0; i < length; i++) { cout << myArray[i]; } charmyarray[10]; for(int i=0;i

字符串是VBA中的数组吗

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

这样做:

char myArray[10]; 

for (int i = 0; i < length; i++)
{
    cout << myArray[i];
}
charmyarray[10];
for(int i=0;icout我认为VBA不允许在不转换字符串的情况下将其作为数组处理

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

代码是OTTOMH

declare i as integer
declare strlen as int

strlen = Len (YourIncomingString)

for i = 0 to strlen
    print Mid (YourIncomingString, i, 1)

简单回答:不,字符串不是VBA中的对象。您必须在使用mid和len函数时按字符将其分开。

它不是数组,但可以使用
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
另请参见,以了解更多优点

编辑 实际上,还有第二种方法可以迭代字符串,即将字符串转换为一个单位数字符串数组,然后进行迭代。为此,我们首先必须将原始字符串转换为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,速度更快):

结果:

Time Mid:     4.62962998426519e-05 
Time Split:    1.15740767796524e-05 
因此,拆分方法似乎要快一些



VBA字符串被实现为。可以找到此数据类型的详细信息。

Mid
用于获取任何字符串中的第n个字符,但返回一个
变量
,该变量会隐式转换为
字符串


使用“强类型”版本:
Mid$

字符串是一个字节数组,如果您知道如何实现字符串的两个字节(或Unicode,通常每个字符2个字节,但可以更多:如果字符串源于VBA,则始终是2个字节),则可以对其进行迭代

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

Public子TestByteString()
作为字符串的暗字符串
Dim arrBytes()作为字节
作为整数的Dim i
strChars=“敏捷的棕色狐狸”
arrBytes=strChars
调试。打印strChars
调试。打印
对于i=LBound(arrBytes)到UBound(arrBytes)步骤2
调试。打印Chr(arrBytes(i))&vbTab&“Byte”&i&“=”&arrBytes(i)
接下来我
arrBytes(0)=Asc(“?”)
arrBytes(2)=Asc(“!”)
arrBytes(4)=Asc(“*”)
strChars=arrBytes
调试。打印
调试。打印strChars
删除arrBytes
端接头
您的输出将如下所示: 敏捷的棕色狐狸

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

?!*快速棕色狐狸

请注意循环中的“第2步”:我将每隔一个字节丢弃一个字节,因为我知道它是普通的拉丁字符,对于未初始化的用户来说是“ASCII”文本

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

要获得更全面的示例和更详细的解释,请尝试以下内容:

字节数组优化位于底部,位于该标题下:Adler-32校验和的VBA实现,在字节数组上运行,而不是使用VBA字符串处理


字符串的基本性质似乎并不像它应该的那样广为人知:这不是您在代码中经常使用的东西,而是Unicode和非拉丁字母表的许多问题,当人们对代码中的变量有了更深入的了解时,这些问题就变得更容易解决了。

仍然可以创建您的o自定义可枚举字符串

可枚举字符串的使用方式如下:

char myArray[10]; 

for (int i = 0; i < length; i++)
{
    cout << myArray[i];
}
将此代码保存在名为
EnumerableString.cls
a的文件中,并将其导入VBA项目

生成Excel,例如ASCII、ANSI和Unicode UTF-8字符:


@timbram这就是你想要做的事情我唯一不喜欢的是计时方法-VBA中的基准测试非常糟糕。单元测试的计算时间只有毫秒,由.net
秒表计算(我知道,我写了它;)…我打算试一试,但我想我应该让你知道我的宠物项目,因为我认为它与此相关。我启动了单元测试-正如你所看到的,我已将大部分设置代码提取到
ModuleInitialize
中,以便测试只测试相关部分。
TestMid
运行时间为17-22毫秒,
TestSplit
运行在7-10毫秒内(运行了几次),所以是的,明确的赢家:)我建议谷歌搜索“VBA中的字符串优化”。任何分配和重新分配字符串变量的函数都会很慢:拆分到数组是一种有效的优化,就像一个(效率极低的)函数一样分配已经结束,您不再在循环中进行分配;但是有很多更好的方法可以做到这一点。从这篇文章开始,继续阅读:@Nile,非常感谢链接,这是一篇很好的阅读,性能比较非常有用。我过去使用过ByteArray,但并不广泛。我同意在使用字节数组时,使用字节数组比拆分或中间分隔更有效。我对您的代码进行了+1-ed,其中唯一需要更改的是,尽管在大多数情况下,差异非常小。如果您真的需要,可以将字符串赋给字节数组并循环使用,但随后您必须将字节转换回字符。我编辑了您的标题。请参见“”,其中共识是“不,他们不应该”。请参见下面的详细答案。字符串是字节数组,反之亦然。不是“可以转换为字节数组的变量”,而是 The quick Brown Fox

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

?!* quick Brown Fox
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
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