I Tried Vibe Coding and You'll Never Guess What Happened Next

Photo by Gabriel Heinzer / Unsplash (A block of computer code)

I've been playing around with vibe coding. It has been a fun, frustrating, constructive, and inefficient experience.

For anyone unfamiliar with the term, vibe coding refers to a non-expert (like me!) using AI to produce code based on vibes and vague instructions, without a full understanding of what is going on under the hood.

To start, I should mention my qualifications for doing any coding. I'm not a professional programmer, but I'm not a total novice either. I took 3 years of computer science in high school, where I learned Pascal and C++, and I've dabbled in C++ and Swift for fun and in HTML/JavaScript for my company's website. I have a Linux homelab full of random services. So, I'm nowhere near a professional level, but I'm also not completely clueless. Just mostly clueless.

So, what did I vibe code? Using Claude (paid for 1 month) and Gemini (free trial for 1 month), I set out to make some Word macros in Visual Basic that would be useful for my editing work. In particular, I made macros for the following:

1) Analyzing acronyms in a paper to assist the editor in determining if they are properly defined.
2) Analyzing parenthetical citations to see which ones are alphabetical and which ones are chronological to help the editor note inconsistencies. For example: (Smith et al., 1997; Ando, 2018; Jones & Johnson, 2022) vs. (Ando, 2018; Jones & Johnson, 2022; Smith et al., 1997).
3) Analyzing hyphenated, open, and closed forms of words (e.g., policy-maker, policy maker, and policymaker, respectively) to assist the editor in spotting inconsistencies.

I managed to get workable versions of all the macros above, and I think the final versions will be beneficial to me and my small team of editors. However, it took a fair bit of time, considerable patience, and lots of banging my head against the proverbial wall. And there are still huge caveats to what you can accomplish with vibe coding.

Disclaimer: Needless to say, there are some fundamental problems with AI. It is inefficient in terms of energy and water usage and it is largely based on questionable or obviously stolen training data. So I apologize in advance for dabbling in the moral muck that AI today. I'll excuse myself on the grounds that this is very smol scale, and I think it is worth seeing what the technology can do to inform thinking on whether a more ethical and efficient version is worth pursuing. Also, I just like to play with new tech. Sorry.

So how was my experience with vibe coding? It was one part "wow!" when I got something that just "magically" worked and many parts "ugggggggg!" when I ran into the wall of stupid that is AI.

First, I'll show you what worked. Below is an example of the hyphewithnation checker's output (macro code provided at the end of the post). Here, you can see the color-coded output, which includes frequency counts and a listing of forms used. As an editor, I find this output to be really helpful for identifying errors that would be easily overlooked. But I guess it's natural that I would find it useful since I told the AI exactly what I wanted. In this sense, I can see the vibe coding being useful for bespoke or idiosyncratic solutions to niche problems that likely won't be addressed in commercial software.

The code isn't perfect. You can see that it doesn't gracefully handle "state-of-the-art", but it does handle singulars and plurals (filter-feeder, filter-feeders), and it can also spot inconsistencies where no hyphen is involved (e.g., well being vs. wellbeing). Although I'm happy with the result, the process of vibe coding was a pain in the ass.

The AI was constantly introducing errors. It was pretty good at filling in the blank canvas in response to my initial prompt. But as soon as I start iterating and refining the code, the AI would start shitting itself. It would introduce duplicate variable declaration or introduce undefined functions. It would forget that you were doing Visual Basic for a Word macro and introduce functions that were only available in Excel. Claude struggled a lot at handing variable types correctly, so it would have For loops with the wrong type of control variable or the wrong variable type as an argument to a dictionary object. Correcting these errors often required user intervention, like reminding the AI what the goal was (a VBA Word Macro!!) or telling the AI which variables were declared multiple times.

Another problem is that relatively simple changes cause the AI to lose it's shit. For example, in the above output, you can see there is color gradation to reflect the frequency of usage. The color and then the color gradation were added after the macro was working as intended (but in black and white). Adding the color led to multiple rounds of the AI introducing errors, and then it happened again when the color gradation was added. Maybe I am just a bad prompt engineer, but as the code became more complex, it seemed like any tweak was liable to send the AI into an error spiral.

Sometimes, I encountered errors that an AI was totally unable to fix. For example, Claude could not resolve an error that came up about an End If without an If block. Ultimately, I ended up sticking the code into Gemini, which recognized the error and fixed it.

Although I am not expert enough to say what is reasonable, I feel like the AI-generated code is overly long and overly complex. This is just my vibes now, but I feel like 1000 lines lines of code and almost 100 globally (?) declared variables is a bit excessive. People who talk about AI opening the door for non-coders to make apps and web pages are fucking insane. It is one thing to make an overly complex script that I don't fully understand to run locally on my machine to do a helpful task. But it would be madness to let me, a non-programmer, use AI to make code to run on a public, internet-facing server where users' data would have to be handled securely.

When the code starts getting long, another annoying thing is that either you have to waste time and usage credits to output the full code, or you have to start mucking about in the code yourself based on instructions from the AI about how change the code in multiple different places. This seems like an inherent flaw of current AI. It still uses lots of AI effort to do something trivial like spit out 1000 lines of mostly unchanged code

To sum up, I think my dabbling suggests that AI is still severely limited without a programmer who knows what they're doing. Maybe the future will be expert programmers assisted by AI, but with the current technology, I doubt it will be wannabe tech bros who know jack shit about programming but rely on AI.

I had fun and got some useful scripts out of this experience, but it was not efficient in terms of time. Prompt engineering is less a clever way of doing things and more a way of brute forcing your way to a tolerable solution. If you plan to do a lot of coding, it still seems worthwhile to actually learn to code. The upfront investment in learning will surely be better than being stuck with the inefficiencies and low-quality that come with being completely reliant on the AI.

Attribute VB_Name = "Hyphenation"
Option Explicit

' I'm making this available CC-BY-NC by Flock of Cats. 

' Helper function to count occurrences of a word and collect examples
Function CountOccurrencesAndCollectExamples(doc As Document, wordToFind As String, ByVal examplesDict As Object) As Long
    On Error GoTo ErrorHandler
    
    Dim rng As Range
    Dim count As Long
    Dim maxIterations As Long
    Dim iterations As Long
    Dim foundText As String
    
    ' Create a duplicate of the document content to avoid modifying the original
    Set rng = doc.Content.Duplicate
    count = 0
    
    ' Set reasonable limits to prevent infinite loops
    If doc.words.count > 1000 Then
        maxIterations = doc.words.count
    Else
        maxIterations = 1000
    End If
    
    If maxIterations > 10000 Then
        maxIterations = 10000 ' Cap at 10,000
    End If
    iterations = 0
    
    With rng.Find
        .ClearFormatting
        .text = wordToFind
        .Forward = True
        .Wrap = wdFindStop  ' Only search to the end, don't wrap around
        .Format = False
        .MatchWholeWord = True
        .MatchCase = False
        
        Do While .Execute
            count = count + 1
            iterations = iterations + 1
            
            ' Get the exact text as found in the document (preserves case)
            foundText = rng.text
            
            ' Add the found text as an example
            If Not examplesDict.Exists(foundText) Then
                examplesDict.Add foundText, 1
            Else
                ' Just increment the counter
                examplesDict(foundText) = examplesDict(foundText) + 1
            End If
            
            If iterations > maxIterations Then Exit Do  ' Emergency exit
            
            ' Move to the end of the current match
            rng.Collapse wdCollapseEnd
            
            ' Check if we've reached the end of the document
            If rng.Start >= doc.Content.End - 1 Then Exit Do
        Loop
    End With
    
    ' Clean up
    Set rng = Nothing
    
    CountOccurrencesAndCollectExamples = count
    Exit Function
    
ErrorHandler:
    CountOccurrencesAndCollectExamples = 0
End Function

' Helper function to check if a string contains only alphabetic characters
Function IsAlphaOnly(strText As String) As Boolean
    Dim i As Integer
    
    For i = 1 To Len(strText)
        If Not (Mid(strText, i, 1) Like "[a-zA-Z]") Then
            IsAlphaOnly = False
            Exit Function
        End If
    Next i
    
    IsAlphaOnly = True
End Function

' Helper function to format examples as a string
Function FormatExamplesString(examplesDict As Object) As String
    On Error Resume Next
    
    Dim result As String
    Dim isFirst As Boolean
    
    If examplesDict.count = 0 Then
        FormatExamplesString = ""
        Exit Function
    End If
    
    ' Sort the examples alphabetically
    Dim sortedKeys() As String
    Dim i As Long, j As Long
    Dim temp As String
    Dim keyExample As Variant
    
    ' Create array with keys
    ReDim sortedKeys(0 To examplesDict.count - 1)
    i = 0
    For Each keyExample In examplesDict.Keys
        sortedKeys(i) = CStr(keyExample)
        i = i + 1
    Next
    
    ' Simple bubble sort
    For i = 0 To UBound(sortedKeys) - 1
        For j = i + 1 To UBound(sortedKeys)
            If LCase(sortedKeys(i)) > LCase(sortedKeys(j)) Then
                temp = sortedKeys(i)
                sortedKeys(i) = sortedKeys(j)
                sortedKeys(j) = temp
            End If
        Next j
    Next i
    
    result = "("
    isFirst = True
    
    ' Build the examples string from sorted array
    For i = 0 To UBound(sortedKeys)
        If Not isFirst Then
            result = result & ", "
        Else
            isFirst = False
        End If
        
        result = result & sortedKeys(i)
    Next i
    
    result = result & ")"
    
    FormatExamplesString = result
End Function

Public Sub FindHyphenatedWords()
    ' Variable declarations
    Dim doc As Document
    Dim tempDoc As Document
    Dim rngDoc As Range
    Dim strText As String
    Dim dictHyphenated As Object
    Dim dictWords As Object
    Dim maxIterations As Long
    Dim iterations As Long
    Dim parts As Variant
    Dim strFirstPart As String
    Dim strSecondPart As String
    Dim baseHyphenForm As String
    Dim baseOpenForm As String
    Dim baseClosedForm As String
    Dim wordForms As Variant
    Dim baseWord As Variant
    Dim originalSecondPart As String
    Dim normalizedSecondPart As String
    Dim varForm As String
    Dim varType As String
    Dim hyphenatedTotal As Long
    Dim openTotal As Long
    Dim closedTotal As Long
    Dim tempCount As Long
    Dim resultsDoc As Document
    Dim tbl As Table
    Dim rowCount As Integer
    Dim tableRange As Range
    Dim currentRow As Integer
    Dim regEx As Object
    Dim Matches As Object
    Dim Match As Object
    Dim variations As Object
    Dim uniqueWordGroups As Object
    Dim groupKey As Variant
    Dim baseKey As Variant
    Dim foundBase As Boolean
    Dim wordGroup As Object
    Dim standardBaseWord As String
    Dim errorMsg As String
    Dim totalHyphenated As Long
    Dim totalOpen As Long
    Dim totalClosed As Long
    Dim forms(2) As String
    Dim i As Integer
    Dim dictFoundHyphenated As Object
    Dim dictFoundOpen As Object
    Dim dictFoundClosed As Object
    Dim dictHyphenCount As Object
    Dim dictOpenCount As Object
    Dim dictClosedCount As Object
    Dim hyphenColor As Long
    Dim openColor As Long
    Dim closedColor As Long
    Dim rowTotal As Long
    Dim hyphenPercent As Double
    Dim openPercent As Double
    Dim closedPercent As Double
    Dim blueValue As Integer
    Dim rbValue As Integer
    Dim rgValue As Integer
    Dim isFirstPartAlpha As Boolean
    Dim isSecondPartAlpha As Boolean
    Dim cellRange As Range
    Dim hyphenExamplesText As String
    Dim openExamplesText As String
    Dim closedExamplesText As String
    Dim exampleWord As Variant
    Dim closedSecondPart As String
    Dim standardForm As String
    Dim variationKey As Variant
    Dim variantKey As Variant
    Dim potentialOpenForm As Variant
    Dim potentialClosedForm As String
    Dim potentialMatch As String
    Dim dictOpenForms As Object
    Dim dictClosedForms As Object
    
    ' Store initial application settings to restore them later
    Dim initialScreenUpdating As Boolean
    Dim initialStatusBar As Boolean
    Dim initialCalculation As Long
    
    initialScreenUpdating = Application.ScreenUpdating
    initialStatusBar = Application.DisplayStatusBar
    
    ' Error handling
    On Error GoTo ErrorHandler
    
    ' Set reference to the active document
    If Documents.count = 0 Then
        MsgBox "No document is open. Please open a document and try again.", vbExclamation
        Exit Sub
    End If
    
    Set doc = ActiveDocument
    
    ' Check if document has content
    If doc.Content.Characters.count <= 1 Then
        MsgBox "Document is empty. Please add content and try again.", vbExclamation
        Exit Sub
    End If
    
    ' Performance optimizations
    Application.ScreenUpdating = False
    Application.DisplayStatusBar = True
    Application.StatusBar = "Accepting all track changes... Please wait."
    
    ' Create a temporary document for analysis
    Set tempDoc = Documents.Add(Visible:=False)
    doc.Content.Copy
    tempDoc.Content.Paste
    
    ' Accept all track changes in the temporary document
    tempDoc.TrackRevisions = False
    tempDoc.AcceptAllRevisions
    
    ' Set rngDoc to use the clean temporary document
    Set rngDoc = tempDoc.Content
    
    ' Create dictionaries to store word forms and counts with optimized settings
    Set dictHyphenated = CreateObject("Scripting.Dictionary")
    dictHyphenated.CompareMode = vbTextCompare  ' Case-insensitive
    
    Set dictWords = CreateObject("Scripting.Dictionary")
    dictWords.CompareMode = vbTextCompare
    
    ' Create dictionaries to track found words for examples
    Set dictFoundHyphenated = CreateObject("Scripting.Dictionary")
    Set dictFoundOpen = CreateObject("Scripting.Dictionary")
    Set dictFoundClosed = CreateObject("Scripting.Dictionary")
    
    ' Create dictionaries for counts
    Set dictHyphenCount = CreateObject("Scripting.Dictionary")
    dictHyphenCount.CompareMode = vbTextCompare
    
    Set dictOpenCount = CreateObject("Scripting.Dictionary")
    dictOpenCount.CompareMode = vbTextCompare
    
    Set dictClosedCount = CreateObject("Scripting.Dictionary")
    dictClosedCount.CompareMode = vbTextCompare
    
    ' Set maximum iterations - scale with document size but with bounds
    maxIterations = doc.words.count * 2
    If maxIterations < 1000 Then
        maxIterations = 1000  ' Minimum value
    End If
    If maxIterations > 100000 Then
        maxIterations = 100000  ' Maximum value
    End If
    iterations = 0
    
    ' Show progress information
    Application.StatusBar = "Finding hyphenated words... Please wait."
    
    ' Use regular expression to find hyphenated words
    Set regEx = CreateObject("VBScript.RegExp")
    regEx.Global = True
    regEx.pattern = "\b[a-zA-Z]+-[a-zA-Z]+\b"
    
    Set Matches = regEx.Execute(rngDoc.text)
    
    ' Process hyphenated words
    For Each Match In Matches
        iterations = iterations + 1
        If iterations Mod 100 = 0 Then
            Application.StatusBar = "Processing hyphenated words... " & iterations & " of " & Matches.count
            DoEvents ' Allow UI to update
        End If
        
        If iterations > maxIterations Then
            MsgBox "Maximum iterations reached. Analysis is incomplete. Try with a smaller document.", vbExclamation
            Exit For
        End If
        
        strText = Match.Value
        
        ' Skip if already processed
        If Not dictHyphenated.Exists(strText) Then
            ' Split the word into parts
            parts = Split(strText, "-")
            
            ' Only process words with one hyphen
            If UBound(parts) = 1 Then
                strFirstPart = parts(0)
                strSecondPart = parts(1)
                
                ' Only process words with meaningful parts (at least 2 characters each)
                If Len(strFirstPart) >= 2 And Len(strSecondPart) >= 2 Then
                    ' Store original second part before any transformations
                    originalSecondPart = strSecondPart
                    
                    ' Make a copy of the second part for normalization
                    normalizedSecondPart = strSecondPart
                    
                    ' Check for -ies ending (could be plural of -y)
                    If Len(normalizedSecondPart) >= 3 Then
                        If Right(normalizedSecondPart, 3) = "ies" Then
                            normalizedSecondPart = Left(normalizedSecondPart, Len(normalizedSecondPart) - 3) & "y"
                        ' Check for regular plural with 's'
                        ElseIf Right(normalizedSecondPart, 1) = "s" Then
                            normalizedSecondPart = Left(normalizedSecondPart, Len(normalizedSecondPart) - 1)
                        End If
                    End If
                    
                    ' Use normalized version for base form detection
                    strSecondPart = normalizedSecondPart
                    
                    ' Check if both parts contain only alphabetic characters
                    isFirstPartAlpha = IsAlphaOnly(strFirstPart)
                    isSecondPartAlpha = IsAlphaOnly(strSecondPart)
                    
                    If Len(strFirstPart) > 0 And Len(strSecondPart) > 0 And _
                       isFirstPartAlpha And isSecondPartAlpha Then
                        
                        ' Create the normalized form for the base word
                        If Right(strSecondPart, 1) = "y" And originalSecondPart <> strSecondPart Then
                            ' We've converted "ies" to "y" - use this as the base form
                            baseHyphenForm = LCase(strFirstPart) & "-" & LCase(strSecondPart)
                        Else
                            ' Use the normalized singular form
                            baseHyphenForm = LCase(strFirstPart) & "-" & LCase(strSecondPart)
                        End If
                        
                        ' Check if we already have this base form (case-insensitive)
                        foundBase = False
                        For Each baseKey In dictWords.Keys
                            If LCase(baseKey) = baseHyphenForm Then
                                foundBase = True
                                baseHyphenForm = baseKey
                                Exit For
                            End If
                        Next baseKey
                        
                        ' Add to dictionary with original form linked to base form
                        If Not dictHyphenated.Exists(strText) Then
                            dictHyphenated.Add strText, baseHyphenForm
                        End If
                        
                        ' Setup word forms dictionary
                        If Not dictWords.Exists(baseHyphenForm) Then
                            ' Create an array to store base variations
                            ' 0: hyphenated, 1: open, 2: closed
                            forms(0) = baseHyphenForm
                            forms(1) = LCase(strFirstPart) & " " & LCase(strSecondPart)
                            forms(2) = LCase(strFirstPart) & LCase(strSecondPart)
                            dictWords.Add baseHyphenForm, forms
                            
                            ' Initialize dictionaries for found examples
                            Set dictFoundHyphenated(baseHyphenForm) = CreateObject("Scripting.Dictionary")
                            Set dictFoundOpen(baseHyphenForm) = CreateObject("Scripting.Dictionary")
                            Set dictFoundClosed(baseHyphenForm) = CreateObject("Scripting.Dictionary")
                        End If
                        
                        ' Add the original found form as an example for its base form
                        If Not dictFoundHyphenated(baseHyphenForm).Exists(strText) Then
                            dictFoundHyphenated(baseHyphenForm).Add strText, 1
                        Else
                            dictFoundHyphenated(baseHyphenForm)(strText) = dictFoundHyphenated(baseHyphenForm)(strText) + 1
                        End If
                    End If
                End If
            End If
        End If
    Next Match
    
    ' NEW FEATURE: Look for open/closed pairs ======================================
    ' Check if we want to continue searching for open/closed form pairs
    Application.StatusBar = "Looking for open/closed word pairs..."
    
    ' Create a dictionary to store potential open forms
    Set dictOpenForms = CreateObject("Scripting.Dictionary")
    dictOpenForms.CompareMode = vbTextCompare
    
    ' Create a dictionary to store potential closed forms
    Set dictClosedForms = CreateObject("Scripting.Dictionary")
    dictClosedForms.CompareMode = vbTextCompare
    
    ' Find all open forms (two words together)
    regEx.pattern = "\b[a-zA-Z]{2,}[ ][a-zA-Z]{2,}\b"
    Set Matches = regEx.Execute(rngDoc.text)
    
    For Each Match In Matches
        potentialOpenForm = Match.Value
        
        If Not dictOpenForms.Exists(potentialOpenForm) Then
            dictOpenForms.Add potentialOpenForm, 1
        End If
    Next Match
    
    ' Find all potentially relevant closed forms
    regEx.pattern = "\b[a-zA-Z]{4,}\b"
    Set Matches = regEx.Execute(rngDoc.text)
    
    For Each Match In Matches
        potentialClosedForm = Match.Value
        
        ' Only track if 4+ characters (to be a potential compound)
        If Len(potentialClosedForm) >= 4 Then
            If Not dictClosedForms.Exists(potentialClosedForm) Then
                dictClosedForms.Add potentialClosedForm, 1
            End If
        End If
    Next Match
    
    ' Now look for matching pairs
    Application.StatusBar = "Analyzing potential compound word pairs..."
    
    For Each potentialOpenForm In dictOpenForms.Keys
        ' Split the open form into two parts
        parts = Split(potentialOpenForm, " ")
        
        ' Only proceed if exactly two parts
        If UBound(parts) = 1 Then
            strFirstPart = parts(0)
            strSecondPart = parts(1)
            
            ' Only process words with meaningful parts (at least 2 characters each)
            If Len(strFirstPart) >= 2 And Len(strSecondPart) >= 2 Then
                ' Check if both parts contain only alphabetic characters
                isFirstPartAlpha = IsAlphaOnly(strFirstPart)
                isSecondPartAlpha = IsAlphaOnly(strSecondPart)
                
                If isFirstPartAlpha And isSecondPartAlpha Then
                    ' Create the potential closed form
                    potentialMatch = LCase(strFirstPart) & LCase(strSecondPart)
                    
                    ' Check if this closed form exists in the document
                    If dictClosedForms.Exists(potentialMatch) Then
                        ' We have both open and closed forms - create a new base entry if needed
                        baseHyphenForm = LCase(strFirstPart) & "-" & LCase(strSecondPart)
                        
                        ' Check if we already have this form from the hyphenated search
                        foundBase = False
                        For Each baseKey In dictWords.Keys
                            If LCase(baseKey) = baseHyphenForm Then
                                foundBase = True
                                baseHyphenForm = baseKey
                                Exit For
                            End If
                        Next baseKey
                        
                        If Not foundBase Then
                            ' This is a new compound term not previously found via hyphenation
                            ' Create an array to store base variations
                            forms(0) = baseHyphenForm
                            forms(1) = LCase(strFirstPart) & " " & LCase(strSecondPart)
                            forms(2) = LCase(strFirstPart) & LCase(strSecondPart)
                            dictWords.Add baseHyphenForm, forms
                            
                            ' Initialize dictionaries for found examples
                            Set dictFoundHyphenated(baseHyphenForm) = CreateObject("Scripting.Dictionary")
                            Set dictFoundOpen(baseHyphenForm) = CreateObject("Scripting.Dictionary")
                            Set dictFoundClosed(baseHyphenForm) = CreateObject("Scripting.Dictionary")
                            
                            ' Add the open form as an example
                            If Not dictFoundOpen(baseHyphenForm).Exists(potentialOpenForm) Then
                                dictFoundOpen(baseHyphenForm).Add potentialOpenForm, 1
                            End If
                            
                            ' Add the closed form as an example
                            If Not dictFoundClosed(baseHyphenForm).Exists(potentialMatch) Then
                                dictFoundClosed(baseHyphenForm).Add potentialMatch, 1
                            End If
                        End If
                    End If
                End If
            End If
        End If
    Next
    
    ' Check if we found any valid words (either hyphenated or open/closed pairs)
    If dictWords.count = 0 Then
        Application.StatusBar = False
        Application.ScreenUpdating = True
        MsgBox "No valid hyphenated words or matching open/closed word pairs were found in this document.", vbInformation
        GoTo CleanupAndExit
    End If
    
    ' Second phase: Count all variations of each normalized word
    Application.StatusBar = "Counting word variations..."
    
    ' Reset iterations counter
    iterations = 0
    
    ' Process each base word
    For Each baseWord In dictWords.Keys
        iterations = iterations + 1
        If iterations Mod 10 = 0 Then
            Application.StatusBar = "Analyzing word variations... " & iterations & " of " & dictWords.count
            DoEvents ' Allow UI to update
        End If
        
        ' Extract parts from the base word (which is in hyphenated form)
        parts = Split(baseWord, "-")
        strFirstPart = parts(0)
        strSecondPart = parts(1)
        
        ' Get all three forms of this word
        wordForms = dictWords.item(baseWord)
        baseHyphenForm = wordForms(0)  ' my-number
        baseOpenForm = wordForms(1)    ' my number
        baseClosedForm = wordForms(2)  ' mynumber
        
        ' Create all possible variations for this base form
        Set variations = CreateObject("Scripting.Dictionary")
        
        ' === HYPHENATED FORMS ===
        ' Add the singular form
        variations.Add baseHyphenForm, "hyphen"
        
        ' Add plural forms based on word ending
        If Right(strSecondPart, 1) = "y" Then
            ' -y to -ies plural transformation
            variations.Add strFirstPart & "-" & Left(strSecondPart, Len(strSecondPart) - 1) & "ies", "hyphen"
            
            ' If we also have a "ey" form, add its plural too
            If Right(strSecondPart, 2) = "ey" Then
                variations.Add strFirstPart & "-" & Left(strSecondPart, Len(strSecondPart) - 1) & "eies", "hyphen"
            End If
        ElseIf Right(strSecondPart, 1) = "s" Or Right(strSecondPart, 1) = "x" Or Right(strSecondPart, 1) = "z" Or _
               Right(strSecondPart, 2) = "sh" Or Right(strSecondPart, 2) = "ch" Then
            ' Words ending in s, x, z, sh, ch add -es
            variations.Add baseHyphenForm & "es", "hyphen"
        End If
        
        ' Regular plural with s
        variations.Add baseHyphenForm & "s", "hyphen"
        
        ' Always add -es form for cases like "numberes"
        If Not variations.Exists(baseHyphenForm & "es") Then
            variations.Add baseHyphenForm & "es", "hyphen"
        End If
        
        ' === OPEN FORMS ===
        ' Add the singular form
        variations.Add baseOpenForm, "open"
        
        ' Add plural forms based on word ending
        If Right(strSecondPart, 1) = "y" Then
            ' -y to -ies plural transformation
            variations.Add strFirstPart & " " & Left(strSecondPart, Len(strSecondPart) - 1) & "ies", "open"
            
            ' If we also have a "ey" form, add its plural too
            If Right(strSecondPart, 2) = "ey" Then
                variations.Add strFirstPart & " " & Left(strSecondPart, Len(strSecondPart) - 1) & "eies", "open"
            End If
        ElseIf Right(strSecondPart, 1) = "s" Or Right(strSecondPart, 1) = "x" Or Right(strSecondPart, 1) = "z" Or _
               Right(strSecondPart, 2) = "sh" Or Right(strSecondPart, 2) = "ch" Then
            ' Words ending in s, x, z, sh, ch add -es
            variations.Add baseOpenForm & "es", "open"
        End If
        
        ' Regular plural with s
        variations.Add baseOpenForm & "s", "open"
        
        ' Always add -es form for cases like "numberes"
        If Not variations.Exists(baseOpenForm & "es") Then
            variations.Add baseOpenForm & "es", "open"
        End If
        
        ' === CLOSED FORMS ===
        ' Add the singular form
        variations.Add baseClosedForm, "closed"
        
        ' Add plural forms based on the ending of the closed form
        closedSecondPart = Mid(baseClosedForm, Len(strFirstPart) + 1)
        
        If Right(closedSecondPart, 1) = "y" Then
            ' -y to -ies plural transformation for closed form
            variations.Add strFirstPart & Left(closedSecondPart, Len(closedSecondPart) - 1) & "ies", "closed"
        ElseIf Right(closedSecondPart, 1) = "s" Or Right(closedSecondPart, 1) = "x" Or Right(closedSecondPart, 1) = "z" Or _
               Right(closedSecondPart, 2) = "sh" Or Right(closedSecondPart, 2) = "ch" Then
            ' Words ending in s, x, z, sh, ch add -es
            variations.Add baseClosedForm & "es", "closed"
        End If
        
        ' Regular plural with s
        variations.Add baseClosedForm & "s", "closed"
        
        ' Always add -es form for cases like "numberes"
        If Not variations.Exists(baseClosedForm & "es") Then
            variations.Add baseClosedForm & "es", "closed"
        End If
        
        ' Now count all variations in the document
        hyphenatedTotal = 0
        openTotal = 0
        closedTotal = 0
        
        ' Loop through all variations
        For Each variationKey In variations.Keys
            varForm = variationKey
            varType = variations(variationKey)
            
            Select Case varType
                Case "hyphen"
                    ' It's a hyphenated form
                    tempCount = CountOccurrencesAndCollectExamples(tempDoc, CStr(varForm), dictFoundHyphenated(baseWord))
                    hyphenatedTotal = hyphenatedTotal + tempCount
                    
                Case "open"
                    ' It's an open form
                    tempCount = CountOccurrencesAndCollectExamples(tempDoc, CStr(varForm), dictFoundOpen(baseWord))
                    openTotal = openTotal + tempCount
                    
                Case "closed"
                    ' It's a closed form
                    tempCount = CountOccurrencesAndCollectExamples(tempDoc, CStr(varForm), dictFoundClosed(baseWord))
                    closedTotal = closedTotal + tempCount
            End Select
        Next variationKey
        
        ' Store the counts in dictionaries
        dictHyphenCount.Add baseWord, hyphenatedTotal
        dictOpenCount.Add baseWord, openTotal
        dictClosedCount.Add baseWord, closedTotal
    Next baseWord
    
    ' Before creating the table, coalesce words that should be considered the same
    Application.StatusBar = "Normalizing word forms..."
    Set wordGroup = CreateObject("Scripting.Dictionary")
    
    ' First pass - identify standard forms (e.g., number vs numbey)
    For Each baseWord In dictWords.Keys
        parts = Split(baseWord, "-")
        
        ' Special handling for "numbey" vs "number" type words
        If Len(parts(1)) >= 4 Then
            ' Check if the word ends with "ey"
            If Right(LCase(parts(1)), 2) = "ey" Then
                ' Generate potential standard form with "er" ending
                standardForm = LCase(parts(0)) & "-" & Left(LCase(parts(1)), Len(parts(1)) - 2) & "er"
                
                ' See if we have this standard form
                For Each baseKey In dictWords.Keys
                    If LCase(baseKey) = standardForm Then
                        ' Found standard form - map this "ey" word to standard
                        wordGroup.Add baseWord, baseKey
                        Exit For
                    End If
                Next baseKey
            End If
            
            ' Handle potential "ies/y" situations
            If Right(LCase(parts(1)), 3) = "ies" Then
                ' Generate potential standard form with "y" ending
                standardForm = LCase(parts(0)) & "-" & Left(LCase(parts(1)), Len(parts(1)) - 3) & "y"
                
                ' See if we have this standard form
                For Each baseKey In dictWords.Keys
                    If LCase(baseKey) = standardForm Then
                        ' Map plural to singular
                        wordGroup.Add baseWord, baseKey
                        Exit For
                    End If
                Next baseKey
                
                ' Also check for possible "eies" to "ey" mapping
                If Len(parts(1)) > 4 And Left(Right(LCase(parts(1)), 4), 1) = "e" Then
                    standardForm = LCase(parts(0)) & "-" & Left(LCase(parts(1)), Len(parts(1)) - 4) & "ey"
                    
                    For Each baseKey In dictWords.Keys
                        If LCase(baseKey) = standardForm Then
                            ' Map this "eies" form to "ey" form
                            wordGroup.Add baseWord, baseKey
                            Exit For
                        End If
                    Next baseKey
                End If
            End If
        End If
    Next baseWord
    
    Application.StatusBar = "Creating results table..."
    
    ' Now reset the uniqueWordGroups collection for table generation
    Set uniqueWordGroups = CreateObject("Scripting.Dictionary")
    
    ' Add all words to groups, using the standard form when available
    For Each baseWord In dictWords.Keys
        If wordGroup.Exists(baseWord) Then
            ' This is a non-standard word (e.g., "numbey") - use its standard form
            standardBaseWord = wordGroup(baseWord)
            If Not uniqueWordGroups.Exists(LCase(standardBaseWord)) Then
                uniqueWordGroups.Add LCase(standardBaseWord), standardBaseWord
            End If
        Else
            ' This is either a standard word or one without a variant
            If Not uniqueWordGroups.Exists(LCase(baseWord)) Then
                uniqueWordGroups.Add LCase(baseWord), baseWord
            End If
        End If
    Next baseWord
    
    ' Create results document
    Set resultsDoc = Documents.Add
    
    ' Add a header
    With resultsDoc.Content
        .text = "Hyphenated Words Analysis" & vbCrLf & vbCrLf
        .ParagraphFormat.Alignment = wdAlignParagraphCenter
        .Font.Bold = True
        .Font.Size = 14
        .InsertParagraphAfter
    End With
    
    ' Add document info
    With resultsDoc.Content
        .Collapse wdCollapseEnd
        .Font.Bold = False
        .Font.Size = 10
        .text = "Source document: " & doc.name & vbCrLf
        .text = "Analysis date: " & Format(Now, "yyyy-mm-dd hh:mm:ss") & vbCrLf
        .text = "Number of unique hyphenated word groups: " & uniqueWordGroups.count & vbCrLf & vbCrLf
    End With
    
    ' Reset formatting
    With resultsDoc.Content
        .Collapse wdCollapseEnd
        .Font.Size = 11
        .ParagraphFormat.Alignment = wdAlignParagraphLeft
    End With
    
    ' Create a table for results
    rowCount = uniqueWordGroups.count + 1  ' +1 for header row
    
    ' Create table with 3 columns (Hyphenated, Open, Closed)
    Set tableRange = resultsDoc.Range(resultsDoc.Content.End - 1, resultsDoc.Content.End - 1)
    Set tbl = resultsDoc.Tables.Add(Range:=tableRange, NumRows:=rowCount, NumColumns:=3)
    tbl.Borders.Enable = True
    
    ' Set table header
    tbl.Cell(1, 1).Range.text = "Hyphenated Form"
    tbl.Cell(1, 2).Range.text = "Open Form"
    tbl.Cell(1, 3).Range.text = "Closed Form"
    
    ' Format the header row
    tbl.Rows(1).Range.Font.Bold = True
    tbl.Rows(1).Shading.BackgroundPatternColor = wdColorGray15
    
    ' Make sure all rows except the header are not bold
    For i = 2 To tbl.Rows.count
        tbl.Rows(i).Range.Font.Bold = False
    Next i
    
    ' Sort group keys alphabetically
    Dim sortedKeys() As String
    Dim tempKey As String
    Dim k As Long, m As Long
    
    ' Create array with the unique word group keys
    ReDim sortedKeys(0 To uniqueWordGroups.count - 1)
    i = 0
    For Each groupKey In uniqueWordGroups.Keys
        sortedKeys(i) = CStr(groupKey)
        i = i + 1
    Next
    
    ' Simple bubble sort to alphabetize
    For k = 0 To UBound(sortedKeys) - 1
        For m = k + 1 To UBound(sortedKeys)
            If LCase(sortedKeys(k)) > LCase(sortedKeys(m)) Then
                tempKey = sortedKeys(k)
                sortedKeys(k) = sortedKeys(m)
                sortedKeys(m) = tempKey
            End If
        Next m
    Next k
    
    ' Variable to track current row
    currentRow = 2  ' Start after header row
    
    ' Track totals
    totalHyphenated = 0
    totalOpen = 0
    totalClosed = 0
    
    ' Process each unique word group in alphabetical order
    For i = 0 To UBound(sortedKeys)
        groupKey = sortedKeys(i)
        baseWord = uniqueWordGroups(groupKey)
        On Error Resume Next  ' Add error handling for this section
        
        ' Get the canonical base word for this group
        baseWord = uniqueWordGroups(groupKey)
        
        ' Make sure the dictionaries exist for this base word
        If Not dictFoundHyphenated.Exists(baseWord) Then
            Set dictFoundHyphenated(baseWord) = CreateObject("Scripting.Dictionary")
        End If
        
        If Not dictFoundOpen.Exists(baseWord) Then
            Set dictFoundOpen(baseWord) = CreateObject("Scripting.Dictionary")
        End If
        
        If Not dictFoundClosed.Exists(baseWord) Then
            Set dictFoundClosed(baseWord) = CreateObject("Scripting.Dictionary")
        End If
        
        ' Need to combine all counts for standard and variant forms
        hyphenatedTotal = 0
        openTotal = 0
        closedTotal = 0
        
        ' For this word and all its variants, merge counts and examples
        If dictHyphenCount.Exists(baseWord) Then
            hyphenatedTotal = hyphenatedTotal + dictHyphenCount(baseWord)
        End If
        
        If dictOpenCount.Exists(baseWord) Then
            openTotal = openTotal + dictOpenCount(baseWord)
        End If
        
        If dictClosedCount.Exists(baseWord) Then
            closedTotal = closedTotal + dictClosedCount(baseWord)
        End If
        
        ' Check for variant forms that need to be merged
        For Each variantKey In wordGroup.Keys
            If wordGroup(variantKey) = baseWord Then
                ' This variant maps to our base word
                If dictHyphenCount.Exists(variantKey) Then
                    hyphenatedTotal = hyphenatedTotal + dictHyphenCount(variantKey)
                End If
                
                If dictOpenCount.Exists(variantKey) Then
                    openTotal = openTotal + dictOpenCount(variantKey)
                End If
                
                If dictClosedCount.Exists(variantKey) Then
                    closedTotal = closedTotal + dictClosedCount(variantKey)
                End If
                
                ' Also merge the examples dictionaries
                If dictFoundHyphenated.Exists(variantKey) Then
                    ' For each example in the variant's dictionary, add it to the base word's dictionary if it's not already there
                    For Each exampleWord In dictFoundHyphenated(variantKey).Keys
                        If Not dictFoundHyphenated(baseWord).Exists(exampleWord) Then
                            dictFoundHyphenated(baseWord).Add exampleWord, dictFoundHyphenated(variantKey)(exampleWord)
                        End If
                    Next exampleWord
                End If
                
                If dictFoundOpen.Exists(variantKey) Then
                    For Each exampleWord In dictFoundOpen(variantKey).Keys
                        If Not dictFoundOpen(baseWord).Exists(exampleWord) Then
                            dictFoundOpen(baseWord).Add exampleWord, dictFoundOpen(variantKey)(exampleWord)
                        End If
                    Next exampleWord
                End If
                
                If dictFoundClosed.Exists(variantKey) Then
                    For Each exampleWord In dictFoundClosed(variantKey).Keys
                        If Not dictFoundClosed(baseWord).Exists(exampleWord) Then
                            dictFoundClosed(baseWord).Add exampleWord, dictFoundClosed(variantKey)(exampleWord)
                        End If
                    Next exampleWord
                End If
            End If
        Next variantKey
        
        On Error GoTo 0  ' Resume normal error handling
        
        ' Update totals
        totalHyphenated = totalHyphenated + hyphenatedTotal
        totalOpen = totalOpen + openTotal
        totalClosed = totalClosed + closedTotal
        
        ' Get the word forms
        If dictWords.Exists(baseWord) Then
            wordForms = dictWords.item(baseWord)
            baseHyphenForm = wordForms(0)
            baseOpenForm = wordForms(1)
            baseClosedForm = wordForms(2)
        Else
            ' If forms don't exist, create them from the base word
            parts = Split(baseWord, "-")
            baseHyphenForm = baseWord
            baseOpenForm = parts(0) & " " & parts(1)
            baseClosedForm = parts(0) & parts(1)
        End If
        
        ' Calculate row total for color intensity calculations
        rowTotal = hyphenatedTotal + openTotal + closedTotal
        
        If rowTotal > 0 Then
            hyphenPercent = hyphenatedTotal / rowTotal
            openPercent = openTotal / rowTotal
            closedPercent = closedTotal / rowTotal
        Else
            hyphenPercent = 0
            openPercent = 0
            closedPercent = 0
        End If
        
        ' Display in the table with color coding
        If currentRow <= tbl.Rows.count Then
            ' Color intensity based on percentage (higher = darker)
            blueValue = 128 + Int(127 * (1 - hyphenPercent))
            If blueValue < 0 Then blueValue = 0
            If blueValue > 255 Then blueValue = 255
            hyphenColor = RGB(255, 255, blueValue)
            
            ' Hyphenated form - use a simpler approach to avoid "Not a valid action" errors
            Set cellRange = tbl.Cell(currentRow, 1).Range
            cellRange.text = baseHyphenForm & " (" & hyphenatedTotal & ")"
            
            ' Add examples if available - using a more compatible approach
            If dictFoundHyphenated.Exists(baseWord) And dictFoundHyphenated(baseWord).count > 0 Then
                hyphenExamplesText = FormatExamplesString(dictFoundHyphenated(baseWord))
                
                If Len(hyphenExamplesText) > 0 Then
                    ' Use this simpler approach that works across Word versions
                    cellRange.text = cellRange.text & hyphenExamplesText
                End If
            End If
            
            ' Set cell background color
            tbl.Cell(currentRow, 1).Shading.BackgroundPatternColor = hyphenColor
            
            ' Format and display the open form - using compatible approach
            rbValue = 128 + Int(127 * (1 - openPercent))
            If rbValue < 0 Then rbValue = 0
            If rbValue > 255 Then rbValue = 255
            openColor = RGB(rbValue, rbValue, 255)
            
            Set cellRange = tbl.Cell(currentRow, 2).Range
            cellRange.text = baseOpenForm & " (" & openTotal & ")"
            
            ' Add examples if available - using compatible approach
            If dictFoundOpen.Exists(baseWord) And dictFoundOpen(baseWord).count > 0 Then
                openExamplesText = FormatExamplesString(dictFoundOpen(baseWord))
                
                If Len(openExamplesText) > 0 Then
                    cellRange.text = cellRange.text & openExamplesText
                End If
            End If
            
            ' Set cell background color
            tbl.Cell(currentRow, 2).Shading.BackgroundPatternColor = openColor
            
            ' Format and display the closed form - using compatible approach
            rgValue = 128 + Int(127 * (1 - closedPercent))
            If rgValue < 0 Then rgValue = 0
            If rgValue > 255 Then rgValue = 255
            closedColor = RGB(rgValue, 255, rgValue)
            
            Set cellRange = tbl.Cell(currentRow, 3).Range
            cellRange.text = baseClosedForm & " (" & closedTotal & ")"
            
            ' Add examples if available - using compatible approach
            If dictFoundClosed.Exists(baseWord) And dictFoundClosed(baseWord).count > 0 Then
                closedExamplesText = FormatExamplesString(dictFoundClosed(baseWord))
                
                If Len(closedExamplesText) > 0 Then
                    cellRange.text = cellRange.text & closedExamplesText
                End If
            End If
            
            ' Set cell background color
            tbl.Cell(currentRow, 3).Shading.BackgroundPatternColor = closedColor
            
            ' Move to next row
            currentRow = currentRow + 1
        End If
    Next i ' Process next sorted key
    
    ' Format the table
    tbl.AutoFitBehavior wdAutoFitContent
    
CleanupAndExit:
    ' Close the temporary document
    On Error Resume Next
    If Not tempDoc Is Nothing Then
        tempDoc.Close wdDoNotSaveChanges
    End If
    On Error GoTo ErrorHandler
    
    ' Reset status bar and screen updating
    Application.StatusBar = False
    Application.ScreenUpdating = initialScreenUpdating
    Application.DisplayStatusBar = initialStatusBar
    
    ' We've removed the stats summary and message box as requested
    
    Exit Sub
    
ErrorHandler:
    ' Restore screen updating and status bar
    Application.ScreenUpdating = initialScreenUpdating
    Application.StatusBar = False
    Application.DisplayStatusBar = initialStatusBar
    
    ' Close the temporary document if it exists
    On Error Resume Next
    If Not tempDoc Is Nothing Then
        tempDoc.Close wdDoNotSaveChanges
    End If
    On Error GoTo 0
    
    ' Display error message
    errorMsg = "An error occurred during analysis:" & vbCrLf & vbCrLf & _
               "Error Number: " & err.Number & vbCrLf & _
               "Description: " & err.Description
               
    MsgBox errorMsg, vbCritical, "Error in FindHyphenatedWords"
End Sub