VB开发中String.Contains无法匹配vbTab拼接Chr内容是代码问题还是bug?
异常原因结论
这不是VB平台的产品bug,属于代码编写时对开发环境规则不熟悉导致的逻辑问题
核心问题拆解
- 出现匹配失效的根本原因是对VBA/VB6环境下
Chr()函数的行为认知偏差:
在中文Windows系统默认的936(GBK)代码页环境下,Chr(n)函数会按照系统当前ANSI代码页规则映射字符,凡是传入的编码值落在GBK双字节字符首字节范围(0x81-0xFE,对应十进制129-254)时,函数会自动生成占2个长度的双字节字符,不会返回单个长度的匹配目标。 - 对应到这段代码的实际执行过程:
代码中用到的Chr(149)、Chr(176)、Chr(183)、Chr(187)对应的十进制值,全部落在GBK双字节首字节的取值范围内,每一个Chr()调用的返回值长度都是2而非1。最终拼接出的vbTab & Chr(n)匹配目标,实际长度为3(1个字符的vbTab + 2个字符的Chr(n)结果),和待检测文本里长度为2的「制表符+单个项目符号」序列完全不匹配,自然会返回匹配失败。 - 校验逻辑的误导性说明:
开发者通过Asc(Mid(Txt,2,1))拿到183的校验值,只能说明待检测文本第二位的ANSI编码是183,但这个校验和代码中Chr(183)生成的字符串本身没有等价性——因为在当前代码页下,Chr(183)根本就不是单个长度的183编码对应的字符,而是一个双字节拼接的结果。
修正方案
- 替换区域映射型的
Chr()函数为ChrW()函数:ChrW()会直接按照Unicode固定编码规则返回单长度字符,不受系统ANSI代码页的映射规则影响,从根源上避免双字节字符拼接的问题。 - 修正后的代码示例:
Public Function GetBullet(Txt As String) As String GetBullet = "" If Txt.Contains(vbTab & ChrW(149)) Then GetBullet = ChrW(149) If Txt.Contains(vbTab & ChrW(176)) Then GetBullet = ChrW(176) If Txt.Contains(vbTab & ChrW(183)) Then GetBullet = ChrW(183) If Txt.Contains(vbTab & ChrW(187)) Then GetBullet = ChrW(187) End Function
- 额外校验提示:匹配前可通过
Len(vbTab & ChrW(183))确认匹配目标长度为2,如果长度大于2则说明存在代码页映射偏差,需要调整字符生成方式。
内容的提问来源于stack exchange,提问作者Michael Duc
相关产品推荐
相关产品推荐

