VBA 字符串处理拓展:从拼接到清洗,这几个常用函数一起讲明白
我们在上一篇的字符串内容里,已经讲了 VBA 字符串的一些基础知识。
比如什么是字符串,双引号怎么用,数字和数字字符串有什么区别,字符串拼接该怎么写,这些最基础的部分,前面都已经讲过了。
但字符串在我们的工作中真的太常用了。
客户名称、订单编号、部门名称、备注内容、状态字段、通知文案、地址信息,这些几乎天天都会碰到。很多时候,代码跑不顺,问题还真不一定出在循环或者判断上,反而是字符串这里藏着一些细小但高频的坑。
再往后写一点 VBA 你就会发现,字符串这块不是“知道一点就够了”的内容。尤其是当你开始批量生成文案、清洗文本、提取字段、替换内容的时候,字符串处理能力几乎就是基本功。
所以这一篇,我把字符串再往前整理一步。
一方面补几个在实操里特别容易出问题的点,另一方面把几个真正常用的字符串函数也一起合并进来,放到同一篇里讲清楚。
希望能对大家有所帮助。
一、固定文本和变量,先分清楚
这个地方看起来基础,但真的很容易反复出错。
比如你想把“已完成”写进单元格里,应该写成:
Range("D2").Value = "已完成"
这里的“已完成”是固定文本,所以必须放在双引号里。
但如果你前面已经定义了一个变量,比如:
Dim statusText AsStringstatusText = "已完成"
那后面再写入单元格时,就应该写成:
Range("D2").Value = statusText
因为这时候写进去的,不是字面上的 statusText 这几个字,而是这个变量里存着的内容。
这个区分很重要。
我自己写字符串相关代码时,脑子里一般都会先过一遍:
我现在写的是固定文案,还是变量里的值。
这个动作看起来很小,但能帮你挡掉很多低级错误。
二、字符串想换行,不能直接敲回车
这一点在生成通知文案的时候特别常见。
有时候我们想在一个单元格里放两行内容,比如第一行是客户名,第二行是预约时间。很多人第一反应是直接在双引号中间按回车。
在 VBA 里,这样写不行。
字符串本身不能直接跨行写。想换行,得插入换行符,最常用的就是 vbNewLine。
比如下面这张安装预约表,我想在 D 列自动生成两行提醒内容。
Sub BuildInstallNotice()Dim i AsLongDim customerName AsStringDim installDate AsStringDim timePeriod AsStringDim noticeText AsStringFor i = 2To4'逐行处理安装预约数据 customerName = Cells(i, 1).Value 'A 列:客户姓名 installDate = Cells(i, 2).Value 'B 列:安装日期 timePeriod=Cells(i,3).Value 'C 列:时间段 noticeText="客户:"&customerName&vbNewLine&"预约:"&installDate&" "&timePeriod '中间插入换行符 Cells(i, 4).Value = noticeText '把结果写入 D 列Next iEndSub
这里最关键的不是案例本身,而是你要先把这个习惯建立起来:
在 VBA 里,换行不是靠敲回车,而是靠插入换行符。
三、看起来是空的,不一定真的就是空
字符串处理里还有一个特别高频的问题,就是“空”。
很多单元格看起来像没填内容,但程序判断的时候,就是不按预期走。
原因往往不复杂:
它看着空,不代表它真的空。
比如下面这两个就不是一回事:
第一个是空字符串,里面一个字符都没有。
第二个里面其实有内容,只不过内容是空格,所以肉眼不太容易看出来。
再往下一层,有些单元格里还可能夹着前后空格、复制粘贴留下来的空白字符,或者换行符。这种东西平时看表格很难看出来,但一比较、一判断,就开始出问题。
所以字符串处理到后面,你会越来越发现:
很多“看起来不正常”的判断结果,本质上不是逻辑写错了,而是文本本身不干净。
这时候,字符串函数就开始真正派上用场了。
四、别太依赖 VBA 替你“猜意思”
这一点,我觉得也挺重要。
前面我们说过,数字和数字字符串不是一回事。
123 是数字。"123" 是字符串。
这个道理其实不难理解,但一到真正写代码的时候,问题就出来了。因为 VBA 有时候会自己帮你“猜”。
比如下面这种写法:
Cells(2, 4).Value = "120" * 2
你乍一看,会觉得这不是拿字符串去乘数字吗,好像不太合理。
但 VBA 很可能真的给你算出 240。
原因就在于,它会先尝试把 "120" 自动转成数值,再继续参与运算。也就是说,你看到的是字符串,VBA 看到的却可能是“这个东西看起来像数字,那我先把它当数字试试”。
这个特性有时候看着像是在帮忙,但写代码的时候,反而容易让人产生误判。
比如你本来只是想处理文本,结果程序偷偷帮你做了数值转换;或者你本来以为这里一定会报错,结果它居然又给你跑出了一个结果。
这种情况一多,代码就会变得不够稳。
所以我自己在写字符串相关内容的时候,会尽量坚持一个比较死板、但很省事的习惯:
只要是拼文本,就统一用 &。只要是做运算,就尽量保证两边本来就是数字。
不要把“它应该懂我的意思”当成写代码的依据。
尤其是 + 这个符号,在 VBA 里最容易把字符串拼接和数字加法混到一起。你自己以为是在拼内容,程序未必这么理解。
比如下面这两种写法,看着都像在“把东西放到一起”,但实际含义完全不一样:
Range("E2").Value = "120" & "30"
这句是字符串拼接,结果会是:
而下面这句:
Range("E3").Value = "120" + 30
VBA 很可能会先把 "120" 转成数字,再去做加法,最后结果就是:
所以同样是“看起来差不多”的写法,最后跑出来的东西可能完全不是一回事。
这也是为什么,到了字符串这块之后,我基本不太建议再用 + 去拼文本了。
不是说它绝对不能用,而是它太容易让代码的意图变得模糊。你自己今天看得懂,过几天回来改,或者换个人接手,就未必还能一眼看清楚这里到底是在做拼接,还是在做运算。
字符串处理这块,很多时候稳定比省事更重要。
能让程序少猜一点,就尽量让它少猜一点。
五、先讲一个最常用的:Len
Len 用来计算字符串长度。
这个函数看起来很简单,但在实际工作里很常用。比如你想判断一个订单号是不是长度不对,手机号是不是少位数,客户编码是不是格式异常,都可以先用 Len 去做一个初筛。
比如下面这张客户信息表,我想检查手机号长度是不是 11 位。
Sub CheckPhoneLength()Dim i AsLongDim phoneText AsStringFor i = 2To4'逐行检查手机号 phoneText = Cells(i, 2).Value 'B 列:联系电话If Len(phoneText) = 11Then'如果长度等于 11 Cells(i, 3).Value = "格式正常"Else Cells(i, 3).Value = "位数异常"EndIfNext iEndSub
这个函数本身不复杂,但很适合做第一道筛选。
六、清理空格最常用的函数:Trim
如果说有哪个字符串函数是我觉得最该早点用起来的,那基本就是 Trim。
它的作用很直接:
去掉字符串两端多余的空格。
这个在实际工作里真的太常见了。有些数据是复制过来的,有些是别人手填的,有些是从系统里导出来的。看着都差不多,实际上前后藏了空格,一比较就出问题。
比如下面这张部门表,我想判断部门名是不是“销售部”,但 B 列里的内容前后空格不统一。
这里你肉眼看不一定看得出来,但有的单元格前后其实带了空格。
Sub CheckDepartment()Dim i AsLongDim deptText AsStringFor i = 2To4'逐行检查部门名称 deptText = Trim(Cells(i, 2).Value) '先去掉前后空格,再拿来比较If deptText = "销售部"Then Cells(i, 3).Value = "匹配成功"Else Cells(i, 3).Value = "名称异常"EndIfNext iEndSub
这类代码我自己真的经常写。
很多时候,不是数据错了,而是数据脏了。Trim 这种函数,就是专门收拾这种问题的。
顺手补一句:
平时最常用的还是 Trim。
七、批量替换内容,很适合用 Replace
再往下一个特别常用的函数,就是 Replace。
它的作用也很直白:
把字符串里的某段内容替换成新的内容。
这个函数很适合批量统一字段。
比如有的表里写“待跟进”,有的写“未跟进”,还有的写“待联系”,你想把它们统一成一个标准写法,就很适合用 Replace。
下面这个例子里,我想把备注里的“待联系”统一改成“待跟进”。
Sub ReplaceRemarkText()Dim i AsLongDim oldRemark AsStringFor i = 2To4'逐行替换备注内容 oldRemark = Cells(i, 2).Value 'B 列:原备注 Cells(i,3).Value=Replace(oldRemark,"待联系","待跟进") '把指定文字替换掉Next iEndSub
这个函数看起来只是“替换文字”,但在日常表格清洗里特别实用。
比如统一部门写法、统一状态名称、统一电话前缀、统一某个标签的格式,都能用。
八、提取部分文本,最常用的是 Left、Right、Mid
字符串处理再往后,很常见的一类需求就是:
我不是要整段文本,我只想取其中一部分。
这时候最常用的就是这三个函数:
这个在订单号、客户编码、日期片段、部门编号这些场景里特别常见。
1. Left:从左边取几个字符
比如订单编号前两位代表渠道,我想把它单独拆出来。
Sub GetChannelCode()Dim i AsLongDim orderCode AsStringFor i = 2To4'逐行提取渠道代码 orderCode = Cells(i, 1).Value 'A 列:订单编号 Cells(i, 2).Value = Left(orderCode, 2) '从左边取前 2 个字符Next iEndSub
2. Right:从右边取几个字符
比如工号最后 3 位代表个人编号,我只想把末尾 3 位拿出来。
Sub GetEmployeeSuffix()Dim i AsLongDim staffCode AsStringFor i = 2To4'逐行提取末尾编号 staffCode = Cells(i, 1).Value 'A 列:员工工号 Cells(i, 2).Value = Right(staffCode, 3) '从右边取后 3 个字符Next iEndSub
3. Mid:从中间截取一段
Mid 更灵活一点。
它可以指定“从第几个字符开始,取几个字符”。
比如订单号 WX240518,我想取中间的 2405 这一段。
Sub GetMiddlePart()Dim codeText AsString codeText = "WX240518" Range("D2").Value = Mid(codeText, 3, 4) '从第 3 个字符开始,取 4 个字符EndSub
这三个函数我自己用得非常多。
因为现实里的很多文本字段,本身就是“拼起来”的。既然能拼,自然也就经常需要拆。
九、大小写统一,也很常见
有时候字符串出问题,不是空格,也不是格式,而是大小写不统一。
比如币种、部门编码、产品代号这些,有人写大写,有人写小写,比较的时候就容易对不上。
这时候可以用:
比如你想先把币种统一转成大写,再去判断:
Sub CheckCurrency()Dim curText AsString curText = UCase(Range("B2").Value) '先统一转成大写If curText = "USD"Then Range("C2").Value = "美元"EndIfEndSub
这个思路其实挺实用:
先把格式统一,再做判断。
这样会稳很多。
十、字符串拼接,本质上是在按模板生成文本
前面讲的这些函数,最终还是要落到实际工作里。
而字符串在工作里最常见的用途,还是拼接。
只不过拼接到后面,你会发现它已经不是“把几个内容连起来”这么简单了,而是在按模板批量生成文案。
比如通知、备注、说明、回访内容、发货提示,这些都属于这一类。
下面这个例子,就是一个很典型的场景:根据客户名、产品名和预约时间,自动生成一段回访提醒。
Sub BuildFollowText()Dim i AsLongDim customerName AsStringDim productName AsStringDim followTime AsStringDim followText AsStringFor i = 2To4'逐行生成回访提醒 customerName = Trim(Cells(i, 1).Value) 'A 列:客户名,顺手去掉前后空格 productName = Trim(Cells(i, 2).Value) 'B 列:产品名称 followTime=Cells(i,3).Value 'C 列:回访时间 followText=customerName&",您好,您预约的“"&productName&"”回访时间为 "&followTime&",请提前做好安排。"'按固定模板拼接文案 Cells(i, 4).Value = followText '把结果写入 D 列Next iEndSub
这里你会发现,前面讲过的内容其实都串起来了:
- 如果后面还要拆字段,就可以再配合
Left、Right、Mid
字符串这块,真正用顺以后,很多文本类自动化就会开始变得很自然。
十一、最后收一下这篇文章的重点
这一篇其实做了两件事。
第一件事,是把字符串里几个特别容易在实操里踩坑的地方,再往前补了一步:
第二件事,是把几个真正高频的字符串函数合到一起,统一讲清楚了:
这些函数单个看都不复杂,但一旦结合到表格清洗、字段提取、备注生成、通知拼接这些场景里,就会特别好用。
相信看到这里,大家会觉得这些函数特别熟悉。确实,这里面用到的很多函数,跟 Excel 公式里的函数都是差不多的。
到这里我还想说一点,其实我们在 VBA 里面也可以直接使用 Excel 函数。这里暂且不说,等到后面用上的时候,我们再单独拿出来讲。