Insert First Sentences and TOC

November 2025

This is another attempt to use Claude to write a macro that creates a reverse outline of a document. It uses the first sentence of each paragraph to create headings for each paragraph, then creates a table of contents based on those headings, as well as any the writer has previously created.

Sub InsertFirstSentencesAndTOC()
Dim doc As Document
Dim para As Paragraph
Dim firstSentence As String
Dim sentenceEnd As Long
Dim paraText As String
Dim sourceRange As Range
Dim newPara As Paragraph
Dim userStyle As String
Dim i As Long
Dim paraCount As Long
Dim tocRange As Range
' Get the active document
Set doc = ActiveDocument

' Ask user for the style to apply
userStyle = inputBox("Enter the Microsoft Word style name to apply to the first sentence headings:" & vbCrLf & vbCrLf & _
                     "Examples:" & vbCrLf & _
                     "• Heading 1" & vbCrLf & _
                     "• Heading 2" & vbCrLf & _
                     "• Heading 3" & vbCrLf & _
                     "• Subtitle" & vbCrLf & _
                     "• Title" & vbCrLf & _
                     "• Emphasis", _
                     "Select Heading Style", _
                     "Heading 2")

' Check if user cancelled
If userStyle = "" Then
    MsgBox "Operation cancelled.", vbInformation
    Exit Sub
End If

' Check if the style exists in the document
On Error Resume Next
Dim testStyle As Style
Set testStyle = doc.Styles(userStyle)
If Err.Number <> 0 Then
    MsgBox "The style '" & userStyle & "' does not exist in this document." & vbCrLf & vbCrLf & _
           "Please check the style name and try again.", vbExclamation, "Style Not Found"
    Exit Sub
End If
On Error GoTo 0

' Get initial paragraph count
paraCount = doc.Paragraphs.count

' Loop through paragraphs in reverse order to avoid issues with inserting new paragraphs
For i = paraCount To 1 Step -1
    Set para = doc.Paragraphs(i)

    ' Get paragraph text and trim whitespace
    paraText = Trim(para.Range.text)

    ' Skip empty paragraphs
    If Len(paraText) > 1 Then
        ' Find the first sentence by looking for sentence-ending punctuation
        sentenceEnd = 0

        ' Look for period, exclamation mark, or question mark
        Dim j As Long
        For j = 1 To Len(paraText)
            If Mid(paraText, j, 1) = "." Or Mid(paraText, j, 1) = "!" Or Mid(paraText, j, 1) = "?" Then
                ' Check if it's not an abbreviation or decimal
                If j < Len(paraText) Then
                    Dim nextPos As Long
                    nextPos = j + 1

                    ' Skip over footnote numbers (digits) that might follow the punctuation
                    While nextPos <= Len(paraText) And IsNumeric(Mid(paraText, nextPos, 1))
                        nextPos = nextPos + 1
                    Wend

                    ' Now check if followed by space and capital letter
                    If nextPos <= Len(paraText) And Mid(paraText, nextPos, 1) = " " Then
                        If nextPos + 1 <= Len(paraText) Then
                            If Asc(Mid(paraText, nextPos + 1, 1)) >= 65 And Asc(Mid(paraText, nextPos + 1, 1)) <= 90 Then
                                sentenceEnd = nextPos - 1 ' Include footnote numbers in the sentence
                                Exit For
                            End If
                        End If
                    ElseIf nextPos > Len(paraText) Then
                        ' If we've reached end of paragraph after footnote numbers
                        sentenceEnd = j
                        ' Include any footnote numbers that were at the end
                        While sentenceEnd < Len(paraText) And IsNumeric(Mid(paraText, sentenceEnd + 1, 1))
                            sentenceEnd = sentenceEnd + 1
                        Wend
                        Exit For
                    End If
                Else
                    ' If it's at the end of paragraph, it's end of sentence
                    sentenceEnd = j
                    Exit For
                End If
            End If
        Next j

        ' Extract the first sentence
        If sentenceEnd = 0 Then
            ' No sentence ending found, take the whole paragraph (minus paragraph mark)
            sentenceEnd = Len(paraText) - 1
        End If

        ' Create a range for the first sentence in the source document
        Set sourceRange = para.Range.Duplicate
        sourceRange.End = para.Range.Start + sentenceEnd

        ' Add the sentence before the current paragraph if not empty
        If Trim(sourceRange.text) <> "" Then
            ' Create a new paragraph before the current one
            Dim insertRange As Range
            Set insertRange = para.Range
            insertRange.Collapse Direction:=wdCollapseStart

            ' Copy the first sentence
            sourceRange.Copy
            insertRange.Paste

            ' Add paragraph break after the pasted content
            insertRange.Collapse Direction:=wdCollapseEnd
            insertRange.InsertParagraphAfter

            ' Get the newly created paragraph
            Set newPara = insertRange.Paragraphs(1)

            ' Apply the user-specified style
            newPara.Style = userStyle
        End If
    End If
Next i

' Now create the Table of Contents at the beginning of the document
' Move cursor to the start of the document
Set tocRange = doc.Range(0, 0)

' Insert a title for the TOC
tocRange.text = "Table of Contents" & vbCrLf & vbCrLf
tocRange.Paragraphs(1).Style = "Heading 1"

' Move to the end of the TOC title (after the second paragraph break)
Set tocRange = doc.Range(tocRange.End, tocRange.End)

' Insert the Table of Contents
' This will include all heading levels found in the document
On Error Resume Next
doc.TablesOfContents.Add _
    Range:=tocRange, _
    UseHeadingStyles:=True, _
    UpperHeadingLevel:=1, _
    LowerHeadingLevel:=9, _
    UseFields:=True, _
    UseHyperlinks:=True, _
    HidePageNumbersInWeb:=False

If Err.Number <> 0 Then
    MsgBox "Table of Contents created, but there may have been an issue. " & _
           "You can update it by right-clicking and selecting 'Update Field'.", _
           vbInformation, "TOC Created"
End If
On Error GoTo 0

' Add a page break after the TOC
tocRange.Collapse Direction:=wdCollapseEnd
tocRange.InsertBreak Type:=wdPageBreak

' Move cursor to the start of the document
doc.Range(0, 0).Select

MsgBox "First sentences inserted as headings with style '" & userStyle & "' and Table of Contents created!", _
       vbInformation, "Macro Complete"
End Sub