斗破苍穹文字页游php_Word VBA文字提取(2)——用 Find 对象帮苏文茂先生 “批三国”...

大家好!上一周我们使用Word VBA统计了《斗破苍穹》中“恐怖如斯”的出现频率,顺便为天蚕土豆正了名。不过正如文末所说的,这个代码的运行速度并不很快,而且写起来多少还点繁琐。所以今天杨老师再为大家介绍一个新的查找办法——用VBA调用Word自带的搜索功能。不过今天使用的案例需要更换一下——我们查一查《三国演义》里都有哪些回目标题里出现过哪些“三”字。

060aef3105ef38f32fbf1ee685079661.png

熟悉相声的朋友马上就会猜到,这个例子是来自于7岁开始读《三国》、9岁在大学开讲《出师表》的神童学者——苏文茂先生的《批三国》。苏先生举了很多例子试图证明:这部书叫“三”国的原因,在于它的目录中带“三”字的标题多。所以我们今天就帮苏先生查一下,看看他的例子里有没有遗漏某些“三”字标题。

e7b9ba130a547f4dad2dbba617bd784a.png

言归正传。在《全民一起VBA 实战篇》的专题一里面,我们曾经用了很多节课程详细介绍Excel VBA中调用内置搜索功能(也就是Find)的方法。学习过这些内容的同学一定会对它的简洁、速度和功能印象深刻。而Word VBA中也是一样,只要搞清楚一个名为Find 的对象,那么凡是Word搜索框所支持的查找功能,VBA代码中都可以直接调用,而且速度奇快。

怎样使用Find对象呢?首先我们知道,Word中也有Range对象,代表文档中的某一部分内容及其格式。比如上篇文章里使用的Document.Content ,就可以把这个文档中的全部内容作为一个Range对象交给我们处理。

而在Word中,Range对象有一个属性叫做Find。这个Range.Find也是一个对象,有自己的属性和方法(就像Range的字体对象Range.Font 一样,可以进一步设置Range.Font.Size等属性)。顾名思义,Range.Find对象就是一个“搜索器”,只要告诉它欲搜索的内容以及各种选项,然后让它执行搜索方法,它就会在这个Range中查找目标。

所以我们如果想在一个Word文档的全文中找到第一个“三”字,只需要写出下面代码即可:

1955c2cd24a47276708e34801597632b.png

在这段代码里,变量 指向了Content的Find属性。由于Content是一个代表全文的Range对象,所以这个 f 就是一个“在全文中执行查找的搜索器”。

然后,f.Text = “三”  这行代码将Find对象的Text属性设置为“三”。而Find对象的Text属性代表的就是“欲查内容”,将它设置为什么,下一步这个搜索器就会搜索什么。所以接下来,我们就可以调用Find对象最重要的方法——Execute()——执行搜索。

Execute()方法的功能就是“查找下一个”。如果找到则返回True,反之如果直到该Range结束都未能找到目标,就返回一个False。因此我们直接将这个Execute放在了 If 语句里,一旦找到目标就执行If里面的分支、并用消息框显示 “找到一个!” 。

搞清楚怎样找到一个结果,就能搞清楚怎样找到所有结果。道理很简单:做一个循环,如果某次搜索之后,Find.Execute 能够返回一个True,就继续循环、再次调用Find.Execute;反之如果 Find.Execute 返回一个False,则说明已经无法再找到更多目标,于是退出循环。按照这个思路,程序可以改写如下(新程序里不再使用消息框输出结果,而是将结果写到新建的Word文档中,方法与上一篇文章完全相同):

134b08773e66ff5a8895dd66bf49791a.png

这里在保存文档时,我们使用了 Find.Parent,它的具体含义可以说很不好理解,甚至可以说是Word VBA中最让人困惑的Range用法之一,所以杨老师后面会在知乎上单独开一篇文章讲解它的含义。不过这并不影响大家日常的使用,因为只要知道 Find.Parent 就是一个Range对象,指向“刚刚被找到的内容” 就可以了。所以 Find.Parent.Paragraphs(1) 就是被找到的内容所在的段落,而 Find.Parent.Paragraphs(1) .Range.Text 就是这个段落中的文字内容。

OK,如果大家现在回头去看看上一篇文章里的程序,会发现使用Find以后,代码简洁了许多!而且如果用这个代码到《斗破苍穹》里面去找“恐怖如斯”,你会发现它的执行速度显著高于上篇文章那种 “逐段检查” 的程序。

不过仔细观察运行结果,我们却发现一个问题:目录里很多标题因为序号里面有“三”,比如 “第三回”、“第三十六回”等,结果也被收了进来。更郁闷的是,因为“第三十三回”里面有两个三,所以还被收录了两次!

0cbd21dfeb2b5e301eddf6839570419e.png

怎样能够只识别标题里的“三”、自动无视 “第...三...回” 这种格式呢?学过《全民一起VBA  提高篇》的朋友可能马上想到了正则表达式。不过很遗憾,因为Word居然敢冒天下之大不韪——不支持正则表达式(我们在《提高篇》里讲过),所以 Find 方法里不能使用正则式,而是要改用微软自家的“WildCard通配符系统 (在《提高篇》讲解正则表达式时提到)。

关于 WildCard ,我们下期文章会给大家详细介绍(即使不使用VBA也可以使用WildCard,而且确实很有用)。这里我们只要知道:Find 对象有一个属性叫做 MatchWildcards ,只要把它设置为True,就可以在 Find.Text 中用通配符指定搜索规则,功能类似于正则表达式。所以把程序改成下面的样子,就能排除 “第三” 或 "三回" 的字样,得到我们预期的结果。

36cf45f0d8843f8609a71921acd40367.png

程序运行结果如下。可以看到,我们一共找出了15个带有“三”字的标题。而相声 “批三国” (苏文茂/朱相臣 版)里只提到了9个,上面红色标记出来的就是其中“遗漏”的内容。

0161c889d62e50128b5d2f9e14b0fdd6.png

本文只是粗略介绍了Find的最基本用法,事实上Find支持几十个属性和方法,对应Word中查找对话框里面的全部选项(就像《实战篇》介绍的 Excel Find 一样),因此功能极其强大。有兴趣的同学只要参考《实战篇》讲解的Excel VBA,稍查文档就能掌握。

而对于本文提到的Word通配符 WildCards,可以说对所有常年使用Word的人士(无论是否使用VBA)都非常有用,可以大大提高查找、替换的效率。所以下篇文章中我们就介绍一下这个技术。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值