熟悉EXCEL函数的朋友遇到截取字符串的时候第一个想到的肯定是FIND()、 LEN() 、LEFT()、**RIGHT()**这一套操作, 但很遗憾VBA里面的FIND针对的是Range对象,用到字符串类型的变量上只能会不停报错。此时需要请出的大神是VBA/Access里面的函数:
InStr() 和 InStrRev()兄弟
对于大量诸如“上海市浦东新区金桥街道某某路某某号”这样的结构化文本而言,可以把重复出现的“市、区、街道、路、号”看做“分隔符”,进而把内容分隔成我们需要的小板块。
具体来说,InStr从左往右找,InStrRev从右向左,不涉及大小写区分的话直接填——(字符串,“分隔符”)即可,函数返回一个整数来表示分隔符在字符串中的下标。留意下,如果分隔符是“//”,“自治区”之类的多个字符组成,那么返回的下标永远是分隔符左起第一个字符在整个字符串里面的位置。
举例说明:
待切片字符串: 北 京 > 海 淀 > 学 院 路 > 北 京 语 言 大 学
对 应 的 下 标: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
要 求: 把最后一个“>”右边的内容解出来
步骤:
- 字符串全长 = VBA.Len(“北京>海淀>学院路>北京语言大学”), 结果是16
- 找到最右边一个“>”的下标 = VBA.InStrRev(“北京>海淀>学院路>北京语言大学”, “>”),结果是10
(有趣吧,InStrRev虽然是从右往左找,但下标并没有从右往左数,也不像python用负数,还是正序下标) - 目标字符串=VBA.Right(“北京>海淀>学院路>北京语言大学”, 16-10), 右截取,搞定。
- 至于说有些列里面没有“>”, 那就IF判断下即可,没有的保持原样不切片即可
下面上我的工作实例,要求写宏代码把原表O列中的样式改成仅存在最后一层机构名的形式:
图1:原表0列的样子
“图2:清理后的样子”
代码如下
代码是一个子过程,工作表对象w是由主过程传进来的。各个步骤的注释写的很详细,仅供和我一样的小白参考。重点在Do While Loop和里面的IF Else判断里。
Sub Col_O_UserInstitute(w As Worksheet)
w.Range("O1").ColumnWidth = 25
Dim Delimiter_Sub As Integer '创建变量存储分隔符下标
Dim ridx As Long '工作表w里的行标row index
Dim FullStr, FullLen, Institute_Name '未截取前的字符串、未截取前的全长、机构名称,都是字符串
ridx = 2 '第一行是表头,从第二行开始循环处理
Do While w.Cells(ridx, 15) <> "" '只要不为空就接着循环
FullStr = w.Cells(ridx, 15) '把全长的字符串读出来准备查找分隔符
FullLen = VBA.Len(FullStr) '把全长字符串的长度读出来
Rem 感谢VBA.InStrRev()函数,VBA里面的FIND找的是Range不是Str,不要和Excel函数搞混了
Delimiter_Sub = VBA.InStrRev(FullStr, ">>") '找到以后输出下标
Rem 很有意思的一点,VBA.InStrRev()函数返回的下标还是从左往右数的哦!
Debug.Print "第" & ridx & "行数据里的分隔符出现在" & "第" & Delimiter_Sub & "位"
'VBE立即窗口内可以监视下跑的情况
If Delimiter_Sub = 0 Then '如果InStrRev返回O说明从右往左找了字符串没有发现目标
Institute_Name = FullStr '没找到就不需要截取,机构名就等于原字符串
Else '如果InStrRev返回了大于0的数字,说明找到了分隔符,机构名一定在分隔符右边
Institute_Name = VBA.Right(FullStr, FullLen - Delimiter_Sub - 1)
'因为是从右边截取,所以截取的长度等于:“字符串全长 - 右起第一个分隔符的下标”
'截取还要再减1,因为>>本身有长度,InStrRev返回的是“>>”里左边那个的下标
'因此如果分隔符是由两个或以上字符串组成的话,截取长度为:
'字符串全长 - InStrRev返回的分隔符下标 - (分隔符本身长度-1)
End If
Debug.Print "第" & ridx & "行数据里的学校名为:" & Institute_Name '输出到立即窗口便于调试
w.Cells(ridx, 15) = Institute_Name
ridx = ridx + 1
Loop
End Sub
代码敲完,在VBE的立即窗口里欣赏下过程就好: