在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 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
                ' 注释引用和注释区注释编号设置为上标
                tmpRange.Font.Superscript = -1
                i = i + 1 ' 计算当前书签序号,用于书签命名
                serial = "_" & Format(i, formatStr) ' 将序号扩充为等长字符串,默认长度为3("000")
                With ActiveDocument.Bookmarks
                    .Add Range:=tmpRange, Name:=contentStr & chapter & serial
                    .DefaultSorting = wdSortByName
                    .ShowHidden = False
                End With
                If useSelection Then hyperText = tmpRange.Text Else hyperText = "#" & i
                ActiveDocument.Hyperlinks.Add Anchor:=tmpRange, Address:="", _
                    SubAddress:=commentStr & chapter & serial, ScreenTip:="", TextToDisplay:=hyperText
                ' 调整搜索范围起始位置,准备定位下一个匹配项
                searchRange.SetRange Start:=tmpRange.End, End:=searchRange.End
            End If
        End With
    Next match
    
End 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", False

End Sub

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大腾智能CAD:国产云原生三维设计新选择

在快速发展的工业设计领域,CAD软件已成为不可或缺的核心工具。它通过强大的建模、分析、优化等功能,不仅显著提升了设计效率与精度,还促进了设计思维的创新与拓展,为产品从概念构想到实体制造的全过程提供了强有力的技术支持。然而…

实现Python将csv数据导入到Neo4j

目录 一、获取数据集 1.1 获取数据集 1.2 以“记事本”方式打开文件 1.3 另存为“UTF-8”格式文件 1.4 选择“是” 二、 打开Neo4j并运行 2.1 创建新的Neo4j数据库 2.2 分别设置数据库名和密码 ​编辑 2.3 启动Neo4j数据库 2.4 打开Neo4j数据库 2.5 运行查看该数据库…

MySQL知识汇总(二):select

select语句 -- select语句 select 字段 from 表 -- 查询全部信息 select * from 表 SELECT * FROM student2 -- 查询指定字段 select name from 表 SELECT name FROM student2 -- 起别名 给查询结果用 AS 起个其他的名字,可以是字段也可以是表 SELECT name AS 名字 …

Restaurants WebAPI(二)——DTO/CQRS

文章目录 项目地址一、DTO1.1 创建Restaurant的Dto1.2 修改之前未使用Dto的接口1.2.1 修改GetRestaurantByIdUseCase1.2.2 修改IGetRestaurantByIdUseCase接口1.2.3 再次请求接口1.3 显示Dish List1.3.1创建DishDto1.3.2 在RestaurantDto里添加DishDto1.3.3 使用Include添加Dis…

c++--------c++概念

定义与起源 C是一种高级编程语言,它是C语言的扩展。C由Bjarne Stroustrup在20世纪80年代初开发,最初被称为“C with Classes”。其设计目的是在保持C语言高效性的同时,增加面向对象编程(OOP)的特性。例如,…

面向对象设计过程的理解和实践

在软件开发的世界里,面向对象设计(Object-Oriented Design,简称OOD)是一项至关重要的技术。它不仅帮助我们更好地将现实世界的问题转化为软件系统中的对象,还确保这些对象之间能够高效地协同工作,共同实现系…

游泳溺水识别数据集,对9984张原始图片进行YOLO,COCO JSON, VOC XML 格式的标注,平均识别率在91.7%以上

游泳溺水识别数据集: 对9984张原始图片进行YOLO,COCO JSON, VOC XML 格式的标注,平均识别率在91.7%以上 ,可识别泳池或者水库中是否有人溺水。 数据集分割 训练组98% 9818图片 有效集%…

Llama3.370B超越GPT-4o和Claude3.5 Sonnet

AI领域日新月异,最近AI 领域发生了太多事情,本文就语言大模型Llama 3.3 70B、GPT-4o 和 Claude 3.5 Sonnet进行对比。 12月7日,Meta今年的最终AI模型将要来了。Meta12月6日发布了Llama 3.3,拥有700亿个参数,但其性能与…

linux内核网络分层概述

在开发应用时,我们使用 socket 实现网络数据的收发。以tcp为例,server端通过 socket, bind, listen来创建服务端,然后通过 accept接收客户端连接;客户端通过 socket和 connect系统调用来创建客户端。用于数据收发的系统调用包括 s…

【全栈实战】基于 Vue3 + Wot Design Uni 动手封装组件

😊你好,我是小航,一个正在变秃、变强的文艺倾年。 😊好久没有更新有关前端实战教程了,本文主要讲解【全栈实战】基于 Vue3 Wot Design Uni 动手封装组件! 😊这个教程你将会学到技术正确的选型、…

Ajax中的axios

既然提到Ajax,那就先来说一说什么是Ajax吧 关于Ajax Ajax的定义 Asynchronous JavaScript And XML:异步的JavaScript和XML。 反正就是一句话总结: 使用XML HttpRequest 对象与服务器进行通讯。 AJAX 是一种在无需重新加载整个网页的情况下&…

60.基于SSM的个人网站的设计与实现(项目 + 论文)

项目介绍 本站是一个B/S模式系统,个人网站是在MySQL中建立数据表保存信息,运用SSMVue框架和Java语言编写。并按照软件设计开发流程进行设计实现充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得基于SSM的网…

聊聊Flink:Flink的状态管理

一、Flink的状态是什么? 我们知道,Flink的一个算子可能会有多个子任务,每个子任务可能分布在不同的实例(即slot)上,我们可以把Flink的状态理解为某个算子的子任务在其当前实例上的一个变量,该变…

Idea 将多个module显示在同一个project

Idea 将多个maven项目显示在同一个project下 1、选择菜单 File-》New -》Module from Existing Sources -> 2、在弹出的界面选中对应的Module的pom.xml,然后点击OK按钮就行了 (弹出框上面也提示了Eclipse 项目选中.project文件;Maven 项目选中pom.xml; ) 最终显…

文件解析漏洞中间件(iis和Apache)

IIS解析漏洞 IIS6.X #环境 Windows Server 2003 在iis6.x中&#xff0c;.asp文件夹中的任意文件都会被当做asp文件去执行 在默认网站里创建一个a.asp文件夹并创建一个1.jpg写进我们的asp代码 <%now()%> #asp一句话 <%eval request("h")%> 单独创建一…

gitee别人仓库再上传自己仓库

一、新建一个自己的Git仓库 如果没有注册账号的朋友&#xff0c;可以先去注册一个Gitee的账号&#xff0c;用于管理自己的代码特别好用&#xff01;&#xff01;&#xff01; 接下来就是在gitee上新建一个自己的仓库&#xff0c;如下图所示 二、右建 Git Bush Here删除.git文件…

STM32F407 | Embedded IDE01 - vscode搭建Embedded IDE开发环境(支持JLINK、STLINK、DAPLINK)

导言 Embedded IDE官网:https://em-ide.com/docs/intro 我猜肯定有部分人使用SI Keil开发STM32项目&#xff0c;也有vscode Keil开发STM32程序。SI或vscode编写代码&#xff0c;然后切换Keil编译、下载、调试程序。有一段时间&#xff0c;我也是这么干的。但是&#xff0c;程…

算法的学习笔记—扑克牌顺子(牛客JZ61)

&#x1f600;前言 扑克牌顺子问题是一道趣味性与逻辑性兼备的题目&#xff0c;要求判断五张牌是否能组成顺子&#xff0c;其中大小王&#xff08;癞子&#xff09;可作为任意牌面。癞子的特殊性增加了问题的复杂度&#xff0c;也为解题提供了更多的可能性。通过这一问题&#…

记录遇到的一个新的变种JS加密

源 逻辑分析 混淆代码的目的是隐藏实际逻辑&#xff0c;增加逆向工程的难度。以下是对代码的逐步分析和解读。 第一部分&#xff1a;立即调用的函数表达式 (IIFE) (function () {var _K [...]; // 存储大量字符串的数组 })();​ 1. 目的&#xff1a;这个 IIFE 是整个代码运行…

LeetCode:104.二叉树的最大深度

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;104.二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节…