在VBA中结合正则表达式和查找功能给文档添加交叉连接

VBA中搜索文本有两种方式可用,一种是利用Range.Find对象(更常见的形式可能是Selection.FindSelectionRange的子类,Selection.Find其实就是特殊的Range.Find),另一种方法是利用正则表达式,但是,这两种方法各有各的问题。
Range.Find对象的问题是正则表达式功能太差。尽管可以通过将MatchWildcards 属性设置为True来使用通配符,但通配符表达式并不完全兼容常用的正则表达式语法,而且不同版本的VBA支持的通配符表达式语法还不一样,例如,我在Word2013中使用通配符表达式(#\d+)|([①-⑨]),它居然因为使用了|操作符,就不能得到预期的结果。
正则表达式的问题则是无法准确定位匹配项在文档中的位置。尽管理论上可以用下面这样的方法定位到匹配项,但是实际运行就会发现除了第一个能定位到,后面的全部会出错:

Dim i As Long
Dim rng As Word.Range
For i = 0 To matchColl.Count - 1' 根据匹配项的位置信息创建Word.Range对象Set rng = doc.Range(matchColl(i).FirstIndex + 1, matchColl(i).FirstIndex + matchColl(i).Length + 1)rng.Select ' 选择第i个匹配项进行其他处理,如打印匹配项内容等    
Next i

为了各取所长避其所短,比较好的思路是将二者结合,先用正则表达式查找匹配项,再用Range.Find来定位匹配项。下面就用这个思路在Word文档主体内容中的注释引用和注释内容中的注释编号之间建立交叉连接来进行一个实践。
我们有这样一个文档:
在这里插入图片描述
要在这个文档中建立如图所描述的交叉链接,需要在主体内容的注释引用和注释区的注释编号位置分别插入书签以及连接到对方的超链接。当然,这里的查找内容用简单的通配符表达式也可以完成任务,但是如果编辑过程中出现失误,导致部分注释引用被替换成了别的样式,重新修复的时候就不得不用到|操作符,这时候Range.Find对象就不见得能按预期完成任务了。
下面的宏要求先在文档中选择主体内容,然后运行宏对主体内容进行处理,处理完后再选择注释中的内容,再次运行宏处理注释,交叉链接就建立完毕。我将插入书签和链接的功能写成了如下函数:

Function DealCrossLink(searchRange As Range, regStr As String, chapter As Integer, _Optional useSelection As Boolean = True, Optional contentStr As String = "cont_c", _Optional commentStr As String = "comm_c", Optional formatStr As String = "000", _Optional ignoreCase As Boolean = True)''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 参数说明:'   searchRange:搜索范围'   regStr:应匹配的正则表达式'   chapter:当前书签的章节序号'   useSelection:插入超链接时显示的文本是否用在文档中选择的文本,默认为True,否则显示#加阿拉伯数字'   contentStr,commentStr:区分主体内容区和注释区的字符串'   formatStr:注释引用序数扩充到固定长度所用的格式字符串,默认扩充为至少3字符("000")'   ignoreCase:匹配内容时是否忽略大小写,默认为True'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''Dim regEx As RegExpDim match, matches As ObjectDim tmpRange As RangeDim i%, serial$, hyperText$Set regEx = CreateObject("VBScript.RegExp")With regEx.Global = True.ignoreCase = ignoreCase.Pattern = regStr 'End WithSet matches = regEx.Execute(searchRange.Text) ' 在搜索范围内执行匹配操作searchRange.Collapse Direction:=wdCollapseStart ' 将搜搜范围折叠到开头For Each match In matchesSet tmpRange = searchRangeWith tmpRange.Find.Text = match.Value.Forward = True.Wrap = 1 ' wdFindContinue.Execute ' 执行查找,定位匹配项的位置If tmpRange.Find.found Then' 注释引用和注释区注释编号设置为上标tmpRange.Font.Superscript = -1i = i + 1 ' 计算当前书签序号,用于书签命名serial = "_" & Format(i, formatStr) ' 将序号扩充为等长字符串,默认长度为3("000")With ActiveDocument.Bookmarks.Add Range:=tmpRange, Name:=contentStr & chapter & serial.DefaultSorting = wdSortByName.ShowHidden = FalseEnd WithIf useSelection Then hyperText = tmpRange.Text Else hyperText = "#" & iActiveDocument.Hyperlinks.Add Anchor:=tmpRange, Address:="", _SubAddress:=commentStr & chapter & serial, ScreenTip:="", TextToDisplay:=hyperText' 调整搜索范围起始位置,准备定位下一个匹配项searchRange.SetRange Start:=tmpRange.End, End:=searchRange.EndEnd IfEnd WithNext matchEnd Function

上面的代码也展示了在选定区域中进行查找的方法。
调用上述函数的代码如下:

Sub test()Dim chapter%    chapter = 1' 处理主体内容中的书签和超链接,超链接文本用文档中的匹配文本DealCrossLink Selection.Range, regStr, chapter' 处理注释内容中的书签和超链接,超链接文本用文档中的匹配文本
'    DealCrossLink Selection.Range, regStr, chapter, contentStr:="comm_c", commentStr:="cont_c"' 处理主体内容中的书签和超链接,超链接文本用#号连接阿拉伯数字编号
'	DealCrossLink Selection.Range, regStr, chapter,False
'    ' 处理注释内容中的书签和超链接,超链接文本用#号连接阿拉伯数字编号
'    DealCrossLink Selection.Range, regStr, chapter, contentStr:="comm_c", commentStr:="cont_c", FalseEnd Sub

可以根据需要,将以上代码中最后四行具体调用函数的语句选择一条执行。
下面是选择主体内容后执行第一条语句的结果:
在这里插入图片描述
下面是选择注释内容执行第四条语句的结果:
在这里插入图片描述
主体内容中的“①”与注释内容中的“#1”之间成功建立起了交叉链接,其它编号也是如此。
如果觉得每次选一个段落有点麻烦,可以考虑在诗标题和校注前先插入连续型分节符(可参阅文档目录、页眉和文档章节标题之间插入相互链接的最佳实践中的过程Sub 指定级别标题前插入分节符()),然后遍历档中的所有节,各节第一段文本为“【校注】”的即为注释区,否则当做主体内容区,然后在调用DealCrossLink函数时将section.Range取代Selection.Range作为第一个参数传入,即可无需选择内容建立全文的交叉链接。示例代码如下:

Sub 全文主体内容的注释引用与注释区注释序号之间建立交叉链接()Dim aSec As Section, chapter%, regStr$, addChapter As Boolean'是否递增章节序号。只有处理完了一个注释区后才递增章节号,以确保对应的主体内容和注释章节号相同addChapter = TrueregStr = "〔\d+〕"For Each aSec In ActiveDocument.SectionsIf addChapter Then chapter = chapter + 1If Left(aSec.Range.Paragraphs(1).Range.Text, 4) = "【注释】" ThenDealCrossLink aSec.Range, regStr, chapter, contentStr:="comm_c", commentStr:="cont_c"addChapter = TrueElseDealCrossLink aSec.Range, regStr, chapteraddChapter = FalseEnd IfNext
End Sub

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/64833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AW36518芯片手册解读(3)

接前一篇文章:AW36518芯片手册解读(2) 二、详述 3. 功能描述 (1)上电复位 当电源电压VIN降至预定义电压VPOR(典型值为2.0V)以下时,该设备会产生复位信号以执行上电复位操作&#x…

【mysql】唯一性约束unique

文章目录 唯一性约束1. 作用2. 关键字3. 特点4. 添加唯一约束5. 关于复合唯一约束 唯一性约束 1. 作用 用来限制某个字段/某列的值不能重复。 2. 关键字 UNIQUE3. 特点 同一个表可以有多个唯一约束。唯一约束可以是某一个列的值唯一,也可以多个列组合的值唯一。…

实操给桌面机器人加上超拟人音色

前面我们讲了怎么用CSK6大模型开发板做一个桌面机器人充当AI语音助理,近期上线超拟人方案,不仅大模型语音最快可以1秒内回复,还可以让我们的桌面机器人使用超拟人音色、具备声纹识别等能力,本文以csk6大模型开发板为例实操怎么把超…

SYD881X RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟

RTC定时器事件在调用timeAppClockSet后会出现比较大的延迟 这里RTC做了两个定时器一个是12秒,一个是185秒: #define RTCEVT_NUM ((uint8_t) 0x02)//当前定时器事件数#define RTCEVT_12S ((uint32_t) 0x0000002)//定时器1s事件 /*整分钟定时器事件,因为其余的…

LearnOpenGL学习(碰撞检测,粒子)

完整代码见:zaizai77/OpenGLTo2DGame: 基于OpenGL制作2D游戏 物体本身的数据来检测碰撞会很复杂,一半使用重叠在物体上的更简单的外形来检测。 AABB - AABB 碰撞 AABB代表的是轴对齐碰撞箱(Axis-aligned Bounding Box),碰撞箱是指与场景基…

SwinTransformer 改进:添加SelfAttention自注意力层

目录 1. SelfAttention自注意力层 2. SwinTransformer SelfAttention 3. 代码 1. SelfAttention自注意力层 Self-Attention自注意力层是一种在神经网络中用于处理序列数据的注意力机制。它通过对输入序列中的不同位置进行关注,来计算每个位置与其他位置的关联程…

c++ ------语句

一、简单语句 简单语句是C中最基本的语句单元,通常以分号(;)结尾,用于执行一个单一的操作。常见的简单语句类型有: 表达式语句:由一个表达式后面加上分号构成,用于计算表达式的值或者执行具有…

【他山之石】The SVG path Syntax: An Illustrated Guide:SVG 中的 path 语法图解指南

写在前面 本文为我的自学精译专栏《CSS in Depth 2》第 086 篇文章、在介绍 CSS 的 clip-path 属性的用法时作者提到的一篇延伸阅读材料,以图文并茂的形式系统梳理了 SVG path 属性的方方面面。其中最为精彩的是文中列举的大量使用案例。为了方便查找,特…

小型 Vue 项目,该不该用 Pinia 、Vuex呢?

说到 Vue3 的状态管理,我们会第一时间想到 Pinia、Vuex,但是经过很长一段时间的 Vue3 项目开发,我逐渐发现,我们真的有必要用 Pinia、Vuex 这类的状态管理工具吗? 带着这样的疑惑,我首先是想知道一下 Pini…

c4d动画怎么导出mp4视频,c4d动画视频格式设置

宝子们,今天来给大家讲讲 C4D 咋导出mp4视频的方法。通过用图文教程的形式给大家展示得明明白白的,让你能轻松理解和掌握,不管是理论基础,还是实际操作和技能技巧,都能学到,快速入门然后提升自己哦。 c4d动…

EfficienetAD异常值检测之瓷砖表面缺陷检测(免费下载测试数据集和模型)

背景 当今制造业蓬勃发展,产品质量把控至关重要。从精密电子元件到大型工业板材,表面缺陷哪怕细微,都可能引发性能故障或外观瑕疵。人工目视检测耗时费力且易漏检,已无法适应高速生产线节奏。在此背景下,表面缺陷异常…

将Minio设置为Django的默认Storage(django-storages)

这里写自定义目录标题 前置说明静态文件收集静态文件 使用django-storages来使Django集成Minio安装依赖settings.py测试收集静态文件测试媒体文件 前置说明 静态文件 Django默认的Storage是本地,项目中的CSS、图片、JS都是静态文件。一般会将静态文件放到一个单独…

Redis生产实践中相关疑问记录

1. Redis相关疑问 1.1. redis内存使用率100% 就等同于redis不可用吗? 正常使用情况下,不是。 redis有【缓存淘汰机制】,Redis 在内存使用率达到 100% 时不会直接崩溃。相反,它依赖内存淘汰策略来释放内存,确保系统的…

量化交易——RSI策略(vectorbt实现)

本文为通过vectorbt(以下简称vbt)实现量化交易系列第一篇文章,通过使用vbt实现RSI策略从而熟悉其代码框架。 关于本文所使用数据的说明 由于vbt官方文档提供的入门案例使用的数据是通过其内置的yfinance包获取,在国内无法直接访…

本地摄像头视频流在html中打开

1.准备ffmpeg 和(rtsp-simple-server srs搭建流媒体服务器)视频服务器. 2.解压视频流服务器修改配置文件mediamtx.yml ,hlsAlwaysRemux: yes 3.双击运行服务器。 4,安装ffmpeg ,添加到环境变量。 5.查询本机设备列表 ffmpeg -list_devices true -f dshow -i d…

unipp中使用阿里图标,以及闭坑指南

-----------------------------------------------------点赞收藏才是更新的动力------------------------------------------------- unipp中使用阿里图标 官网下载图标在项目中引入使用注意事项 官网下载图标 进入阿里图标网站 将需要下载的图标添加到购物车中 2. 直接下载…

设计模式の享元模板代理模式

文章目录 前言一、享元模式二、模板方法模式三、代理模式3.1、静态代理3.2、JDK动态代理3.3、Cglib动态代理3.4、小结 前言 本篇是关于设计模式中享元模式、模板模式、以及代理模式的学习笔记。 一、享元模式 享元模式是一种结构型设计模式,目的是为了相似对象的复用…

flink实现复杂kafka数据读取

接上文:一文说清flink从编码到部署上线 环境说明:MySQL:5.7;flink:1.14.0;hadoop:3.0.0;操作系统:CentOS 7.6;JDK:1.8.0_401。 常见的文章中&…

越疆科技营收增速放缓:毛利率未恢复,持续亏损下销售费用偏高

《港湾商业观察》施子夫 12月13日,深圳市越疆科技股份有限公司(以下简称,越疆科技,02432.HK)发布全球发售公告,公司计划全球发售4000万股股份,其中3800万股国际发售,200万股香港公开…

datasets 笔记:加载数据集(基本操作)

参考了huggingface的教程 1 了解数据集基本信息( load_dataset_builder) 在下载数据集之前,通常先快速了解数据集的基本信息会很有帮助。数据集的信息存储在 DatasetInfo 中,可能包括数据集描述、特征和数据集大小等信息。&…