字符串的比较

在E xcel VBA和Python中,可以使用关系运算符比较字符串,也可以使用提供的各种函数比较字符串。

使用关系运算符进行比较

【Excel VBA】

Excel VBA中,可以使用关系运算符直接对字符串进行比较。关系运算符包括<, <=, >, >=, =和<>等。使用关系运算符比较两个字符串时,从头开始逐个比较两个字符串的字符,根据第1个不同字符的比较结果得到两个字符串比较的结果。

下面给定两个字符串,比较第1个字符串是否小于第2个字符串。示例文件的存放路径为Samples\ch06\Excel VBA\字符串比较.xlsm。

code.vba
Sub Test()
  Dim strA As String
  Dim strB As String
  strA = "dqexcel"
  strB = "dqexcel123"
  Debug.Print strA < strB
End Sub

运行程序,在立即窗口中输出True,表示字符串strA小于strB。

【Python】

Python中,使用关系运算符、成员运算符和字符串相关的函数和方法进行字符串比较。

下面用==或!=比较两个字符串对象的值相等或不相等。

code.python
>>> a='dqexcel'
>>> b='dqexcel123'
>>> a==b    #值相等时返回True
False
>>> a!=b   #值不相等时返回True
True

用is比较两个字符串对象的内存地址是否相同。

code.python
>>> a is b    #内存地址相同时返回True
False

用成员运算符in或not in计算指定字符串是否包含或不包含在另一个字符串中,成立时返回True,否则返回False。

code.python
>>> a in b    #'dqexcel'是否包含在'dqexcel123'中
True
>>> 'd' not in b    #'d'是否不包含在'dqexcel123'中
True

使用函数进行比较

【Excel VBA】

也可以使用StrComp函数比较两个字符串的大小。该函数的语法格式为:

code.vba
StrComp(String1, String2[, Compare])

其中,Compare参数指定字符串比较的方式,默认值为vbBinaryCompare,区分大小写;设置为vbTextCompre时不区分大小写。设置比较方式,也可以在模块顶部输入Option Compare Binary或Option Compare Text语句指定比较时区分大小写或不区分大小写。

StrComp函数的返回值为-1时,表示String1<String2;返回值为0时,表示String1=String2;返回值为1时,表示Strign1>String2;返回值为Null时,表示String1和String2中至少有1个为Null。

下面给定两个字符串,用StrComp函数比较它们的大小。示例文件的存放路径为Samples\ch06\Excel VBA\字符串比较.xlsm。

code.vba
Sub Test2()
  Dim strA As String
  Dim strB As String
  Dim strC As String
  Dim varComp1, varComp2, varComp3
  strA = "dqexcel"
  strB = "dqexcel123"
  strC = "Dqexcel"
  varComp1 = StrComp(strA, strB)  '区分大小写
  varComp2 = StrComp(strA, strC)  '
  varComp3 = StrComp(strA, strC, vbTextCompare)  '不区分大小写
  Debug.Print varComp1, varComp2, varComp3
End Sub

运行程序,在立即窗口中输出比较结果:

code.vba
-1             1             0

可见,区分大小写时,strA<strB,strA>strC,不区分大小写时,strA=strB。

【Python】

Python 3中没有功能类似VBA中StrComp函数的函数,实现类似的功能可以使用operator模块中的相关函数,如表6-7中所示。注意,这些函数比较字符串的大小时,是按字符串中的字母逐个比较的。比较时先获取字母对应的ASCII码,然后比较该数字的大小。

表6-7 用operator模块中的函数比较字符串

函 数 说 明
operator.lt(str1, str2) str1小于str2时返回True, 否则返回False
operator.le(str1, str2) str1小于或等于str2时返回True, 否则返回False
operator.eq(str1, str2) str1等于str2时返回True, 否则返回False
operator.ne(str1, str2) str1不等于str2时返回True, 否则返回False
operator.gt(str1, str2) str1大于str2时返回True, 否则返回False
operator.ge(str1, str2) str1大于或等于str2时返回True, 否则返回False

下面导入operator模块并使用模块中的函数比较给定字符串的大小。

code.python
>>> import operator as op
>>> op.lt('a';,'b')    #'a'是否比'b'小
True
>>> op.eq('a123',&#x27;a12b')    #'a123'与'a12b'是否相等
False
>>> op.ge('forpython',&#x27;forvba')    #'forpython'是否大于或等于'forvba'
False

Python提供的其他一些进行字符串比较的函数如表6-8所示。可以用它们判断字符串中元素的类型和大小写等情况。

表6-8 进行字符串比较的函数

函数 说 明
str.isalnum() 字符串中全是数字或字母
str.isalpha() 字符串中至少有一个字母并且全是字母
str.isdigit() 字符串中全是数字
str.isnumeric() 字符串中全是数字
str.islower() 字符串中全是否为小写字母
str.isupper() 字符串中全是否为大写字母
str.isspace() 字符串中只包含空格,返回True,否则返回False
max() 最大的字母
min() 最小的字母

下面举例说明:

code.python
>>> 'Abc123'.isalnum()    #字符串全是字母和数字
True
>>> 'Abc123'.isalpha()    #是否全是字母
False
>>> '123123'.isdigit()    #是否全是数字
True
>>> '123.123'.isnumeric()    #是否全是数字
False
>>> 'abc'.islower()    #字母是否全是小写
True
>>> max('Abc&#x27;)    #最大的字母
'c'

字符串比较示例-找老乡

图6-8中第1-2列为一组人的姓名和籍贯,现在希望将籍贯相同的人员姓名找出来,并如图6-8中进行显示。

Document Image

图6-8 找老乡

查找的思路是,首先遍历第2列的籍贯数据,在第4列建一个唯一籍贯列表,如果第2列的当前籍贯在第4列不存在,则将该籍贯添加到第4列下面第1个空行对应的单元格,将对应的姓名添加到该单元格右侧单元格;如果当前籍贯在第4列已经存在,则直接添加对应姓名到第4列中对应籍贯右侧第1个空单元格。完成遍历后各地人员就找到了。所以这里需要进行籍贯名称的比较。

【Visual VBA】

示例文件的存放路径为Samples\ch06\Excel VBA\找老乡.xlsm。

code.vba
Sub Test()
  Dim intK As Integer  '记录省份个数
  Dim intN As Integer  '记录某籍姓名个数
  Dim intR As Integer  '记录数据行数
  Dim sht As Object  '工作表对象
  Set sht = ActiveSheet
  Dim intI As Integer
  Dim intJ As Integer
  Dim bolExist As Boolean  '省份是否已经存在

  '数据行数
  intR = sht.Range("B1").End(xlDown).Row

  '省份去重,去重结果放在第4列
  sht.Range("D2").Value = "河北"
  intK = 1
  For intI = 3 To intR
    '遍历工作表中第2列数据
    bolExist = False
    For intJ = 2 To intK + 1
      '遍历已经得到的唯一省份
      If sht.Cells(intI, 2).Value = sht.Cells(intJ, 4).Value Then
        '如果有一个相等,则省份已经存在
        bolExist = True
      End If
    Next
    '如果不存在,则在第4列追加省份名称
    If Not bolExist Then
      intK = intK + 1
      sht.Cells(intK + 1, 4).Value = sht.Cells(intI, 2).Value
    End If
  Next

  '获取各省同乡姓名,添加到省份名称后面
  '遍历唯一省份名称
  For intI = 1 To intK
    intN = 1
    For intJ = 2 To intR  '遍历第2列数据
      '如果第2列当前数据与唯一省份名称相同
      If sht.Cells(intJ, 2).Value = sht.Cells(intI + 1, 4).Value Then
        '把姓名追加到省份名称后面
        sht.Cells(intI + 1, 4 + intN).Value = sht.Cells(intJ, 1).Value
        intN = intN + 1
      End If
    Next
  Next
End Sub

运行程序,查找结果如图6-8中所示。

【Python】

本示例的数据文件存放路径为Samples\ch06\Python\找老乡.xlsx,py文件保存在相同目录下,文件名为sam06-08.py。

code.python
import xlwings as xw  #导入xlwings包
#从constants类中导入Direction
from xlwings.constants import Direction
import os  #导入os包
#获取本py文件的当前路径
root = os.getcwd()
#创建Excel应用,可见,没有工作簿
app=xw.App(visible=True, add_book=False)
#打开数据文件,可写
bk=app.books.open(fullname=root+\
    r'\找老乡.xlsx',read_only=False)
sht=bk.sheets(1)  #获取第1个工作表
#工作表中第2列数据最大行号
rows=sht.api.Range('B1').End(Direction.xlDown).Row
n=1  #记录当前行号
#遍历第2列,获取唯一省份名称
for i in range(2,rows+1):
    ex=False
    #在第4列显示唯一省份
    #遍历已经获取的唯一省份
    for j in range(1,n+1):
        if sht.cells(i,2).value==sht.cells(j+1,4).value:
            #如果有一个相等,则省份已经存在
            ex=True
    #如果不存在,则在第4列追加省份名称
    if not ex:
        n+=1
        sht.cells(n,4).value=sht.cells(i,2).value
#获取各省同乡姓名,添加到省份名称后面
#遍历唯一省份名称
for i in range(n):
    k=1
    for j in range(2,rows+1):
        #如果第2列当前数据与唯一省份名称相同
        if sht.cells(j,2).value==sht.cells(i+1,4).value:
            #把姓名追加到省份名称后面
            sht.cells(i+1,4+k).value=sht.cells(j,1).value
            k+=1

运行脚本,查找结果如图6-8中所示。