当前位置: 首页 > article >正文

在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 String, contentStr As String, commentStr As String, _
            Optional ignoreCase As Boolean = True, Optional useSelection As Boolean = True)
            
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    ' 参数说明:
    '   searchRange:搜索范围
    '   regStr:应匹配的正则表达式
    '   chapter,contentStr,commentStr:用于命名书签的标志字符串
    '   ignoreCase:匹配内容时是否忽略大小写,默认为True
    '   useSelection:插入超链接时显示的文本是否用在文档中选择的文本,默认为True,否则显示#加阿拉伯数字
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    
    Dim regEx As RegExp
    Dim match, matches As Object
    Dim tmpRange As Range
    Dim i%, serial$, hyperText$
    Set regEx = CreateObject("VBScript.RegExp")
    With regEx
        .Global = True
        .ignoreCase = ignoreCase
        .Pattern = regStr '
    End With
    
    Set matches = regEx.Execute(searchRange.Text) ' 在搜索范围内执行匹配操作

    searchRange.Collapse Direction:=wdCollapseStart ' 将搜搜范围折叠到开头
    
    For Each match In matches
        Set tmpRange = searchRange
        With tmpRange.Find
            .Text = match.Value
            .Forward = True
            .Wrap = 1 ' wdFindContinue
            .Execute ' 执行查找,定位匹配项的位置
            If tmpRange.Find.found Then
                i = i + 1 ' 计数,用于书签命名
                serial = Trim(Str(i))
                With ActiveDocument.Bookmarks
                    .Add Range:=tmpRange, Name:=chapter & contentStr & serial
                    .DefaultSorting = wdSortByName
                    .ShowHidden = False
                End With
                If useSelection Then hyperText = tmpRange.Text Else hyperText = "#" & serial
                ActiveDocument.Hyperlinks.Add Anchor:=tmpRange, Address:="", _
                    SubAddress:=chapter & commentStr & serial, ScreenTip:="", TextToDisplay:=hyperText
                ' 调整搜索范围起始位置,准备定位下一个匹配项
                searchRange.SetRange start:=tmpRange.End, End:=searchRange.End
                searchRange.Collapse Direction:=wdCollapseStart
            End If
        End With
    Next match
    
End Function

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

Sub test()
    Dim searchStr$, chapter$, contentStr$, commentStr$
    searchStr = "[①-⑨]"
    chapter = "c001"
    contentStr = "_cont_"
    commentStr = "_comm_"
    ' 处理主体内容中的书签和超链接,超链接文本用文档中的匹配文本
    DealCrossLink Selection.Range, searchStr, chapter, contentStr, commentStr
'    ' 处理注释内容中的书签和超链接,超链接文本用文档中的匹配文本
'    DealCrossLink Selection.Range, searchStr, chapter, commentStr, contentStr
'    ' 处理主体内容中的书签和超链接,超链接文本用#号连接阿拉伯数字编号
'    DealCrossLink Selection.Range, searchStr, chapter, commentStr, contentStr, , False
'    ' 处理注释内容中的书签和超链接,超链接文本用#号连接阿拉伯数字编号
'    DealCrossLink Selection.Range, searchStr, chapter, commentStr, contentStr, , False

End Sub

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


http://www.kler.cn/a/445666.html

相关文章:

  • 网络安全概论——防火墙原理与设计
  • 南城云趣:智能云平台,杜绝电动车充电安全隐患
  • 相机内外参知识
  • 【信息系统项目管理师】高分论文:论信息系统项目的进度管理(人力资源管理系统)
  • 穷举vs暴搜vs深搜vs回溯vs剪枝系列一>找出所有子集的异或总和再求和
  • 容器化技术全面解析:Docker 与 Containerd 的深入解读
  • css 动画实现从中间到两边亮度逐渐变暗的流水灯效果
  • DNS 服务器是什么?有什么作用
  • MQTT入门:在Spring Boot中建立连接及测试
  • 面试题整理10----k8s集群架构是什么
  • 数据库管理系统——数据库设计
  • 【Linux】基础IO------理解文件系统(inode)
  • Java 面经之 Kafka
  • MATLAB常用颜色RGB汇总
  • 低空无人机产教融合技术详解
  • docker启动nginx并部署前端
  • 打通全网SEO优化:提高百度、B站、抖音等平台搜索排名
  • 英伟达 - 笔记
  • 分布式系统架构4:容错设计模式
  • [element-ui] e-image 和e-table一起使用显示问题
  • 在 Unity 6 中使用APV为您的世界创建全局照明的新方法(二)
  • 【Linux系统编程】:信号(1)——前置知识,了解信号
  • BigBlueButton视频会议 vs 钉钉视频会议系统的详细对比
  • Ubuntu 20.04 卸载和安装 MySQL8.0
  • 项目实操:windows批处理拉取git库和处理目录、文件
  • [CSP-S 2024] 超速检测 题解