我在阅读/管理文献一直用的就是zotero(version6),在写本科毕业论文的时候感受到了zotero在查找文献、管理文献、参考引用文献等方面的便捷性,但一直有个小问题没来得及去解决,拖到了现在:
如何用zotero实现word的交叉引用?
虽然zotero可以结合word中的zotero选项,通过插入引用位置,添加文献,刷新三个操作直接实现参考文献的管理,如下图所示:
但我们很容易就发现,此时的引用位置和实际参考文献的位置只是做到了一一对应,并没有实现交叉引用的跳转,这其实不符合我们参考文献的要求的。如下:
于是我们就开始信息检索,搞一搞,解决一下hh
下载配置zotero citation插件
注意Releases中的插件版本和zotero版本对应hh
word配置宏
- 创建新的宏,这里命名为:ZoteroLinkCitation
- 编辑代码,直接应用下面开源代码即可
Public Sub ZoteroLinkCitation()
' get selected area (if applicable)
Dim nStart&, nEnd&
nStart = Selection.Start
nEnd = Selection.End
' toggle screen updating
Application.ScreenUpdating = False
' define variables
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
' find the Zotero bibliography
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 With
Selection.Find.Execute
' add bookmark for the Zotero bibliography
With ActiveDocument.Bookmarks
.Add Range:=Selection.Range, Name:="Zotero_Bibliography"
.DefaultSorting = wdSortByName
.ShowHidden = True
End With
' loop through each field in the document
For Each aField In ActiveDocument.Fields
' check if the field is a Zotero in-text reference
'##################################################
If InStr(aField.Code, "ADDIN ZOTERO_ITEM") > 0 Then
fieldCode = aField.Code
'#############
' Prepare
' Plain citation== Format of Textfield shown
' must be in Brackets
Dim plain_Cit As String
plCitStrBeg = """plainCitation"":""["
plCitStrEnd = "]"""
n1 = InStr(fieldCode, plCitStrBeg)
n1 = n1 + Len(plCitStrBeg)
n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), plCitStrEnd) - 1 + n1
plain_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 String
i = 0
Do While InStr(fieldCode, """title"":""") > 0
n1 = InStr(fieldCode, """title"":""") + Len("""title"":""")
n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), """,""") - 1 + n1
If n2 < n1 Then 'Exception the type 'Article'
n2 = InStr(Mid(fieldCode, n1, Len(fieldCode) - n1), "}") - 1 + n1 - 1
End If
array_RefTitle(i) = Mid(fieldCode, n1, n2 - n1)
fieldCode = Mid(fieldCode, n2 + 1, Len(fieldCode) - n2 - 1)
i = i + 1
Loop
Titles_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 here
Dim RefNumber(32) As String
i = 0
Do While (InStr(plain_Cit, "]") Or InStr(plain_Cit, "[")) > 0
n1 = 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 + 1
Loop
Refs_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 Then
array_RefTitle(Refs_in_Cit - 1) = array_RefTitle(Titles_in_Cit - 1)
i = 1
Do While Refs_in_Cit + i <= Titles_in_Cit
array_RefTitle(Refs_in_Cit + i - 1) = ""
i = i + 1
Loop
End If
'#############
'Make the links
For Refs = 0 To Refs_in_Cit - 1 Step 1
title = array_RefTitle(Refs)
array_RefTitle(Refs) = ""
' make title a valid bookmark name
titleAnchor = title
titleAnchor = MakeValidBMName(titleAnchor)
ActiveWindow.View.ShowFieldCodes = False
Selection.GoTo What:=wdGoToBookmark, Name:="Zotero_Bibliography"
'' locate the corresponding reference in the bibliography
'' by searching for its title
Selection.Find.ClearFormatting
With Selection.Find
.Text = Left(title, 255)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute
' select the whole caption (for mouseover tooltip)
Selection.MoveStartUntil ("["), Count:=wdBackward
Selection.MoveEndUntil (vbBack)
lnkcap = "[" & Selection.Text
lnkcap = Left(lnkcap, 70)
' add bookmark for the reference within the bibliography
Selection.Shrink
With ActiveDocument.Bookmarks
.Add Range:=Selection.Range, Name:=titleAnchor
.DefaultSorting = wdSortByName
.ShowHidden = True
End With
' jump back to the field
aField.Select
' find and select the numeric part of the field which will become the hyperlink
Selection.Find.ClearFormatting
With Selection.Find
.Text = RefNumber(Refs)
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute
numOrYear = Selection.Range.Text & ""
' store current style这一行如果不注释可能会存在格式变化
' style = Selection.style
' Generate the Hyperlink -->Forward!
ActiveDocument.Hyperlinks.Add Anchor:=Selection.Range, Address:="", SubAddress:=titleAnchor, ScreenTip:=lnkcap, TextToDisplay:="" & numOrYear
' reset the style这一行如果不注释可能会存在格式变化
' Selection.style = style
' comment if you want standard link style
aField.Select
With Selection.Font
.Underline = wdUnderlineNone
.ColorIndex = wdBlack
End With
Next Refs 'References in Cit
End If 'If Zotero-Field
'#########################
Next aField ' next field
' go back to original range selected
ActiveWindow.View.ShowFieldCodes = False
ActiveDocument.Range(nStart, nEnd).Select
End Sub
Function MakeValidBMName(strIn As String)
Dim pFirstChr As String
Dim i As Long
Dim tempStr As String
strIn = Trim(strIn)
pFirstChr = Left(strIn, 1)
If Not pFirstChr Like "[A-Za-z]" Then
strIn = "A_" & strIn
End If
For i = 1 To Len(strIn)
Select Case Asc(Mid$(strIn, i, 1))
Case 49 To 57, 65 To 90, 97 To 122
tempStr = tempStr & Mid$(strIn, i, 1)
Case Else
tempStr = tempStr & "_"
End Select
Next i
tempStr = Replace(tempStr, " ", " ")
MakeValidBMName = Left(tempStr, 40)
End Function
保存,重启word
- 打开宏命令-查看宏
- 运行刚才的宏:ZoteroLinkCitation
运行宏,没问题的,宏命令选项卡会直接消失。
验证交叉引用功能
经过验证,发现交叉引用功能没有问题了。
但这时候发现,ctrl+鼠标后的跳转,数字的颜色将从黑色变成紫色,以为只是影响word预览状态,结果打印pdf和保存后确实就是紫色(虽然后知后觉是超链接的颜色设置,但当时以为是宏命令中的颜色设置问题),就继续搞一搞hh
修改宏命令中的VBA代码
结合zotero的官方论坛和gpt的指导,做出修改如下:
定位到代码块:
With Selection.Font
.Underline = wdUnderlineNone
.Color = wdColorBlack
End With
将.ColorIndex = wdBlack
更改为.Color = wdColorBlack
,因为ColorIndex属性用于较旧版本,貌似更改为.ColorIndex = wdColorBlack
也一样,我都试了,效果没啥区别,因为都没用hhh
后来发现,这个修改颜色的功能代码块只是作用到参考文献的上标显示颜色,而并不影响交叉引用跳转后的情况
又去疯狂信息检索,发现没有这个解决的方法,只是零零星星有人也反映了这个问题,如:
为什么点击超链接后会变色啊?
变紫色是什么情况?有人解决嘛?
哎等等,这个本质是超链接啊! 那这样,就和插件中的代码没关系了,代码是没问题的,那只需要设置word中超链接的颜色情况就行了
- word-设计
- 颜色-自定义的颜色-已访问的超链接-设置成黑色
ok解决~
ps:在解决问题的过程中,又看到了如何用Word批量修改交叉引用、Zotero Citation等的字体颜色
这个还是很实用功能,在我有一次写本子的过程中,要求参考文献是蓝色,就需要手动调颜色,当参考文献到200+的时候,就很难受了,正好也搞一搞hh
类比上述的宏-VBA代码,这个也是新建一个宏,命名为CitingColor,复制代码如下:
Sub CitingColor()
For i = 1 To ActiveDocument.Fields.Count '遍历文档所有域
If Left(ActiveDocument.Fields(i).Code, 4) = " REF" Or Left(ActiveDocument.Fields(i).Code, 14) = " ADDIN EN.CITE" Or Left(ActiveDocument.Fields(i).Code, 31) = " ADDIN ZOTERO_ITEM CSL_CITATION" Then 'Word自带的交叉引用的域代码起始4位是" REF"(注意空格),EndNote插入的引用域代码的起始14位是" ADDIN EN.CITE",Zotero插入的引用域代码的起始31位是" ADDIN ZOTERO_ITEM CSL_CITATION"。根据需求可添加其他类型。
ActiveDocument.Fields(i).Select '选中上述几类域
Selection.Font.Color = wdColorBlue '设置字体颜色为蓝色,也可以使用以下代码设置为任意颜色Selection.Font.Color = 12673797
End If
Next
End Sub
这样再搭配上面提到的修改word中已访问的超链接颜色,就可以实现数字和括号都能变为指定颜色。这里以蓝色为例。
但这样出现了新的问题,word超链接本身的蓝色和宏命令代码中的蓝色并不一致,需要调整一下配色:
下面是常见的蓝色超链接配色
- RGB:(0,0,255)
- Google的超链接颜色码:RGB:(42,30,177) ;RGB: (38, 25, 175);RGB: (32, 19, 173)
- 百度超链接颜色码:RGB: (53, 85, 188) ;RGB: (46, 68, 180);RGB: (36, 64, 179)
- 维基百科超链接颜色码:RGB:(6, 69, 173) ;RGB(51,102,204)
查看word(2019)中的已访问超链接颜色,确认是RGB(5,99,193)
直接选取在代码块中的Selection.Font.Color = wdColorBlue
位置进行修改即可Selection.Font.Color = RGB(5, 99, 193)
至此,完成了更改交叉引用颜色的配置,并避免了超链接颜色与引用本身颜色的不一致性。
完结撒花!~
总结
当项目/课题不需要交原稿word的时候,还是latex舒服,因为不是word不好用,而是很多功能隐藏太深,需要深度了解word的人才懂,有这个时间我觉得latex都更熟了(bushi。当然,很多情况下(真的是很多!)是需要交word版稿的,那只能硬着头皮让工作更丝滑一下啦hh~
参考
感谢下面的文章(不分先后顺序)
https://zhuanlan.zhihu.com/p/674910734
https://forums.zotero.org/discussion/comment/332882#Comment_332882
https://forums.zotero.org/discussion/77079/ms-word-macro-to-convert-zotero-citations-into-clickable-hyperlinks
https://affinity.help/publisher2/zh-Hans.lproj/index.html?page=pages/Advanced/aboutCrossrefs.html&title=%E5%85%B3%E4%BA%8E%E4%BA%A4%E5%8F%89%E5%BC%95%E7%94%A8
https://zhuanlan.zhihu.com/p/533318295
https://www.haoyep.com/posts/word-zotero-citation/
https://github.com/altairwei/ZoteroLinkCitation/tree/master
https://www.bilibili.com/read/cv18943916/
感谢分享,之前发现zotero不能交叉引用,看到了您这篇文章,学习一下。
一起学习进步~
感谢您的分享,受益良多,谢谢~
不客气~一起学习,一起进步呀hh