这是一个头分裂器: 我试图以编程方式为文档中的现有标题创建隐藏的书签,以便我可以在文档中的其他位置创建指向这些书签的超链接。 (我想使用超链接而不是交叉引用,因此我可以为链接指定我自己的“显示文本”,这不可能使用交叉引用)。
我希望我的书签以与其相关的标题命名,并带有自定义前缀。 示例:
我指定了一个自定义前缀,使每个书签都具有独特的风格,因此我可以在文档中有两个匹配的标题,只要它们采用不同的标题样式即可。 (示例: _Hd1_Entrance_& _Hallway 和 _Hd3_Entrance_& _Hallway )
问题是:如果我的标题中包含特殊字符,例如'&',我会收到一个错误的书签名称'错误,我理解,这是在网上记录的。我只允许使用有限的字符集。
那么,如果我使用Word自己的对话框手动创建一个超链接,选择一个'放置在此文档中'比如"入口&走廊",Word管理这个没问题?创建Hlink后,我现在可以在Word'书签'中看到与此Hlink关联的隐藏书签。对话 - 它非常愉快地命名为" _Entrance _& _Hallway"。这让我很困惑!
有人有解释吗?我真的希望能够利用相同的功能,但无法理解如何。任何帮助都非常有价值! 谢谢,
Sub ScratchPad_Bookmarks()
Dim doc As Document
Dim rng As Range
Dim sHdName As String
Dim sBmName As String
Set doc = ActiveDocument
'Insert a heading at start of document
sHdName = "Entrance & Hallway"
doc.Range.InsertBefore sHdName & vbCr
doc.Paragraphs(1).Range.Style = doc.Styles("Heading 1")
'Find the above heading in the active document
Set rng = doc.Range
With rng.Find
.ClearFormatting
.Text = sHdName
.Style = "Heading 1"
If Not .Execute Then
'Heading not found, so quit
Exit Sub
End If
End With
'rng has collapsed to the found heading, so create a bookmark
'rng.Select 'debug
sBmName = Replace(rng.Text, " ", "_")
rng.Collapse wdCollapseStart
rng.Bookmarks.Add sBmName
'sBmName contains '&' so this throws a Runtime error:
'5828: Bad Bookmark Name (as expected)
End Sub
以上不起作用。但是,要自己测试手动操作很容易。只需创建一个标题,其中包含'&'字符,将其设为标题1 。 在下一段中,使用Word自己的对话框插入超链接。选择放置此文档并选择刚刚创建的标题。不应该是一个问题。 现在打开Word的书签对话框,启用隐藏书签视图,然后选择隐藏的书签,其中包含'&'字符。 (Wd 2010)说什么?!
答案 0 :(得分:2)
IMO Word是“作弊”,要么通过破坏自己的书签名称规则,要么拒绝给出规范允许的全部名称。
如果你回到.docx的早期ECMA标准,书签的名字被定义为ST_String,这是xsd:string的限制,最大长度为255个字符。我认为,自ECMA或ISO版本的任何标准以来,这都没有改变。
但是,Microsoft的实施说明[MS-OE376] .pdf,它与规范的ECMA版本有关,而[MS-OI29500] .pdf与2012 ISO版本有关,则指明该名称可以为no超过40个字符,但不描述任何其他限制。
我(之前)的理解是书签名称限制为40个字符,必须由“字母”,“数字”和“下划线”组成,并且必须以下划线(隐藏书签)或字母开头。 (不确定,例如“_1”)。我相信VBA仍然会强制执行这些规则,尽管我从未检查过它对“字母”或“数字”的理解是什么 - 是否允许使用非拉丁字母/数字?
但是,如果您将文档另存为.xml或在.docx中编辑document.xml,则可以修改书签名称,使其包含,例如: “&安培;”。此外,Word将重新保存这些字符。但是,当您打开时,它会将名称截断为40个字符,并且在您重新保存时它不会保留原始名称。我认为使用初始“_”来表示“隐藏”也不在标准中。
因此,根据规范,我会说Word是“作弊”,因为不允许您使用全部可能的名称,而不是通过允许超链接目的地包含“&”来“欺骗”。
您可以使用“&”插入书签在Windows版本的VBA中使用InsertXML插入一大块带有预配置书签名称的XML(请参阅下面的一些简单示例代码),但我怀疑您必须更加努力地移动书签。你可能不得不提取你想要“覆盖”的东西的现有XML,然后用bookmarkStart和bookmarkEnd标签包围它,这对我来说听起来像是一个非常讨厌的练习。
作为最后的观察,AFAICR您可以为旧表单字段指定的书签名称具有20个字符的长度限制。
那段代码:
Sub insertbm()
Dim x As String
x = ""
x = x & "<?xml version='1.0' encoding='utf-8' standalone='yes'?>"
x = x & "<pkg:package xmlns:pkg='http://schemas.microsoft.com/office/2006/xmlPackage'>"
x = x & " <pkg:part pkg:name='/_rels/.rels' pkg:contentType='application/vnd.openxmlformats-package.relationships+xml'>"
x = x & " <pkg:xmlData>"
x = x & " <Relationships xmlns='http://schemas.openxmlformats.org/package/2006/relationships'>"
x = x & " <Relationship Id='rId1' Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument' Target='word/document.xml' />"
x = x & " </Relationships>"
x = x & " </pkg:xmlData>"
x = x & " </pkg:part>"
x = x & " <pkg:part pkg:name='/word/document.xml' pkg:contentType='application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml'>"
x = x & " <pkg:xmlData>"
x = x & " <w:document xmlns:w='http://schemas.openxmlformats.org/wordprocessingml/2006/main'>"
x = x & " <w:body>"
x = x & " <w:p>"
x = x & " <w:bookmarkStart w:id='0' w:name='bookmark&name' />"
x = x & " <w:r>"
x = x & " <w:t>"
x = x & "bookmarkedtext</w:t>"
x = x & " </w:r>"
x = x & " <w:bookmarkEnd w:id='0' />"
x = x & " </w:p>"
x = x & " </w:body>"
x = x & " </w:document>"
x = x & " </pkg:xmlData>"
x = x & " </pkg:part>"
x = x & "</pkg:package>"
Selection.InsertXML x
End Sub