前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Excel VBA解读(138): 自定义函数时使用字节数组实现更快的字符串处理

Excel VBA解读(138): 自定义函数时使用字节数组实现更快的字符串处理

作者头像
fanjy
发布2019-07-19 11:23:51
2K0
发布2019-07-19 11:23:51
举报
文章被收录于专栏:完美Excel完美Excel

学习Excel技术,关注微信公众号:

excelperfect

字符串处理会使VBA变慢。

假设想要找到字符串中第一个大写字母的位置,可以使用数组公式:

=MATCH(TRUE,ISERR(FIND(MID(A1,ROW($1:$255),1),LOWER(A1))),0)

如果有很多行,要查找每行字符串第一个大写字母的位置,则使用数组公式会花费不少时间。

如果编写用户自定义函数,则会更快些。代码如下:

Function FirstCap2(Cell As Range)
   For FirstCap2 = 1 To Len(Cell.Value)
        If Mid(Cell.Value, FirstCap2, 1) Like"[A-Z]" Then
            Exit For
        End If
   Next FirstCap2
End Function

代码使用Mid遍历字符串,使用LIKE依次检查每个字符是否为大写字母A到大写字母Z之一。

稍微修改一下代码,让其运行更快:

Function FirstCap3(Rng As Range)
   Dim theString As String
   theString = Rng.Value2
   For FirstCap3 = 1 To Len(theString)
        If Mid$(theString, FirstCap3, 1) Like"[A-Z]" Then
            Exit For
        End If
   Next FirstCap3
End Function

将代码更改为将字符串从单元格中仅取出一次,并使用Mid$函数而不是Mid函数。所有的VBA字符串处理函数都有2个版本:不带后缀$使用变体参数的版本,和带有$后缀的只能处理字符串参数的版本,后者速度更快。

但是,也许使用LIKE还是慢?尝试比较字符串的小写版本,并在字符不匹配时停止:

Function FirstCap4(strInp AsString) As Long
   Dim tmp As String
   Dim i As Long
   Dim pos As Long
   tmp = LCase$(strInp)
   pos = -1
   For i = 1 To Len(tmp)
        If Mid$(tmp, i, 1) <>Mid$(strInp, i, 1) Then
            pos = i
            Exit For
        End If
   Next
   FirstCap4 = pos
End Function

但这个版本比前一个版本更慢!将Byte数组与字符串一起使用是VBA不为人知的秘密之一,当需要依次检查每个字符时,它通常是处理字符串的一种有效方法。

Function FirstCap5(theRange AsRange) As Long
   Dim aByte() As Byte
   Dim j As Long
   FirstCap5 = -1
   aByte = theRange.Value2
   For j = 0 To UBound(aByte, 1) Step 2
        If aByte(j) < 91 Then
            If aByte(j) > 64 Then
                FirstCap5 = (j + 2) / 2
                Exit For
            End If
        End If
   Next j
End Function

这个版本的自定义函数更快。代码首先创建一个Byte类型的数组,然后将字符串赋给该数组。字符串中的每个字符都有2个字节,英文大写字符的ANSI编号是65到90,因此可以循环这个字节数组,间隔查看其中的字节,并直接对字符进行数字测试,看它是否为大写。

Byte数组另一个令人惊讶的特点是可以直接赋值字节数组到字符串:

Dim str1 as string

str1=aByte

正如在上一篇文章中所讨论的,数组公式更快。因此,给出该用户定义函数的数组公式版本:

Function AFirstCap(theRange AsRange) As Variant
   Dim aByte() As Byte
   Dim j As Long
   Dim L As Long
   Dim vRange As Variant
   Dim jAnsa() As Long
   Dim NumCells As Long
   vRange = theRange.Value2
   NumCells = UBound(vRange, 1)
   ReDim jAnsa(NumCells - 1, 0)
   For L = 0 To NumCells - 1
        jAnsa(L, 0) = -1
        aByte = vRange(L + 1, 1)
        For j = 0 To UBound(aByte, 1) Step 2
            If aByte(j) < 91 Then
                If aByte(j) > 64 Then
                    jAnsa(L, 0) = (j + 2) / 2
                    Exit For
                End If
            End If
        Next j
   Next L
   AFirstCap = jAnsa
End Function

小结:在字符串处理中,需要检查或操作很多单个字符时,使用字节数组是一个很好的解决方案。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 完美Excel 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档