在word中使用zotero添加参考文献并附带超链接
一、引言
在写大论文时,为了避免文中引用与文末参考文献频繁对照、修改文中引用顺序/引用文献时手动维护参考文献耗易出错,拟在 word 中使用 zotero 插入参考文献,并为每个参考文献附加超链接,实现交互式阅读。
版本:word2016 + zotero7.0.15
二、配置zotero
这里我首先对 zotero 进行了一下更新,原本我是 6.0 版本,更新为 7.0 版本后发现好多东西 zotero 都已经自带了,不需要再自行下载配置。
1. 添加引用文献样式
下载链接
里面有非常多学校的模板,感谢各位大佬的分享。
下载好后,选择自己学校的模板,然后双击 cls 文件,即可添加至 zotero 参考文献样式库。

安装。

OK。
调用这个模板后没有出现中英文混杂等任何问题。
2. 配置宏实现超链接
参考链接1
参考链接2
- word 选项卡——>视图——>宏——>查看宏

- 创建一个名为 ZoteroLinkCitation 的宏

- 在编辑器中填入以下代码并保存
Public Sub ZoteroLinkCitation()' get selected area (if applicable)Dim nStart&, nEnd&nStart = Selection.StartnEnd = Selection.End' toggle screen updatingApplication.ScreenUpdating = False' define variablesDim title As StringDim titleAnchor As StringDim style As StringDim fieldCode As StringDim numOrYear As StringDim pos&, n1&, n2&, n3&ActiveWindow.View.ShowFieldCodes = TrueSelection.Find.ClearFormatting' find the Zotero bibliographyWith Selection.Find.Text = "^d ADDIN ZOTERO_BIBL".Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.Execute' add bookmark for the Zotero bibliographyWith ActiveDocument.Bookmarks.Add Range:=Selection.Range, Name:="Zotero_Bibliography".DefaultSorting = wdSortByName.ShowHidden = TrueEnd With' loop through each field in the documentFor Each aField In ActiveDocument.Fields' check if the field is a Zotero in-text reference'##################################################If InStr(aField.Code, "ADDIN ZOTERO_ITEM") > 0 ThenfieldCode = aField.Code'#############' Prepare' Plain citation== Format of Textfield shown' must be in BracketsDim plain_Cit As StringplCitStrBeg = """plainCitation"":""["plCitStrEnd = "]"""n1 = InStr(fieldCode, plCitStrBeg)n1 = n1 + Len(plCitStrBeg)n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), plCitStrEnd) - 1 + n1plain_Cit = Mid$(fieldCode, n1 - 1, n2 - n1 + 2)'Reference 'as shown' in word as a string'Title array in fieldCode (all referenced Titles within this field)Dim array_RefTitle(32) As Stringi = 0Do While InStr(fieldCode, """title"":""") > 0n1 = InStr(fieldCode, """title"":""") + Len("""title"":""")n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), """,""") - 1 + n1If n2 < n1 Then 'Exception the type 'Article'n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), "}") - 1 + n1 - 1End Ifarray_RefTitle(i) = Mid(fieldCode, n1, n2 - n1)fieldCode = Mid(fieldCode, n2 + 1, Len(fieldCode) - n2 - 1)i = i + 1LoopTitles_in_Cit = i'Number array with References shown in PlainCit'Numer is equal or less than Titels, depending on the type'[3], [8]-[10]; [2]-[4]; [2], [4], [5]' All citations have to be in Brackets each! [3], [8] not [3, 8]' This doesnt work otherwise!' --> treatment of other delimiters could be implemented hereDim RefNumber(32) As Stringi = 0Do While (InStr(plain_Cit, "]") Or InStr(plain_Cit, "[")) > 0n1 = InStr(plain_Cit, "[")n2 = InStr(plain_Cit, "]")RefNumber(i) = Mid(plain_Cit, n1 + 1, n2 - (n1 + 1))plain_Cit = Mid(plain_Cit, n2 + 1, Len(plain_Cit) - (n2 + 1) + 1)i = i + 1LoopRefs_in_Cit = i'treat only the shown references (skip the rest)'[3], [8]-[10] --> skip [9]'Order of titles given from fieldcode, not checked!If Titles_in_Cit > Refs_in_Cit Thenarray_RefTitle(Refs_in_Cit - 1) = array_RefTitle(Titles_in_Cit - 1)i = 1Do While Refs_in_Cit + i <= Titles_in_Citarray_RefTitle(Refs_in_Cit + i - 1) = ""i = i + 1LoopEnd If'#############'Make the linksFor Refs = 0 To Refs_in_Cit - 1 Step 1title = array_RefTitle(Refs)array_RefTitle(Refs) = ""' make title a valid bookmark nametitleAnchor = titletitleAnchor = MakeValidBMName(titleAnchor)ActiveWindow.View.ShowFieldCodes = FalseSelection.GoTo What:=wdGoToBookmark, Name:="Zotero_Bibliography"'' locate the corresponding reference in the bibliography'' by searching for its titleSelection.Find.ClearFormattingWith Selection.Find.Text = Left(title, 255).Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.Execute' select the whole caption (for mouseover tooltip)Selection.MoveStartUntil ("["), Count:=wdBackwardSelection.MoveEndUntil (vbBack)lnkcap = "[" & Selection.Textlnkcap = Left(lnkcap, 70)' add bookmark for the reference within the bibliographySelection.ShrinkWith ActiveDocument.Bookmarks.Add Range:=Selection.Range, Name:=titleAnchor.DefaultSorting = wdSortByName.ShowHidden = TrueEnd With' jump back to the fieldaField.Select' find and select the numeric part of the field which will become the hyperlinkSelection.Find.ClearFormattingWith Selection.Find.Text = RefNumber(Refs).Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.ExecutenumOrYear = Selection.Range.Text & ""' store current stylestyle = Selection.style' Generate the Hyperlink -->Forward!ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:="", SubAddress:=titleAnchor, ScreenTip:=lnkcap, TextToDisplay:="" & numOrYear' reset the style' comment if you want standard link styleaField.SelectWith Selection.Font.Underline = wdUnderlineNone.ColorIndex = wdBlackEnd WithNext Refs 'References in CitEnd If 'If Zotero-Field'#########################Next aField ' next field' go back to original range selectedActiveWindow.View.ShowFieldCodes = FalseActiveDocument.Range(nStart, nEnd).SelectEnd SubFunction MakeValidBMName(strIn As String)Dim pFirstChr As StringDim i As LongDim tempStr As StringstrIn = Trim(strIn)pFirstChr = Left(strIn, 1)If Not pFirstChr Like "[A-Za-z]" ThenstrIn = "A_" & strInEnd IfFor i = 1 To Len(strIn)Select Case Asc(Mid$(strIn, i, 1))Case 49 To 57, 65 To 90, 97 To 122tempStr = tempStr & Mid$(strIn, i, 1)Case ElsetempStr = tempStr & "_"End SelectNext itempStr = Replace(tempStr, " ", " ")MakeValidBMName = Left(tempStr, 40)End Function
- 添加超链接
回到Word,切换到视图栏,然后打开宏窗口,找到刚刚创建好的宏,然后点击运行:

即可为每篇文献添加超链接。
三、问题
1. 新建宏
这里我首先用了 zotero 自带的 ZoteroLinkCitation 宏,运行后出现了如下问题:

然后我又新建了一个 ZoteroLinkCitation 宏,复制了 CSDN 上另外一个大佬分享的代码,但是运行时出现了如下错误:

搜索了一下好像是因为选中的文本中包含了换行符?我改了一下没有改好,然后又换成了上面那位大佬分享的代码,没有选择任何文本,直接运行之后没有错误,成功添加了超链接。
2. 在同一个位置引用多篇文献的方法
经典视图中点击“多重来源”,并且可以调整多个文献的相对顺序:


3.无法在同一个位置添加多个超链接
1. 问题描述
这里我使用新建宏添加了超链接后,出现了一个问题,即 1 个方括号只能为 1 篇参考文献添加超链接。具体来讲,就是当 1 个位置同时引用了多篇参考文献时,只能添加最后 1 篇参考文献的链接:

由于 zoero 实际上是通过书签的方式添加超链接的,因此我们先查看一下参考文献中是不是每篇都添加了书签。
word 选项卡——>文件——>选项——>高级——>显示书签

然后看到参考文献中的确有些文献没有附上书签,例如文献 2、4:

或者查看所有书签的名称:

宏代码中是使用文献名称作为书签名的,可以发现书签数量与文献数量并不相符。因此确实有些文献没有成功创建超链接。
2. 解决方案
来看一下这段 VBA 代码写了什么(不得不说有大模型太方便了,分分钟解释清楚代码在干嘛):
' 声明一个公共子程序(宏)ZoteroLinkCitation
Public Sub ZoteroLinkCitation()' 获取当前选中的文本区域(如果存在选择)
' 定义长整型变量存储选区起始和结束位置Dim nStart&, nEnd&nStart = Selection.Start ' 记录选区开始位置nEnd = Selection.End ' 记录选区结束位置' 关闭屏幕刷新(提升执行速度)Application.ScreenUpdating = False' 定义变量Dim title As String ' 存储文献标题Dim titleAnchor As String ' 存储有效书签名Dim style As String ' 存储文本样式Dim fieldCode As String ' 存储字段代码Dim numOrYear As String ' 存储引用编号或年份Dim pos&, n1&, n2&, n3& ' 存储位置索引ActiveWindow.View.ShowFieldCodes = True ' 显示字段代码Selection.Find.ClearFormatting ' 清除查找格式,确保查找操作不会受到之前格式设置的影响。' 查找Zotero参考文献目录字段With Selection.Find.Text = "^d ADDIN ZOTERO_BIBL" ' 查找特殊字段标识.Replacement.Text = "".Forward = True ' 向前查找.Wrap = wdFindContinue ' 查找范围为整个文档.Format = False ' 不匹配格式.MatchCase = False ' 不区分大小写.MatchWholeWord = False ' 不匹配整个单词.MatchWildcards = False ' 不使用通配符.MatchSoundsLike = False ' 不匹配发音相似的单词.MatchAllWordForms = False ' 不匹配所有词形End WithSelection.Find.Execute ' 执行查找' 为找到的参考文献目录添加书签With ActiveDocument.Bookmarks.Add Range:=Selection.Range, Name:="Zotero_Bibliography" ' 创建书签.DefaultSorting = wdSortByName ' 默认按名称排序.ShowHidden = True ' 显示隐藏书签End With' 遍历文档中的所有字段For Each aField In ActiveDocument.Fields' 检查是否是Zotero的引用字段If InStr(aField.Code, "ADDIN ZOTERO_ITEM") > 0 ThenfieldCode = aField.Code ' 获取字段代码'############# 准备阶段 #############' 提取纯文本引用(例如[3])Dim plain_Cit As StringplCitStrBeg = """plainCitation"":""[" ' 定义引用开始标记plCitStrEnd = """]""" ' 定义引用结束标记n1 = InStr(fieldCode, plCitStrBeg) ' 查找开始位置n1 = n1 + Len(plCitStrBeg)n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), plCitStrEnd) - 1 + n1plain_Cit = Mid$(fieldCode, n1 - 1, n2 - n1 + 2) ' 提取引用内容' 提取所有文献标题到数组Dim array_RefTitle(32) As String ' 最多存储32个标题i = 0Do While InStr(fieldCode, """title"":""") > 0 ' 循环查找所有标题n1 = InStr(fieldCode, """title"":""") + Len("""title"":""")n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), """,""") - 1 + n1If n2 < n1 Then ' 处理特殊类型(如文章)n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), "}") - 1 + n1 - 1End Ifarray_RefTitle(i) = Mid(fieldCode, n1, n2 - n1) ' 存储标题fieldCode = Mid(fieldCode, n2 + 1, Len(fieldCode) - n2 - 1)i = i + 1LoopTitles_in_Cit = i ' 记录找到的标题数量' 提取引用编号(例如[3]中的3)Dim RefNumber(32) As Stringi = 0Do While (InStr(plain_Cit, "]") Or InStr(plain_Cit, "[")) > 0n1 = InStr(plain_Cit, "[")n2 = InStr(plain_Cit, "]")RefNumber(i) = Mid(plain_Cit, n1 + 1, n2 - (n1 + 1)) ' 提取编号plain_Cit = Mid(plain_Cit, n2 + 1, Len(plain_Cit) - (n2 + 1) + 1)i = i + 1LoopRefs_in_Cit = i ' 记录引用编号数量' 处理标题与引用编号数量不一致的情况If Titles_in_Cit > Refs_in_Cit Thenarray_RefTitle(Refs_in_Cit - 1) = array_RefTitle(Titles_in_Cit - 1)i = 1Do While Refs_in_Cit + i <= Titles_in_Citarray_RefTitle(Refs_in_Cit + i - 1) = ""i = i + 1LoopEnd If'############# 创建链接 #############For Refs = 0 To Refs_in_Cit - 1 Step 1title = array_RefTitle(Refs)array_RefTitle(Refs) = ""' 生成有效书签名(调用函数处理非法字符)titleAnchor = MakeValidBMName(title)' 跳转到参考文献书签位置ActiveWindow.View.ShowFieldCodes = FalseSelection.GoTo What:=wdGoToBookmark, Name:="Zotero_Bibliography"' 在参考文献中查找对应标题Selection.Find.ClearFormattingWith Selection.Find.Text = Left(title, 255) ' 限制搜索长度.Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.Execute' 选择完整的引用条目Selection.MoveStartUntil ("["), Count:=wdBackwardSelection.MoveEndUntil (vbBack)lnkcap = "[" & Selection.Text ' 创建悬浮提示文本lnkcap = Left(lnkcap, 70) ' 截断前70个字符' 为文献条目添加书签Selection.ShrinkWith ActiveDocument.Bookmarks.Add Range:=Selection.Range, Name:=titleAnchor.DefaultSorting = wdSortByName.ShowHidden = TrueEnd With' 返回原引用位置aField.Select' 查找引用编号所在位置Selection.Find.ClearFormattingWith Selection.Find.Text = RefNumber(Refs).Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.ExecutenumOrYear = Selection.Range.Text & "" ' 获取显示的编号' 创建超链接ActiveDocument.Hyperlinks.Add _Anchor:=Selection.Range, _Address:="", _SubAddress:=titleAnchor, _ScreenTip:=lnkcap, _TextToDisplay:="" & numOrYear' 重置字体样式(取消下划线)aField.SelectWith Selection.Font.Underline = wdUnderlineNone.ColorIndex = wdBlackEnd WithNext Refs ' 处理下一个引用End If ' 结束Zotero字段判断Next aField ' 处理下一个字段' 恢复原始视图和选区ActiveWindow.View.ShowFieldCodes = FalseActiveDocument.Range(nStart, nEnd).SelectEnd Sub' 辅助函数:生成有效书签名(移除非法字符)
Function MakeValidBMName(strIn As String)Dim pFirstChr As StringDim i As LongDim tempStr As StringstrIn = Trim(strIn)pFirstChr = Left(strIn, 1)If Not pFirstChr Like "[A-Za-z]" Then ' 首字符非字母时加前缀strIn = "A_" & strInEnd IfFor i = 1 To Len(strIn)Select Case Asc(Mid$(strIn, i, 1)) ' 只保留字母数字Case 49 To 57, 65 To 90, 97 To 122 ' 允许1-9, A-Z, a-ztempStr = tempStr & Mid$(strIn, i, 1)Case ElsetempStr = tempStr & "_" ' 替换其他字符为下划线End SelectNext itempStr = Replace(tempStr, " ", " ") ' 替换双空格MakeValidBMName = Left(tempStr, 40) ' 截断为前40字符End Function
1)参考文献以逗号形式隔开
参考链接
当遇到引用形式类似 [2, 3] 这种情况时,在执行完下面这段代码后:
'Title array in fieldCode (all referenced Titles within this field) fieldCode中的标题数组(此字段中引用的所有标题)Dim array_RefTitle(32) As Stringi = 0Do While InStr(fieldCode, """title"":""") > 0n1 = InStr(fieldCode, """title"":""") + Len("""title"":""")n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), """,""") - 1 + n1If n2 < n1 Then 'Exception the type 'Article'n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), "}") - 1 + n1 - 1End Ifarray_RefTitle(i) = Mid(fieldCode, n1, n2 - n1)fieldCode = Mid(fieldCode, n2 + 1, Len(fieldCode) - n2 - 1)i = i + 1Loop
可以看到 array_RefTitle 确实存入了文献 2 和文献 3 的标题:

在执行完下面这段代码后,RefNumber 变为了 ‘2, 3’, Refs_in_Cit 变为了 1:
'Number array with References shown in PlainCit 'PlainCit中显示了引用的数字数组'Numer is equal or less than Titels, depending on the type 'Numer等于或小于Titels,具体取决于类型'[3], [8]-[10]; [2]-[4]; [2], [4], [5] '[3], [8]-[10]; [2]-[4]; [2], [4], [5]' All citations have to be in Brackets each! [3], [8] not [3, 8] 所有引文都必须用括号括起来![3] [8]不是[3,8]' This doesnt work otherwise! 否则,这行不通!' --> treatment of other delimiters could be implemented hereDim RefNumber(32) As Stringi = 0Do While (InStr(plain_Cit, "]") Or InStr(plain_Cit, "[")) > 0n1 = InStr(plain_Cit, "[")n2 = InStr(plain_Cit, "]")RefNumber(i) = Mid(plain_Cit, n1 + 1, n2 - (n1 + 1))plain_Cit = Mid(plain_Cit, n2 + 1, Len(plain_Cit) - (n2 + 1) + 1)i = i + 1LoopRefs_in_Cit = i


在执行完下面这段代码后,array_RefTitle 就只剩下了文献 3 的标题:
'treat only the shown references (skip the rest) 仅处理显示的引用(跳过其余部分)'[3], [8]-[10] --> skip [9] [3] ,[8]-[10]-->跳过[9]'Order of titles given from fieldcode, not checked! 从字段代码给出的标题顺序,未选中!If Titles_in_Cit > Refs_in_Cit Thenarray_RefTitle(Refs_in_Cit - 1) = array_RefTitle(Titles_in_Cit - 1)i = 1Do While Refs_in_Cit + i <= Titles_in_Citarray_RefTitle(Refs_in_Cit + i - 1) = ""i = i + 1Loop

在执行到下面这段代码时:
' find and select the numeric part of the field which will become the hyperlink 查找并选择将成为超链接的字段的数字部分Selection.Find.ClearFormattingWith Selection.Find.Text = RefNumber(Refs).Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.ExecutenumOrYear = Selection.Range.Text & ""' store current stylestyle = Selection.style' Generate the Hyperlink -->Forward!ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:="", SubAddress:=titleAnchor, ScreenTip:=lnkcap, TextToDisplay:="" & numOrYear
可以看到,插入超链接的文本就是 RefNumber,这里即为 ‘2, 3’。
看到这里问题已经很明白了。现在的代码是为每个方括号添加了超链接,且只能添加最后 1 篇文献的超链接。而我们需要的实际上是为每个引文编号添加超链接。
因此,我们只需要将插入超链接的文本由每个方括号的内容改为每个引用编号即可。将 RefNumber 部分的代码改为如下形式:
'Number array with References shown in PlainCit 'PlainCit中显示了引用的数字数组'Numer is equal or less than Titels, depending on the type 'Numer等于或小于Titels,具体取决于类型'[3], [8]-[10]; [2]-[4]; [2], [4], [5] '[3], [8]-[10]; [2]-[4]; [2], [4], [5]' All citations have to be in Brackets each! [3], [8] not [3, 8] 所有引文都必须用括号括起来![3] [8]不是[3,8]' This doesnt work otherwise! 否则,这行不通!' --> treatment of other delimiters could be implemented hereDim RefNumber(32) As Stringi = 0' 初始化起始位置和数组startPosition = InStr(plain_Cit, "[")commaPosition = 0ReDim commaPositions(0 To 0)Do While (InStr(plain_Cit, "]") Or InStr(plain_Cit, "[")) > 0' 查找逗号的位置commaPosition = InStr(plain_Cit, ",") ' 这里查找的是第一个逗号的位置If commaPosition = 0 Then ' 引文数量 = 1commaPosition = InStr(plain_Cit, "]")RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 1, Len(plain_Cit) - (commaPosition + 1) + 1)Else ' 引文数量 > 1RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 2, Len(plain_Cit) - (commaPosition + 2))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfEnd Ifi = i + 1LoopRefs_in_Cit = i
以逗号为分隔,为每个引用编号添加超链接。这里由于我使用的引用文献样式中每个逗号后面都会有一个空格,所以提取字符串部分使用的是 commaPosition + 2,若没有空格则应该改为 commaPosition + 1。
运行后发现 4、5 分别引用成功了:

可以看到参考文献部分添加的书签也明显多了,例如2、4,都成功添加了书签:

2)参考文献以短横线连接
除了形如 [2, 3] 类的引用形式外,还存在 [6-8] 这类的形式。显然,这种形式的引用也只能添加最后 1 篇参考文献的链接:

以上如为例,我们需要的是为文献 2、6、8 分别添加超链接,这里 2 添加成功了,但是 6-8 只添加了文献 8 的链接。因此我们只需要再查找一下 “-” 的位置即可。
将 RefNumber 部分的代码改为如下形式:
'Number array with References shown in PlainCit 'PlainCit中显示了引用的数字数组'Numer is equal or less than Titels, depending on the type 'Numer等于或小于Titels,具体取决于类型'[3], [8]-[10]; [2]-[4]; [2], [4], [5] '[3], [8]-[10]; [2]-[4]; [2], [4], [5]' All citations have to be in Brackets each! [3], [8] not [3, 8] 所有引文都必须用括号括起来![3] [8]不是[3,8]' This doesnt work otherwise! 否则,这行不通!' --> treatment of other delimiters could be implemented hereDim RefNumber(32) As Stringi = 0' 初始化起始位置和数组startPosition = InStr(plain_Cit, "[")commaPosition = 0 ' 初始化逗号位置dashPosition = 0 ' 初始化短横线位置ReDim commaPositions(0 To 0)Do While (InStr(plain_Cit, "]") Or InStr(plain_Cit, "[")) > 0' 查找逗号的位置commaPosition = InStr(plain_Cit, ",") ' 这里查找的是第一个逗号的位置' 查找短横线的位置dashPosition = InStr(plain_Cit, "-") ' 这里查找的是第一个短横线的位置If commaPosition = 0 And dashPosition = 0 Then ' 情况0:都不存在commaPosition = InStr(plain_Cit, "]")RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 1, Len(plain_Cit) - (commaPosition + 1) + 1)ElseIf commaPosition > 0 And dashPosition > 0 Then ' 情况1/2:两者都存在If commaPosition < dashPosition Then ' 逗号在前RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 2, Len(plain_Cit) - (commaPosition + 2))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfElse ' 短横线在前RefNumber(i) = Mid(plain_Cit, startPosition + 1, dashPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, dashPosition + 1, Len(plain_Cit) - (dashPosition + 1))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfEnd IfElseIf commaPosition > 0 Then ' 情况3:只有逗号RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 2, Len(plain_Cit) - (commaPosition + 2))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfElse ' 情况4:只有短横线RefNumber(i) = Mid(plain_Cit, startPosition + 1, dashPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, dashPosition + 1, Len(plain_Cit) - (dashPosition + 1))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfEnd Ifi = i + 1LoopRefs_in_Cit = i
运行结束后可以分别为每个引用编号添加超链接:

再次查看参考文献部分,每篇论文都成功添加了书签,所有论文都被成功引用了。
修改后完整的代码如下:
Public Sub ZoteroLinkCitation()' get selected area (if applicable)获取选定区域(如果适用)Dim nStart&, nEnd&nStart = Selection.StartnEnd = Selection.End' toggle screen updating 切换屏幕更新Application.ScreenUpdating = False' define variables 定义变量Dim title As StringDim titleAnchor As StringDim style As StringDim fieldCode As StringDim numOrYear As StringDim pos&, n1&, n2&, n3&ActiveWindow.View.ShowFieldCodes = TrueSelection.Find.ClearFormatting' find the Zotero bibliography 查找Zotero参考目录With Selection.Find.Text = "^d ADDIN ZOTERO_BIBL".Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.Execute' add bookmark for the Zotero bibliography 为Zotero参考目录添加书签With ActiveDocument.Bookmarks.Add Range:=Selection.Range, Name:="Zotero_Bibliography".DefaultSorting = wdSortByName.ShowHidden = TrueEnd With' loop through each field in the document 遍历文档中的每个字段For Each aField In ActiveDocument.Fields' check if the field is a Zotero in-text reference 检查文本引用中的字段是否为Zotero'##################################################If InStr(aField.Code, "ADDIN ZOTERO_ITEM") > 0 ThenfieldCode = aField.Code'#############' Prepare' Plain citation== Format of Textfield shown 纯文本引用' must be in Brackets 必须放在方括号中Dim plain_Cit As StringplCitStrBeg = """plainCitation"":""["plCitStrEnd = "]"""n1 = InStr(fieldCode, plCitStrBeg)n1 = n1 + Len(plCitStrBeg)n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), plCitStrEnd) - 1 + n1plain_Cit = Mid$(fieldCode, n1 - 1, n2 - n1 + 2)'Reference 'as shown' in word as a string'Title array in fieldCode (all referenced Titles within this field) fieldCode中的标题数组(此字段中引用的所有标题)Dim array_RefTitle(32) As Stringi = 0Do While InStr(fieldCode, """title"":""") > 0n1 = InStr(fieldCode, """title"":""") + Len("""title"":""")n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), """,""") - 1 + n1If n2 < n1 Then 'Exception the type 'Article'n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), "}") - 1 + n1 - 1End Ifarray_RefTitle(i) = Mid(fieldCode, n1, n2 - n1)fieldCode = Mid(fieldCode, n2 + 1, Len(fieldCode) - n2 - 1)i = i + 1LoopTitles_in_Cit = i'Number array with References shown in PlainCit 'PlainCit中显示了引用的数字数组'Numer is equal or less than Titels, depending on the type 'Numer等于或小于Titels,具体取决于类型'[3], [8]-[10]; [2]-[4]; [2], [4], [5] '[3], [8]-[10]; [2]-[4]; [2], [4], [5]' All citations have to be in Brackets each! [3], [8] not [3, 8] 所有引文都必须用括号括起来![3] [8]不是[3,8]' This doesnt work otherwise! 否则,这行不通!' --> treatment of other delimiters could be implemented hereDim RefNumber(32) As Stringi = 0' 初始化起始位置和数组startPosition = InStr(plain_Cit, "[")commaPosition = 0 ' 初始化逗号位置dashPosition = 0 ' 初始化短横线位置ReDim commaPositions(0 To 0)Do While (InStr(plain_Cit, "]") Or InStr(plain_Cit, "[")) > 0' 查找逗号的位置commaPosition = InStr(plain_Cit, ",") ' 这里查找的是第一个逗号的位置' 查找短横线的位置dashPosition = InStr(plain_Cit, "-") ' 这里查找的是第一个短横线的位置If commaPosition = 0 And dashPosition = 0 Then ' 情况0:都不存在commaPosition = InStr(plain_Cit, "]")RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 1, Len(plain_Cit) - (commaPosition + 1) + 1)ElseIf commaPosition > 0 And dashPosition > 0 Then ' 情况1/2:两者都存在If commaPosition < dashPosition Then ' 逗号在前RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 2, Len(plain_Cit) - (commaPosition + 2))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfElse ' 短横线在前RefNumber(i) = Mid(plain_Cit, startPosition + 1, dashPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, dashPosition + 1, Len(plain_Cit) - (dashPosition + 1))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfEnd IfElseIf commaPosition > 0 Then ' 情况3:只有逗号RefNumber(i) = Mid(plain_Cit, startPosition + 1, commaPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, commaPosition + 2, Len(plain_Cit) - (commaPosition + 2))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfElse ' 情况4:只有短横线RefNumber(i) = Mid(plain_Cit, startPosition + 1, dashPosition - (startPosition + 1))plain_Cit = Mid(plain_Cit, dashPosition + 1, Len(plain_Cit) - (dashPosition + 1))' 检查是否为空字符串If Len(Trim(plain_Cit)) = 0 Thenplain_Cit = plain_CitElseplain_Cit = "[" & plain_Cit & "]"End IfEnd Ifi = i + 1LoopRefs_in_Cit = i'treat only the shown references (skip the rest) 仅处理显示的引用(跳过其余部分)'[3], [8]-[10] --> skip [9] [3] ,[8]-[10]-->跳过[9]'Order of titles given from fieldcode, not checked! 从字段代码给出的标题顺序,未选中!If Titles_in_Cit > Refs_in_Cit Thenarray_RefTitle(Refs_in_Cit - 1) = array_RefTitle(Titles_in_Cit - 1)i = 1Do While Refs_in_Cit + i <= Titles_in_Citarray_RefTitle(Refs_in_Cit + i - 1) = ""i = i + 1LoopEnd If'#############'Make the linksFor Refs = 0 To Refs_in_Cit - 1 Step 1title = array_RefTitle(Refs)array_RefTitle(Refs) = ""' make title a valid bookmark nametitleAnchor = titletitleAnchor = MakeValidBMName(titleAnchor)ActiveWindow.View.ShowFieldCodes = FalseSelection.GoTo What:=wdGoToBookmark, Name:="Zotero_Bibliography"'' locate the corresponding reference in the bibliography'' by searching for its titleSelection.Find.ClearFormattingWith Selection.Find.Text = Left(title, 255).Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.Execute' select the whole caption (for mouseover tooltip) 选择整个标题(用于鼠标悬停工具提示)Selection.MoveStartUntil ("["), Count:=wdBackwardSelection.MoveEndUntil (vbBack)lnkcap = "[" & Selection.Textlnkcap = Left(lnkcap, 70)' add bookmark for the reference within the bibliography 为参考目录中的参考添加书签Selection.ShrinkWith ActiveDocument.Bookmarks.Add Range:=Selection.Range, Name:=titleAnchor.DefaultSorting = wdSortByName.ShowHidden = TrueEnd With' jump back to the fieldaField.Select' find and select the numeric part of the field which will become the hyperlink 查找并选择将成为超链接的字段的数字部分Selection.Find.ClearFormattingWith Selection.Find.Text = RefNumber(Refs).Replacement.Text = "".Forward = True.Wrap = wdFindContinue.Format = False.MatchCase = False.MatchWholeWord = False.MatchWildcards = False.MatchSoundsLike = False.MatchAllWordForms = FalseEnd WithSelection.Find.ExecutenumOrYear = Selection.Range.Text & ""' store current stylestyle = Selection.style' Generate the Hyperlink -->Forward!ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:="", SubAddress:=titleAnchor, ScreenTip:=lnkcap, TextToDisplay:="" & numOrYear' reset the style' comment if you want standard link styleaField.SelectWith Selection.Font.Underline = wdUnderlineNone.ColorIndex = wdBlackEnd WithNext Refs 'References in CitEnd If 'If Zotero-Field'#########################Next aField ' next field' go back to original range selectedActiveWindow.View.ShowFieldCodes = FalseActiveDocument.Range(nStart, nEnd).SelectEnd SubFunction MakeValidBMName(strIn As String)Dim pFirstChr As StringDim i As LongDim tempStr As StringstrIn = Trim(strIn)pFirstChr = Left(strIn, 1)If Not pFirstChr Like "[A-Za-z]" ThenstrIn = "A_" & strInEnd IfFor i = 1 To Len(strIn)Select Case Asc(Mid$(strIn, i, 1))Case 49 To 57, 65 To 90, 97 To 122tempStr = tempStr & Mid$(strIn, i, 1)Case ElsetempStr = tempStr & "_"End SelectNext itempStr = Replace(tempStr, " ", " ")MakeValidBMName = Left(tempStr, 40)End Function
相关文章:
在word中使用zotero添加参考文献并附带超链接
一、引言 在写大论文时,为了避免文中引用与文末参考文献频繁对照、修改文中引用顺序/引用文献时手动维护参考文献耗易出错,拟在 word 中使用 zotero 插入参考文献,并为每个参考文献附加超链接,实现交互式阅读。 版本:…...
性能测试、负载测试、压力测试的全面解析
在软件测试领域,性能测试、负载测试和压力测试是评估系统稳定性和可靠性的关键手段。它们各自关注不同的测试目标和应用场景,理解这些差异对于制定有效的测试策略至关重要。 本文对性能测试、负载测试和压力测试进行深入分析,探讨其定义、…...
mysqloracledb2 (uuid函数)
项目场景: 创建一个32位的UUID 问题描述 原因分析: 解决方案: mysql内置UUID函数 SELECT UUID(); SELECT UUID_SHORT();oracle内置UUID函数 SELECT sys_guid() FROM dual;db2,模拟UUID函数 SELECT TEST || substr (CONCAT…...
工具介绍《WireShark》
Wireshark 过滤命令中符号含义详解 一、比较运算符 Wireshark 支持两种比较运算符语法:英文缩写(如 eq)和 C语言风格符号(如 ),两者功能等价。 符号(英文缩写)C语言风格符号含义示…...
Redis中的数据类型与适用场景
目录 前言1. 字符串 (String)1.1 特点1.2 适用场景 2. 哈希 (Hash)2.1 特点2.2 适用场景 3. 列表 (List)3.1 特点3.2 适用场景 4. 集合 (Set)4.1 特点4.2 适用场景 5. 有序集合 (Sorted Set)5.1 特点5.2 适用场景 6. Redis 数据类型的选型建议结语 前言 Redis 作为一款高性能的…...
gz sim机器人SDF模型 [持续更新]
机器人SDF模型 linklink的一级pose材质 plugin话题信息通信键盘操作plugin Sensor传感器imu 不算教学,个人的记录 sdf的格式跟urdf有所不同,必须是完整的一个包括,比如< pose></ pose>这样前一个后一个,urdf中是有<…...
【Qt】Ubuntu22.04使用命令安装Qt5和Qt6
1、安装Qt5 注意:Ubuntu22.04已经没有 qt5-default ,因此不能一键安装啦 1)安装核心组件 sudo apt install qtbase5-dev qtchooser qt5-qmake qtcreator2)安装QtCreator sudo apt install qtcreator3)安装工具包、Qt Quick 开发的核心库(qtdeclarative5-dev) sudo a…...
Pytest的Fixture使用
概述 Pytest中的Fixture可以使得测试代码高度复用,同时对资源进行安全的管理,以及在复杂的测试场景用进行灵活的组合。 概念 Fixture:可重用的函数,用@pytest.fixture来进行装饰,用于为测试提供数据、环境或者服务作用域:控制Fixture的生命周期,默认是function,可设置…...
【MySQL | 六、索引特性(进一步理解)】
目录 索引的理解索引的作用MySQL与磁盘的IOPage单个Page的分类多个Page的组织B树的特点 B树和B树的区别聚簇索引 VS 非聚簇索引聚簇索引的优缺点非聚簇索引的优缺点 创建索引常见索引分为:主键索引InnoDB主键索引的生成过程(1)初始化…...
计算机网络高频(三)UDP基础
计算机网络高频(三)UDP基础 1.UDP的头部格式是什么样的?⭐ UDP 头部具有以下字段: 源端口(Source Port):16 位字段,表示发送方的端口号。目标端口(Destination Port):16 位字段,表示接收方的端口号。长度(Length):16 位字段,表示 UDP 数据报(包括头部和数据部…...
【测试开发】OKR 小程序端黑盒测试报告
【测试报告】OKR 小程序端 项目名称版本号测试负责人测试完成日期联系方式OKR 小程序端4.0马铭胜2025-03-2515362558972 1、项目背景 1.1 OKR 用户端 在如今这个快节奏的时代中,个人和组织的成长往往依赖于清晰、明确且意义深远的目标。然而,如何设定…...
HTTP 1.0和2.0 有什么区别?
HTTP 1.0和HTTP 2.0是互联网中用于数据传输的重要协议,两者在功能和性能上有显著差异。 以下是它们的主要区别: HTTP 1.0 的特点: 单一连接:每个请求需要独立连接,导致高延迟和资源浪费。文本传输:使用文…...
部署高可用PostgreSQL14集群
目录 基础依赖包安装 consul配置 patroni配置 vip-manager配置 pgbouncer配置 haproxy配置 验证 本文将介绍如何使用Patroni、Consul、vip-manager、Pgbouncer、HaProxy组件来部署一个3节点的高可用、高吞吐、负载均衡的PostgresSQL集群(14版本)&…...
JavaScript 对事件的反应机制
JavaScript 对事件的反应机制 JavaScript 对事件的反应机制是网页实现用户交互的核心,主要通过事件监听与处理函数实现对用户行为的响应。以下是关键要点解析: 一、事件机制基础 1. 事件的定义 事件是用户或浏览器在页面上的动作(如点击、…...
Vue3中keep-alive缓存组件应用场景。
文章目录 一、KeepAlive是什么?二、基本使用1.例子2.keep-alive使用 三、其他属性3.1 包含/排除3.2 最大缓存实例数3.3 缓存实例的生命周期 总结 一、KeepAlive是什么? 是一个内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例…...
Pythonload JSON文件需要手动关闭吗?
在Python中使用 json 模块加载JSON文件时,通常不需要手动关闭文件。 例如,使用以下方式加载JSON文件: import json with open(data.json, r) as f: data json.load(f) 在上述代码中,使用 with 语句打开文件,它会在代码…...
SCI论文阅读指令(特征工程)
下面是一个SCI论文阅读特征工程V3.0,把指令输入大模型中,并上传PDF论文,就可以帮你快速阅读论文。 优先推荐kimi,当然DeepSeek、QwQ-32B等大语言模型也可以。测试了一下总结的还不错,很详细。 请仔细并深入地阅读所提…...
CosyVoice2在Windows系统上本地部署的详细步骤
CosyVoice2在Windows系统上本地部署的详细步骤: 下载源码并初始化: 确保你的设备上安装了Git。打开命令提示符(cmd),执行以下命令来克隆仓库:git clone --recursive https://github.com/FunAudioLLM/CosyVo…...
鸿蒙入门——ArkUI 跨页面数据同步和应用全局单例的UI状态存储AppStorage 小结(三)
文章大纲 引言一、AppStorage 应用全局的UI状态存储1、StorageProp和StorageLink装饰器建立联系2、StorageProp2.1、StorageProp使用规则2.2、StorageProp变量的传递/访问规则2.3、StorageProp支持的观察变化2.4、StorageProp 值初始化和更新 3、StorageLink3.1、StorageLink使…...
RabbitMQ 核心组件及功能详解
RabbitMQ 是一个开源的消息代理和队列服务器,其核心架构由以下关键组件构成: 一、核心组件架构 #mermaid-svg-mIHqbpvVt25Kpyl0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-mIHqbpvVt25Kpyl0 .error-icon{fil…...
海思烧录工具HITool电视盒子刷机详解
HiTool是华为开发的一款用于海思芯片设备的刷机和调试工具,可对搭载海思芯片的机顶盒、智能电视等设备进行固件烧录、参数配置等操作。以下为你详细介绍: 功能用途 固件烧录:这是HiTool最主要的功能之一。它能够将下载好的适配固件文件烧录到…...
探秘 C++ 双星系统模型:实现快速值切换
在软件开发的世界里,有时我们会遇到需要频繁在两个值之间进行切换的场景。为了高效地处理这类情况,我们可以设计一个专门的类来实现这个功能。今天,我们就来详细介绍一个用 C 实现的双星系统模型类 Turner,它能够帮助我们轻松地在…...
AI 生成内容(AIGC):从文本到视频的完整流程
近年来,AI 生成内容(AIGC, AI-Generated Content) 迅速发展,从文本、图片到音频、视频,AI 在创意内容生成方面展现出了惊人的能力。AIGC 不仅提升了内容创作效率,还降低了成本,使得普通用户也能…...
使用VS2022编译CEF
前提 选择编译的版本 CEF自动编译,在这里可以看到最新的稳定版和Beta版。 从这里得出,最新的稳定版是134.0.6998.118,对应的cef branch是6998。通过这个信息可以在Build requirements查到相关的软件配置信息。 这里主要看Windows下的编译要…...
WebMvcConfigurer 的 addResourceLocations
在 Spring Boot 的 addResourceLocations 方法中,file: 是一个 URL 前缀,用于指示资源的位置是本地文件系统路径。以下是详细解释: 一、file: 的作用 file: 是 Java 中用于表示本地文件系统的 URL 前缀。它告诉 Spring Boot,资源…...
Pytorch学习笔记(八)Learn the Basics - Save and Load the Model
这篇博客瞄准的是 pytorch 官方教程中 Learn the Basics 章节的 Save and Load the Model 部分。 官网链接:https://pytorch.org/tutorials/beginner/basics/saveloadrun_tutorial.html 完整网盘链接: https://pan.baidu.com/s/1L9PVZ-KRDGVER-AJnXOvlQ?pwdaa2m …...
正则表达式基本语法和Java中的简单使用
先来个例子 public static final Pattern CHINESE_PATTERN Pattern.compile("[\\u4e00-\\u9fa5]"); / 检测字符串是否包含汉字 String text "Hello 世界"; boolean hasChinese CHINESE_PATTERN.matcher(text).find(); // 返回 true// 提取所有汉字 Mat…...
Mysql 回表查询,什么是回表查询,如何拒绝sql查询时的回表问题
文章目录 1. 什么是回表(回表查询)2. 如何减少回表3. 使用案例3.1 问题分析3.2 避免回表查询3.3 开始优化前言: 在继续讲解专栏内容之前,先学习几个概念,以便更好了解: 什么是聚簇索引什么是回表查询这篇文章详细分析 回表查询。聚簇索引的理解可以进入这篇文章:什么是聚…...
Spring Boot响应压缩配置与优化
一、核心工作机制 1.1 自动协商触发条件 Spring Boot的响应压缩功能基于智能协商机制,需同时满足以下条件方可触发: 客户端支持:请求头包含Accept-Encoding: gzip/deflate数据量阈值:响应体大小超过预设值(默认2KB&…...
常考计算机操作系统面试习题(三上)
目录 1. 为何要引入与设备的无关性?如何实现设备的独立性? 2. 页面置换先进先出算法 3. 页面置换先进先出算法,4个页框 4. 进程优先级调度算法 5. 短作业优先调度策略 6. 平均内存访问时间计算 7. 页式存储和段式存储的物理地址计算 …...
