1、简单实现

前面我们实现了首字母大写、转换大写、转换小写3个功能,如果再实现一个大小写互换,有了前面的基础,实现起来应该没什么大问题:

Function FUpperLowerSwap(str As String) As String    Dim i As Long    Dim tmp As String        For i = 1 To VBA.Len(str)        tmp = VBA.Mid$(str, i, 1)                If tmp >= "a" And tmp <= "z" Then            tmp = VBA.UCase$(tmp)            Mid(str, i, 1) = tmp        ElseIf tmp >= "A" And tmp <= "Z" Then            tmp = VBA.LCase$(tmp)            Mid(str, i, 1) = tmp        End If    Next        FUpperLowerSwap = strEnd Function

注意这里的Mid(str, i, 1) = tmp,里面的Mid是一个语句,不是字符串处理函数。功能是替换str中的字符。

实现了FUpperLowerSwap函数,我们只要调用这个函数就可以实现字符串中的字母大小写互换了。

2、思路扩展

函数里面主要是通过判断字符是否是小写字符或者是否是大写字符,然后进行转换,在这里这个功能比较简单,只需要两个If判断就可以。如果是要实现一个更复杂的功能,需要判断的东西更多,那么只能不停的增加If判断。

这样不但代码看起来混乱、复杂,而且一旦要处理的数据量太多,程序效率也会很低。

这里我们介绍一种比较常用的编程思路,使用数组来减少If的使用。

通过前面的了解,我们知道字母都是ASCII编码的,数字不会超过255,所以,我们首先可以使用一个下标是0-255的数组,分别对应ASCII编码的字符,那么字母自然也能够和数组一一对应。

数组记录什么呢?

我们这里是希望能够实现字母的大小写转换,所以需要记录的就是字符要进行转换的时候,需要去做什么。

根据前面提到过的大小写字母相差编码固定的知识,我们使用数组记录的就是这个需要增加的数字(减少的时候就是负数)。

而为了功能的更加完整,我们记录一个字符转换为大写、转换为小写、大小写转换3个数据,这个时候使用自定义的结构体就非常合适了:

Private Type Letter    '转换为大写需要增加的数字,可以是负数    ToUpper As Integer    '转换为小写需要增加的数字,可以是负数    ToLower As Integer    '转换需要增加的数字,可以是负数    Change As IntegerEnd Type

然后是要初始化:

Private Function InitLetters() As Letter()    Dim ret() As Letter    'ASCII字符不会超过255    ReDim ret(&HFF) As Letter        Dim i As Long    '记录小写字母需要转换的时候,应该增加的数字    For i = VBA.Asc("a") To VBA.Asc("z")        ret(i).ToUpper = VBA.Asc("A") - VBA.Asc("a")        ret(i).Change = ret(i).ToUpper    Next         '记录大写字母需要转换的时候,应该增加的数字    For i = VBA.Asc("A") To VBA.Asc("Z")        ret(i).ToLower = VBA.Asc("a") - VBA.Asc("A")        ret(i).Change = ret(i).ToLower    Next        '其他的字符都不需要初始化,默认为0即可        InitLetters = retEnd Function

在这个基础上,来实现FUpperLowerSwap函数,因为转换方式有3种,这里再使用枚举来定义:

Private Enum EChange    Upper    Lower    ChangeEnd Enum

函数实现:

Private Function ToUpperLowerOrChange(str As String, ls() As Letter, C As EChange) As String    Dim i As Long    Dim b() As Byte    'String转换为byte来处理    b = str        'VBA使用的是Unicode编码,每个字符占用2个字节    For i = 0 To UBound(b) - 1 Step 2        '字符低位在前面,高位在后面,所以如果是ASCII字符的话,高位就是0        If b(i + 1) = 0 Then            '这里不需要再判断是否是字母来,因为未初始化的ASCII字符转换的时候都是增加0,不会影响            Select Case C                Case EChange.Upper                b(i) = b(i) + ls(b(i)).ToUpper                                Case EChange.Lower                b(i) = b(i) + ls(b(i)).ToLower                                Case EChange.Change                b(i) = b(i) + ls(b(i)).Change            End Select        End If    Next        ToUpperLowerOrChange = bEnd Function

主函数再调用:

Sub UpperLowerSwap()    Dim rng As Range, selectRng As Range    Dim ls() As Letter        '确保选中的是单元格    If TypeName(Selection) = "Range" Then        Set selectRng = Selection                ls = InitLetters()        For Each rng In selectRng            rng.Value = ToUpperLowerOrChange(VBA.CStr(rng.Value), ls, EChange.Change)        Next rng    End If        Set rng = Nothing    Set selectRng = NothingEnd Sub

3、性能测试

Sub testletter()    Dim strs(500000) As String    Dim ls() As Letter    Dim t As Double        Dim i As Long    For i = 0 To UBound(strs)        strs(i) = "abABalsdfasSLDFJGOAEIsl中文..asdf1.,..,msfi"    Next        t = VBA.Timer    Debug.Print "扩展方法:"    Debug.Print "开始时间:", t        ls = InitLetters()        For i = 0 To UBound(strs)        ToUpperLowerOrChange strs(i), ls, Change    Next    Debug.Print "结束时间:", VBA.Timer    Debug.Print "使用时间:", VBA.Timer - t        Debug.Print "————————————————————————————"            t = VBA.Timer        Debug.Print "普通方法:"    Debug.Print "开始时间:", t    For i = 0 To UBound(strs)        FUpperLowerSwap strs(i)    Next    Debug.Print "结束时间:", VBA.Timer    Debug.Print "使用时间:", VBA.Timer - tEnd Sub

本人电脑测试结果:

扩展方法:开始时间:      36800.1328125 结束时间:      36801.96 使用时间:      1.828125 ————————————————————————————普通方法:开始时间:      36801.9609375 结束时间:      36810.26 使用时间:      8.30078125

50万个字符串,1.8秒和8.3秒,时间差异大约在4倍左右。