Получите информацию о заголовке, используя цикл поиска с подстановочными знаками в MS Word, используя VBA

Я выполняю цикл поиска по подстановочным знакам в MS Word и генерирую список всех найденных значений в новом документе, используя следующий код. Я добавил номера страниц в вывод. Но я не могу придумать, как получить заголовки для искомого вывода. Пожалуйста, предложите.

Образец документа Word:

1 Heading
Text Text Text Text Text

--<Page Break>--

1.1 Heading
Text Text Text Text Text [Reference X1]

1.1.1 Heading
Text Text Text Text Text
Text Text Text Text Text
Text Text Text Text Text

--<Page Break>--

1.2 Heading
Text Text Text Text Text

1.2.1 Heading
Text Text Text Text Text
Text Text Text Text Text [Reference X2]
Text Text Text Text Text [Reference X3]

Заголовки 1, 1.1 и т. д. являются стилями заголовков по умолчанию, используемыми в MS Word. (Для меня название стиля — Заголовок 1, Заголовок 2 и т. д.)

Результат, который я ожидаю, такой же, как и в табличном формате:

| Reference     | Heading        | Page  |
| Reference X1  | 1.1 Heading    | 2     |
| Reference X2  | 1.2.1 Heading  | 3     |
| Reference X2  | 1.2.1 Heading  | 3     |

Код (часть подраздела, который выполняет поиск и запись в таблицу), который я смог написать до сих пор:

With oDoc
    Set oRange = .Range
    n = 1
    With oRange.Find
        .Text = "<Reference X[0-9]{1,}>"
        .Forward = True
        .MatchWildcards = True
        Do While .Execute
            strFound = oRange
            With oTable
                .Cell(n+1,1).Range.Text = strFound
                .Cell(n+1,3).Range.Text = oRange.Information(wdActiveEndPageNumber)
            End With
            n = n + 1
        Loop
    End With
End With

У меня уже есть код для определения этих переменных, создания таблицы и необходимых строк в ней. Меня только смущает, как получить заголовок чуть выше найденного элемента. Проблема в том, что под одним заголовком может быть одна или несколько ссылок XX. Далее уровень заголовка может быть любым. И мне нужны отдельные строки для каждого элемента, найденного с использованием подстановочного знака.


person Meet    schedule 15.04.2021    source источник


Ответы (2)


Например:

Sub GetRefHeadings()
Application.ScreenUpdating = False
Dim Rng As Range, StrOut As String, Tbl As Table
StrOut = "Ref." & vbTab & "Heading" & vbTab & "Page" & vbCr
With ActiveDocument.Range
  With .Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Text = "<Reference X[0-9]@>"
    .Replacement.Text = ""
    .Format = False
    .Forward = True
    .Wrap = wdFindStop
    .MatchWildcards = True
  End With
  Do While .Find.Execute
    Set Rng = .Paragraphs(1).Range
    Set Rng = Rng.GoTo(What:=wdGoToBookmark, Name:="\HeadingLevel")
    StrOut = StrOut & .Text & vbTab & Rng.Paragraphs.First.Range.ListFormat.ListString & _
      " " & Split(Rng.Text, vbCr)(0) & vbTab & Rng.Information(wdActiveEndPageNumber) & vbCr
  Loop
End With
Set Rng = ActiveDocument.Range.Characters.Last
Rng.Text = StrOut
Set Tbl = Rng.ConvertToTable(Separator:=vbTab)
With Tbl
  .PreferredWidthType = wdPreferredWidthPercent
  .PreferredWidth = 100
  .Columns.PreferredWidthType = wdPreferredWidthPercent
  .Columns(1).PreferredWidth = 20
  .Columns(2).PreferredWidth = 70
  .Columns(3).PreferredWidth = 10
  .Rows(1).Range.Font.Bold = True
  .Rows(1).HeadingFormat = True
  '.Sort ExcludeHeader:=True, FieldNumber:=1
End With
Set Rng = Nothing: Set Tbl = Nothing
Application.ScreenUpdating = True
End Sub

Если вам нужна страница # найденного текста, а не страница # заголовка, измените Rng.Information на .Information.

Порядок сортировки по умолчанию определяется по ссылке, независимо от номера ссылки, что совпадает с сортировкой по заголовку. Код также включает закомментированную строку для сортировки по номеру ссылки.

person macropod    schedule 15.04.2021
comment
Может в этом чего-то не хватает. Я запустил это, и он генерирует только таблицу ‹Ref. Заголовок› в конце документа. Не получает содержимое под этой таблицей. - person Meet; 16.04.2021
comment
Содержит ли ваш тестовый документ какой-либо указанный контент (т.е. ссылка X1, ссылка X2 и т. д.)??? Код работает просто отлично, если он работает! - person macropod; 16.04.2021
comment
Ой, извини. Виноват. Это работает. Хорошо понимает заголовки. Спасибо. Только одно, он получает название заголовка (текст), но пропускает номера заголовков 1.1, 1.1.1 и т. д. Есть ли способ получить это? - person Meet; 16.04.2021
comment
Попробуйте исправленный код. - person macropod; 16.04.2021
comment
Идеальный друг! Большое спасибо. Я пытался добавить .Range.Paragraph(1).Range.ListFormat.ListString в строку после оператора GoTo, но это не сработало. Я также пытался использовать метод ActiveDocument.Bookmarks для этого. Но в этом случае я искал ссылки в одном документе и вставлял таблицу ссылок в другой документ внутри цикла. Итак, active document.bookmark искал заголовки в новом документе, а не в документе, в котором работал .find, что опять-таки было неправильно. Спасибо, ваш код решает это. - person Meet; 16.04.2021

Вы можете найти уровень заголовка раздела текста, который вы нашли, используя предустановленная закладка. Так как этот трюк использует объект Selection, вам нужно передать найденный диапазон текста в Selection. Этот фрагмент кода ниже показывает, как:

Option Explicit

Sub test()
    With ActiveDocument
        Dim foundThis As Range
        Set foundThis = .Range
        With foundThis.Find
            .Text = "<Reference X[0-9]{1,}>"
            .Forward = True
            .MatchWildcards = True
            Do While .Execute
                Dim strFound As String
                Dim heading As String
                strFound = foundThis.Text
                heading = foundThis.GoTo(What:=wdGoToBookmark, _
                                         Name:="\HeadingLevel").Paragraphs(1).Range.Text
                Debug.Print "string found: " & strFound & " on page " & _
                            foundThis.Information(wdActiveEndPageNumber) & _
                            ", Heading: " & heading
            Loop
        End With
    End With
End Sub
person PeterT    schedule 15.04.2021
comment
Хотя использование предопределенной закладки является правильным способом получения уровня заголовка, абсолютно нет необходимости использовать Selection. Подсказка: GoTo возвращает диапазон - person Timothy Rylatt; 15.04.2021
comment
@TimothyRylatt - спасибо за совет. Я не так часто использовал GoTo, поэтому научился. Код обновляется в ответе. - person PeterT; 16.04.2021