最近写论文的时候,经常需要向上或向下插入题注的交叉引用,word 自带的界面往往需要操作多次,才能实现插入。而平时使用较多的只是交叉引用附近的题注,比如如图1.1所示,在图1.1中等,距离较远的引用则可以直接复制已经存在的交叉引用项,复制的项只要保留原格式复制,仍然是存在超链接的。所以可以借助 VBA 写一个函数,用来在当前位置插入向上或向下距离最近指定的题注类型,然后给指定的脚本指定快捷键,就可以实现一键插入。

首先 Word VBA中关于题注和插入交叉引用,我只找到两个函数,分别是 GetCrossReferenceItems 和 InsertCrossReference,一个是获得当前所有的特定题注,一个是插入指定的题注,其中InsertCrossReference 需要使用 GetCrossReferenceItems 来确定插入的题注所在的位置。

由于 GetCrossReferenceItems 的对象是全文,因此需要首先找到距离最近的题注所在的位置,然后取得其相应的特征值,最后与GetCrossReferenceItems返回的结果进行对比,确定其索引值后,再使用InsertCrossReference进行插入。

根据上述思路, 整体代码如下:

  1. Public Function autoInsertReferece(crossRefName As String, direction As Integer) As Boolean
  2. ' 功能:自动插入最靠近当前位置的题注,需要指定向上或向下搜索
  3. ' 变量名:
  4. ' crossRefName: 题注名
  5. ' direction: 方向 0-> 向下搜索 其它整数->向上搜索
  6. ' 注意事项:
  7. ' 必须要文档中定义相应的标签
  8. ' 先找到向上或向下距离最近的标注所在的段落,获得其文本后,再确定其在所有该类题注中所处的位置
  9. ' 工具》引用》Microsoft VBScript Regular Expressions 5.5打勾
  10.  
  11. Dim target_para As Long
  12. Dim flag As Boolean
  13. Dim flagUpdate As Boolean
  14. Dim rngParagraph As Range
  15. Dim currentParaNum As Long
  16. Dim endParaNum As Long
  17.  
  18. target_para =
  19. flag = False
  20. flagUpdate = False
  21.  
  22. ' 根据方向做不同处理, 找到距离最近的题注对象,获得其所在的段落
  23. currentParaNum = ActiveDocument.Range(, Selection.End).Paragraphs.Count '获得当前的段落数
  24.  
  25. Set rngParagraph = ActiveDocument.Paragraphs(currentParaNum).Range
  26. If direction = Then
  27. endParaNum = ActiveDocument.Paragraphs.Count
  28. rngParagraph.SetRange Start:=rngParagraph.Start, _
  29. End:=ActiveDocument.Paragraphs(endParaNum).Range.End
  30. target_para = findTargetPara(crossRefName, direction, rngParagraph)
  31. Else
  32. '以20段为周期,向上遍历,直到行首
  33. Dim para_step As Integer
  34. para_step =
  35. Do While currentParaNum > para_step
  36. currentParaNum = currentParaNum - para_step
  37. rngParagraph.SetRange Start:=rngParagraph.End, _
  38. End:=ActiveDocument.Paragraphs(currentParaNum).Range.End
  39. target_para = findTargetPara(crossRefName, direction, rngParagraph)
  40. If target_para <> Then
  41. Exit Do
  42. End If
  43. '重新设置 range
  44. Set rngParagraph = ActiveDocument.Paragraphs(currentParaNum).Range
  45. Loop
  46. '没找到目标段落,处理到开关
  47. If target_para = Then
  48. rngParagraph.SetRange Start:=rngParagraph.Start, _
  49. End:=ActiveDocument.Paragraphs().Range.End
  50. target_para = findTargetPara(crossRefName, direction, rngParagraph)
  51. End If
  52. End If
  53. '找到段落后进行相应的处理
  54.  
  55. If target_para <> Then
  56. ' 获取目标段落的文本
  57. Dim target_text As String
  58. ActiveDocument.Paragraphs(target_para).Range.Fields.Update '更新目标域代码,以防出错
  59. target_text = ActiveDocument.Paragraphs(target_para).Range.Text
  60. ' 正则表达式设置
  61. Dim regEx, Match, Matches '创建变量
  62. Set regEx = New RegExp '创建正则表达式
  63. regEx.Pattern = "\s*\d+(.\d+)*" '设置匹配字符串, 匹配 2 2.1 2.1.1
  64. regEx.IgnoreCase = True '设置是否区分大小写
  65. regEx.Global = True '设置全程匹配
  66.  
  67. Set Match = regEx.Execute(target_text) '执行搜索
  68. target_item = Match.Item().Value '目标题注
  69. allCrossRef = ActiveDocument.GetCrossReferenceItems(crossRefName)
  70. For I = To UBound(allCrossRef) '遍历所有的给定题注直至找到目标题注
  71. Set Match = regEx.Execute(allCrossRef(I))
  72. compare_item = Match.Item().Value
  73. If target_item = compare_item Then
  74. If crossRefName <> "公式" Then
  75. ' 非公式只引用题注
  76. Selection.InsertCrossReference ReferenceType:=crossRefName, ReferenceKind:= _
  77. wdOnlyLabelAndNumber, ReferenceItem:=CStr(I), InsertAsHyperlink:=True, _
  78. IncludePosition:=False, SeparateNumbers:=False, SeparatorString:=" "
  79. flag = True
  80. Else
  81. ' 公式全文引用
  82. Selection.InsertCrossReference ReferenceType:=crossRefName, ReferenceKind:= _
  83. wdEntireCaption, ReferenceItem:=CStr(I), InsertAsHyperlink:=True, _
  84. IncludePosition:=False, SeparateNumbers:=False, SeparatorString:=" "
  85. End If
  86. Selection.TypeText Text:=" " '输出一个空格
  87. flag = True
  88. Exit For
  89. End If
  90. Next
  91.  
  92. End If
  93. autoInsertReferece = flag
  94. End Function
  95.  
  96. Private Function findTargetPara(crossRefName As String, direction As Integer, rngParagraph As Range)
  97. '在指定的范围内查找目标段落
  98. '参数说明
  99. 'direction = 0 向下搜索,找到后立即跳出,否则向上搜索,完全遍历后再确定是否找到目标项
  100. Dim target_para As Long
  101. target_para =
  102. For Each para In rngParagraph.Paragraphs:
  103. 'If para.Range.Tables.Count = 0 Then '跳过表格,以加快处理速度
  104. For Each oField In para.Range.Fields
  105. With oField
  106. If .Code.Text = " SEQ " + crossRefName + " \* ARABIC \s 1 " Then
  107. target_para = ActiveDocument.Range(, para.Range.End).Paragraphs.Count
  108. If direction = Then
  109. Exit For
  110. End If
  111. End If
  112. End With
  113. Next
  114. If direction = And target_para <> Then
  115. Exit For
  116. End If
  117. Next
  118.  
  119. findTargetPara = target_para
  120.  
  121. End Function
  122.  
  123. Sub InsertPictureCrossReferenceDown()
  124. autoInsertReferece "图",
  125. End Sub
  126.  
  127. Sub InsertPictureCrossReferenceUp()
  128. autoInsertReferece "图",
  129. End Sub
  130.  
  131. Sub InsertTableCrossReferenceDown()
  132. autoInsertReferece "表",
  133. End Sub
  134.  
  135. Sub InsertTableCrossReferenceUp()
  136. autoInsertReferece "表",
  137. End Sub
  138.  
  139. Sub InsertMathCrossReferenceDown()
  140.  
  141. Selection.TypeText Text:=" "
  142. flag = autoInsertReferece("公式", )
  143. If Not flag Then
  144. Selection.TypeBackspace
  145. End If
  146.  
  147. End Sub
  148.  
  149. Sub InsertMathCrossReferenceUp()
  150.  
  151. Selection.TypeText Text:=" "
  152. flag = autoInsertReferece("公式", )
  153. If Not flag Then
  154. Selection.TypeBackspace
  155. End If
  156.  
  157. End Sub

代码中 autoInsertReferece 为主体实现函数,由于 Word 中的 Range 遍历只能从上向下进行,而自己用索引去遍历,运行速度会非常慢。所以,当需要向上搜索目标题注时,只能以一个一个段落范围的range向前推进,如果一个范围搜索后,找到结果,就说明其为最后的结果;而向下搜索时,则可以直接把 range 设为从当前到文未,找到目标题注后,即可立即停止搜索。findTargetPara   的主要功能是在给定的范围内,找到题注所在的段落。

最后的相应 Sub 函数是具体的应用,由于我对文中的公式有特殊的处理,插入时需要引用题注和内容,其余的默认只引用题注。实际使用时,可以给相应的 Sub 设定快捷键,比如将  InsertPictureCrossReferenceDown 宏的快捷键设为 Alt + 1,然后在Word文档中按 Alt + 1 键,即可在当前位置插入距离当前位置最近的题注(向下搜索)。

宏的使用及快捷键设置参照  Onenote代码高亮的实现方法

Word 借助VBA一键实现插入交叉引用的更多相关文章

  1. Word 图片表格自动编号、交叉引用、批量更改图片标题格式、生成图录和表录

    1. 前言 论文往往里往往需要插入很多图片,下放需要标上 图a-b,其中 a 是章节号码,b是该章节中第几张图.比如第一章第二副图就是 图1-2.但是有个问题,每次我们插入了一张图或删掉了一张,前后的 ...

  2. 第五周 Word注释与交叉引用

    第五周 Word注释与交叉引用 教学时间 2013-3-26 教学课时 2 教案序号 4 教学目标 1.掌握脚注.尾注.题注的概念和应用 2.掌握交叉引用的操作方法 教学过程: 复习提问 1.如何利用 ...

  3. 【Word】自动化参考文献-交叉引用

    第一步:设置参考文献标号 开始-定义新编号格式中,定义参考文献式的方框编号: 这里注意不要把他原来的数字去掉 第二步:选择交叉引用 插入-交叉引用: 第三步:更新标号 如果更新标号,使用右键-更新域. ...

  4. Word2010设置题注和交叉引用方法

    设置题注 点击图片-->右键-->插入题注-->新建标签:“图”-->选择新建标签“图”-->修改“编号”-->勾选包含章节号-->设置章节起始样式:标题2- ...

  5. Word操作之参考文献自动关联和引用

    转载:https://blog.csdn.net/qq_40078121/article/details/88681605 编号选项->定义新编号格式: 选择插入->交叉引用选项: 然后选 ...

  6. WPS2012交叉引用技巧,word比wps这点强更新參考文献

                WPS2012交叉引用技巧,word比wps这点强更新參考文献 到时生成仅仅有有一条线,好像WPS不能够,word能够,假设谁知道能够补充.^_^ 1.写论文,參考文献的改动非 ...

  7. WPS2012交叉引用提示word比wps这种强烈的更新参考

                WPS2012交叉引用技巧,word比wps这点强更新參考文献 到时生成仅仅有有一条线,好像WPS不能够,word能够,假设谁知道能够补充.^_^ 1.写论文,參考文献的改动非 ...

  8. word正文中怎么引用章节编号、怎么引用图片表格编号、交叉引用

    摘自:https://blog.csdn.net/m0_37549050/article/details/88823135 在写文档的时候,可能会出现需要在文档中引用其它段落的编号.比如文档分了章节, ...

  9. word交叉引用公式编号时和连公式一起引用

    如下所示: 假定一副待处理图像中的灰度值个数为m,灰度值为i的像素个数为 个,那么图像中的总像素数为N,公式如m=x+y (2)所示: m=x+y                            ...

随机推荐

  1. (转)C#抽象类和接口对比

    c#中抽象类(abstract)和接口(interface)的相同点与区别  转自:http://blog.csdn.net/fxh_hua/archive/2009/08/20/4464739.as ...

  2. List和set集合:交集、差集、合集的区别retainAll,removeAll、addAll

    set .list集合的交集(retainAll).差集(removeAll)是没有区别的都是一样的. set .list集合的合集addAll是有区别的:set可以去重复:list不去重复 publ ...

  3. Error: Can't set headers after they are sent.

    Error: Can't set headers after they are sent. 错误:无法设置头信息后发送. 具体报错: 看到了一下代码,自己写错了 没有进行错误判断,两个条件都直接返回, ...

  4. C#实现程序单例日志输出

    对于一个完整的程序系统,一个日志记录是必不可少的.可以用它来记录程序在运行过程中的运行状态和报错信息.比如,那些不想通过弹框提示的错误,程序执行过程中捕获的异常等. 首先,在你的解决方案中,适当的目录 ...

  5. MySQL存储过程多条修改语句

    DROP procedure Sel_Function_ActivityPastDueDELIMITER $$DROP procedure IF EXISTS`shouyi`.`Sel_Functio ...

  6. 第12届D2前端技术论坛

    第12届D2前端技术论坛 最近参加了阿里的D2前端技术论坛,听了一天的报告,收获良多,下面对几场报告做一个记录. 自己选择听的主线也是从: 实践应用 -> 管理 -> 性能 -> 新 ...

  7. JavaScript中函数对象和对象的区别

    function Test (word) { console.log (word); } Test('哈哈,我是函数'); new Test('哈哈,我是对象'); //将以上的调用方式换种通俗易懂的 ...

  8. 64位Windows系统下32位应用程序连接MySql

    1.首先得安装“Connector/ODBC”,就是Mysql的ODBC驱动,这个是与应用程序相关的,而不是与操作系统相关的,也就是说,不管你的系统是x64还是x86,只要你的应用程序是x86的那么, ...

  9. HDU 3681 Prison Break 越狱(状压DP,变形)

    题意: 给一个n*m的矩阵,每个格子中有一个大写字母,一个机器人从‘F’出发,拾取所有的开关‘Y’时便能够越狱,但是每走一格需要花费1点能量,部分格子为充电站‘G’,每个电站只能充1次电.而且部分格子 ...

  10. Linux 的数字权限意义

    三个组 每个都有三个权限 r w x每个权限用二进制 0 和 1 标示 1即为有此权限 0 标示无权限  ower    group  other  r w x    r w x  r w x 每个组 ...