批量重命名 Word .docx 文件中的多个书签

批量重命名 Word .docx 文件中的多个书签

是否可以在标准 Word 97-2003 文档文件中重命名多个书签?我刚刚在 Word 2010 中完成了一份 400 页的文档,其中有数百个必须重命名的书签,我绝对不想手动重命名它们。我发现Word 插件用于增强内置的 Word 书签对话框,但似乎无法将其正确加载到我的文档中,如果我可以让它工作,它将解决我的问题。在此之前,还有其他直接的方法可以实现这一点吗?也许可以使用宏来实现。现在,我想看看 OpenOffice 是否支持批量重命名 docx 文件中的书签。非常感谢您的帮助。

答案1

您可以使用 Word 中的 VBA 宏来执行此操作。下面的宏取自这里(并在网页上进行了更详细的讨论),将在每个现有书签名称前面添加“NEW_”,但可以按照所需的任何约定来重命名书签。

Sub RenameBookmarks()
'  although it does NOT rename them
'  it creates a new one for the same range
'  then deletes the old one

Dim BM_Names()
Dim i As Long
With ActiveDocument
  For i = 1 To .Bookmarks.Count
    ReDim Preserve BM_Names(i)
    BM_Names(i) = .Bookmarks(i).Name
  Next
  For i = 1 To .Bookmarks.Count
    With .Bookmarks(BM_Names(i))
      .Range.Bookmarks.Add Name:="NEW_" & .Name, Range:=.Range
      .Delete
    End With
  Next
End With
End Sub

答案2

joeschwa 的回答很好,但我想稍微扩展一下,是有充分理由的。 因为看起来您无法直接编辑书签名称,所以您必须像 joeschwa 那样,添加新名称,然后删除原始书签。 问题是,这会产生不良的副作用:文档中对原始书签的所有现有引用都将被破坏!

为了解决这个问题,必须将引用重定向到新的书签名称。下面的代码处理了这个问题。它做了 3 件事:

  1. 它首先根据需要创建新的书签名称,然后删除旧书签名称 - 方式类似于 joeschwa 的代码。

(不过请注意代码中的注释。我提供了一种在选定区域而不是整个文档中执行此操作的方法;此外,我还提供了一种处理以不同前缀为特征的书签组的方法。例如,如果您想将所有以“C1_”前缀开头的书签更改为以“CH1_”前缀开头的书签,您可以这样做,而不会影响其他书签)。

  1. 它将所有内容引用重定向到文档主体中新重命名的书签。

  2. 它将文档所有部分的所有类型的所有页眉和页脚(在部分的第一页上、在部分的其他页面上等)中所有对新重命名的书签的引用重定向。

' By Yiftach, 2018-4-9
'   There's no option in word to rename bookmarks, so this: _
    1.  creates a new one for the same range, then deletes the old one, and _
    2.  Fixes all existing cross-references in the doc, so that any references to old bookmarks are _
        re-routed to the respective new bookmarks which replaced them
          
'   This is especially useful for BULK/BATCH renaming. This assumes there's a pattern in bookmark names. _
    I.e. that a certain substring in a group of bookmarks is replaced by another substring. _
    e.g. if all bookmarks in chapter 1 start with "C1_", and I'm switching chapter order and want to _
    rename them "C2_". (But of course it can be used to replace a single bookmark as well).
    
'NOTE: Currently the old and new texts are hard coded as CONSTs at the top of the code. Adapt as needed.

'*****************EXTREME WARNING: Bookmark names must not contain the string "REF" ***********************
'*
'*        (in whatever case)!!! because of how i fix references to renamed bookmarks.
'*                  THIS CAN FUCK UP ALL REFERENCES IN THE DOC, IRREVERSABLY!
'*
'************************************************************************************************

Const old_txt_in_bookmark_names As String = "C1_"   'change as needed
Const new_txt_in_bookmark_names As String = "C2_"   'change as needed

'PART 1: RENAME BOOKMARKS (creates new bookmarks and deletes old)
    Dim bm As Bookmark
    
    For Each bm In ActiveDocument.Bookmarks 'activedocument.bookmarks can be replaced with selection.bookmarks as needed
        If InStr(1, bm.Name, old_txt_in_bookmark_names, vbTextCompare) > 0 Then 'if you want to replace ALL bookmark names in the doc/selection _
                                                                                regardless of their prefix, remove the if statement and just _
                                                                                leave the next line
            bm.Range.Bookmarks.Add Name:=Replace(bm.Name, old_txt_in_bookmark_names, new_txt_in_bookmark_names), Range:=bm.Range
            bm.Delete
        End If
    Next bm

'PART 2: edit referenecs to the bookmarks that were renamed
'   2.1 In the main body of the doc (this doesn't treat headers and footers) _
'       (   even if in PART1 I choose to only rename bookmarks in the selection rather than in the entire doc _
            I still want to ensure that all cross-references in the doc are pointing to the renamed bookmarks correctly!)

    Dim doc As Word.Document
    
    Set doc = ActiveDocument
    If doc.Fields.count >= 1 Then
            For i = 1 To doc.Fields.count
                fieldStr = doc.Fields(i).Code.Text
                If Left(fieldStr, 4) = " REF" Then
                    doc.Fields(i).Code.Text = Replace(fieldStr, old_txt_in_bookmark_names, new_txt_in_bookmark_names, , 1, vbTextCompare)
                    doc.Fields(i).Update
                End If
            Next i
    End If

'   2.2 In the doc headers and footers, in all doc sections

    For s = 1 To ActiveDocument.Sections.count
        For HFT = 1 To 3    'HFT stands for Header-Footer type, according to the WdHeaderFooterIndex Enumeration
                            '  Name                  Value Description
                            '  wdHeaderFooterEvenPages 3   Returns all headers or footers on even-numbered pages.
                            '  wdHeaderFooterFirstPage 2   Returns the first header or footer in a document or section.
                            '  wdHeaderFooterPrimary   1   Returns the header or footer on all pages other than the first page of a document or section.
    
        '   2.2.1   Treating references in HEADERS
            If doc.Sections(s).Headers(HFT).Range.Fields.count >= 1 Then
                For i = 1 To doc.Sections(s).Headers(HFT).Range.Fields.count
                    fieldStr = doc.Sections(s).Headers(HFT).Range.Fields(i).Code.Text
                    If Left(fieldStr, 4) = " REF" Then
                        doc.Sections(s).Headers(HFT).Range.Fields(i).Code.Text = Replace(fieldStr, old_txt_in_bookmark_names, new_txt_in_bookmark_names, , 1, vbTextCompare)
                        doc.Sections(s).Headers(HFT).Range.Fields.Update
                    End If
                Next i
            End If
        '   2.2.2   Treating references in FOOTERS
            If doc.Sections(s).Footers(HFT).Range.Fields.count >= 1 Then
                For i = 1 To doc.Sections(s).Footers(HFT).Range.Fields.count
                    fieldStr = doc.Sections(s).Footers(HFT).Range.Fields(i).Code.Text
                    If Left(fieldStr, 4) = " REF" Then
                        doc.Sections(s).Footers(HFT).Range.Fields(i).Code.Text = Replace(fieldStr, old_txt_in_bookmark_names, new_txt_in_bookmark_names, , 1, vbTextCompare)
                        doc.Sections(s).Footers(HFT).Range.Fields.Update
                    End If
                Next i
            End If
        Next HFT
    Next s
End Sub


相关内容