当前位置: 首页 > 审计之窗 > 审计信息化

利用VBA正则表达式匹配文本中的数字
时间:2023-01-11 10:08:08  作者:   来源: 包头市审计局  点击量:

在审计工作中,可能会面对需要提取文本中数字的场景,尤其数据行数较多时,利用VBA正则表达式将会大幅度提升工作效率。正则表达式的作用是检索、替换那些符合某个规则的文本,故又称之为“规则表达式”。本文意图探讨在电子表格中使用正则表达式来获取单元格里文本中的数字,VBA作为VB的子集,同样支持正则表达式的功能,在本文中,VBA正则表达式和VB正则表达式的概念是等同的。本文将以此例展开探讨表中某列单元格内容形式结构类似为“差旅费500.16/ 2人”,我们可以获取其中“500.16”和“2”这两个数字,用来进行数学运算。

一、编写“正则表达式”的规则

这是为了确定文本中数字出现时的规则。例如500.16”,它有如下规则(特征):一是首位数字不为0,二是具有小数点和小数,三是小数部分最后一位不为0。同时,对于“2”这个自然数,它只是单个整数而已,没有小数位。那么现在需要制定一种规则,能够同时满足以上所有要求,且无需关注每一个数字的整数部分和小数部分到底有几位。正则表达式是这样的表示的:普通字符+元字符。普通字符就是大小写字母、数字、中文等,比如[1-9]表示19中任意一个数字,[a-z]表示从az的任意一个小写字母。而元字符看似是特殊符号,其实它另有含义。元字符有很多种,为便于理解接纳此概念,本文中只列举本案例所需元字符。

例如反斜杠后面一个d\d)表示一个数字字符,等价于[0-9]

例如一个星号(*)表示匹配前面的内容任意次。

例如一个点(.)表示匹配任意一个普通字符。

例如一个反斜杠(\)表示将其后面的字符只表达其原本的意思,比如反斜杠后面一个点(\.)只表示普通字符点(.)的本身。

例如一个问号(?)表示匹配前面的内容0次或一次。

例如一个竖线(|)表示或运算,比如(x|y)表示要么匹配x,要么匹配y

例如可以使用成对儿的括号“()”将一个规则与别的规则区分开来。

综上所述,我们可以构造出本例所需正则表达式的规则:([1-9]\d*(\.\d*[1-9])?) | ([0]\.\d*[1-9])。它表示:数字的第一位是不为0的整数([1-9]);第一位数的后面有任意位个数(\d*);该数的小数点后可以有任意位数(\.\d*);且小数部分最后一位是不为0的整数([1-9]);但该数字只能有0个或1个小数部分,所以要将小数部分的规则用括号括起来并在后面加上问号“(\.\d*[1-9])?”;亦或者(|);匹配一个以0开头([0])小于1的小数,该数的小数点后可以有任意位数(\.\d*);且小数部分最后一位是不为0的整数([1-9]);

二、在VBA中应用正则表达式

第一步需要打开EXCEL,点击“文件”→“选项”→“自定义选项卡”将“开发工具”选项卡置顶于最上方菜单栏,在“开发工具”选项卡打开VB编辑器,从编辑器最上方菜单栏点击“工具”→“引用”,找到“Microsoft VBScript Regular Expressions 5.5”,将其复选框打勾,然后点击确定,此时VBA便已经引用了VB正则表达式的功能。

VB正则表达式有四种属性,在本案列中只需要设置其中两种:GlobalPatternGlobal是一个“非真即假”的二元对立类型的值,当Global等于True(真)时,正则表达式将会匹配整个文本中的内容,当Global等于False(假)时,则只匹配第一个结果,在本案例中需要将Global设置为True,以便同时匹配“500.16”和“2”这两个数字。而Pattern是一个字符串,用来存储我们定义好的正则表达式规则,即Pattern = ([1-9]\d*(\.\d*[1-9])?) | ([0]\.\d*[1-9])”。

VB正则表达式有三种功能:判断是否成功匹配、替换目标字符、匹配目标字符。在本案例中,我们只需要用到“匹配目标字符”这个功能,即Execute(源文本),该功能把在源文本中匹配到的结果存放到一个集合当中,且每个匹配到的结果都会自动标上索引,同时还会获取匹配结果在源文本中的起始位置、长度。

接下来,便可以在代码中定义一个正则表达式,设置好GlobalPattern属性,依照Pattern中存储的规则,利用Execute(源文本)功能去匹配整个文本。示例代码和结果如下:

三、总结

本文描述了一个简单案例,如果进一步结合VBA常用方法,可以对工作簿、工作表、单元格进行批量处理,以达到工作人员“解放劳动力,提高生产力”的效果。虽然本文所给出的正则表达式规则已能够处理大多常见数字,但仍有缺陷,比如无法匹配负数。需要注意的是,针对每一种匹配场景,正则表达式规则的编写并不是固定不变的,可以根据自身理解去编写,但务必做到逻辑上的严谨有序。