The various inputbox UI makes this rather crude and better suited for a
UserForm but I adapted some code that Doug Robbins has provided from time to
time to count and report unique words. I simply added the feature to
"exclude" words from processing or "designate" specific words to process
only.
Sub WordFrequency2()
Dim aWord As Range 'Raw word pulled from doc
Dim SingleWord As String 'Processed raw word
Dim Words() As String 'Array to hold unique words
Dim Freq() As Integer 'Frequency counter for Unique Words
Dim Ans As String 'Logic router
Dim WordNum As Integer 'Number of unique words
Dim ByFreq As Boolean 'Flag for sorting order
Dim Count As Long 'Total words in the document
Dim Excludes As String 'Words to be excluded
Dim Specifics As String 'Specific words to process
Dim bSpecifics As Boolean 'Logic router
Dim Found As Boolean 'Temporary flag
Dim j, k, l, Temp As Integer 'Temporary variables
Dim lngProcessedWords As Long 'Total processed words in document
Dim NonWordObjects As Long
Dim TotalWords As Long
Dim tword As String '
Dim tmpName
Dim oRng As Word.Range
Dim oTbl As Word.Table
Excludes = InputBox$("Enter words that you wish to exclude. " _
& "Place each word within square brackets [ ]. " _
& "Example: [is][a].", "Excluded Words", "")
If Len(Excludes) = 0 Then
Specifics = InputBox("Enter any specific words you wish to process. " _
& "Place each word withing squiggly brackets { }. " _
& "Example: {I}{me}{you}.", "Specific Words", "")
If Len(Specifics) > 0 Then bSpecifics = True
End If
'Find out how to sort
ByFreq = True
Ans = InputBox$("Default sort order is word freqeuncy." _
& " To sort alphabetically by word, type Word in the field below.",
"Sort order", "FREQ")
If Ans = "" Then End
If UCase(Ans) = "WORD" Then
ByFreq = False
End If
System.Cursor = wdCursorWait
WordNum = 0
Count = ActiveDocument.Words.Count
ReDim Words(Count)
ReDim Freq(Count)
'Control the repeat
For Each aWord In ActiveDocument.Words
SingleWord = Trim(LCase(aWord))
If SingleWord < "a" Or SingleWord > "z" Then
SingleWord = "" 'Out of range?
NonWordObjects = NonWordObjects + 1 '
End If
If InStr(Excludes, "[" & SingleWord & "]") Then SingleWord = "" 'On
exclude list?
If Not bSpecifics Then
If Len(SingleWord) > 0 Then
lngProcessedWords = lngProcessedWords + 1
Found = False
For j = 1 To WordNum
If Words(j) = SingleWord Then
Freq(j) = Freq(j) + 1
Found = True
Exit For
End If
Next j
If Not Found Then
WordNum = WordNum + 1
Words(WordNum) = SingleWord
Freq(WordNum) = 1
End If
End If
Else
If Len(SingleWord) > 0 And InStr(Specifics, "{" & SingleWord & "}") Then
lngProcessedWords = lngProcessedWords + 1
Found = False
For j = 1 To WordNum
If Words(j) = SingleWord Then
Freq(j) = Freq(j) + 1
Found = True
Exit For
End If
Next j
If Not Found Then
WordNum = WordNum + 1
Words(WordNum) = SingleWord
Freq(WordNum) = 1
End If
End If
End If
Count = Count - 1
StatusBar = "Remaining: " & Count & " Unique: " & WordNum
Next aWord
'Now sort it into word order
For j = 1 To WordNum - 1
k = j
For l = j + 1 To WordNum
If (Not ByFreq And Words(l) < Words(k)) Or (ByFreq And Freq(l) >
Freq(k)) Then k = l
Next l
If k <> j Then
tword = Words(j)
Words(j) = Words(k)
Words(k) = tword
Temp = Freq(j)
Freq(j) = Freq(k)
Freq(k) = Temp
End If
StatusBar = "Sorting: " & WordNum - j
Next j
Count = ActiveDocument.Words.Count
TotalWords = Count - NonWordObjects
'Write out the results
tmpName = ActiveDocument.AttachedTemplate.FullName
Documents.Add Template:=tmpName, NewTemplate:=False
Set oRng = ActiveDocument.Range
With oRng
.ParagraphFormat.TabStops.ClearAll
For j = 1 To WordNum
.InsertAfter Words(j) & vbTab & Trim(Str(Freq(j))) & vbCrLf
Next j
.ConvertToTable
.Collapse wdCollapseStart
End With
Set oTbl = ActiveDocument.Tables(1)
oTbl.Rows.Add BeforeRow:=Selection.Rows(1)
oTbl.Cell(1, 1).Range.InsertBefore "Unique Words"
oTbl.Cell(1, 2).Range.InsertBefore "Number of Occurrences"
oTbl.Columns(2).Select
Selection.ParagraphFormat.Alignment = wdAlignParagraphRight
Selection.Collapse wdCollapseStart
oTbl.Rows(1).Shading.BackgroundPatternColor = wdColorGray20
oTbl.Columns(1).PreferredWidth = InchesToPoints(4.75)
oTbl.Columns(2).PreferredWidth = InchesToPoints(1.9)
oTbl.Rows.Add
oTbl.Cell(oTbl.Rows.Count, 1).Range.InsertBefore "Summary"
oTbl.Cell(oTbl.Rows.Count, 2).Range.InsertBefore "Total"
oTbl.Rows(oTbl.Rows.Count).Shading.BackgroundPatternColor = wdColorGray20
If Not bSpecifics Then
oTbl.Rows.Add
oTbl.Cell(oTbl.Rows.Count, 1).Range.InsertBefore "Number of unique words
in Document"
oTbl.Cell(oTbl.Rows.Count, 2).Range.InsertBefore Trim(Str(WordNum))
oTbl.Rows(oTbl.Rows.Count).Shading.BackgroundPatternColor =
wdColorAutomatic
End If
oTbl.Rows.Add
oTbl.Cell(oTbl.Rows.Count, 1).Range.InsertBefore "Total number of reported
words in document"
oTbl.Cell(oTbl.Rows.Count, 2).Range.InsertBefore (lngProcessedWords)
If bSpecifics Then oTbl.Rows(oTbl.Rows.Count).Shading.BackgroundPatternColor
= wdColorAutomatic
oTbl.Rows.Add
oTbl.Cell(oTbl.Rows.Count, 1).Range.InsertBefore "Total number of words in
document"
oTbl.Cell(oTbl.Rows.Count, 2).Range.InsertBefore (TotalWords)
System.Cursor = wdCursorNormal
If Not bSpecifics Then
MsgBox "This document contains " & Trim(Str(WordNum)) & " unique words."
End If
MsgBox "This document contains " & lngProcessedWords & " reported words. "
MsgBox "This document contains a total of " & TotalWords & " words. "
MsgBox "For more statistics on this document, use Tools>Word Count in the
original document. "
ActiveDocument.Range(0, 0).Select
End Sub
--
Greg Maxey/Word MVP
See:
http://gregmaxey.mvps.org/word_tips.htm
For some helpful tips using Word.
Russ said:
Hi Helmut,
I like it.
It's fast.
To help ignore case you could add something like the change I made below
for
the word "the"
Sub Test445B()
Dim rTmp As Range
Set rTmp = ActiveDocument.Sections(1).Range
With ActiveDocument.Tables(1)
.Cell(1, 1).Range.Text = "The or the"
.Cell(2, 1).Range.Text = "quick"
.Cell(3, 1).Range.Text = "brown"
.Cell(4, 1).Range.Text = "fox"
.Cell(1, 2).Range.Text = UBound(Split(LCase(rTmp.Text), "the"))
.Cell(2, 2).Range.Text = UBound(Split(rTmp.Text, "quick"))
.Cell(3, 2).Range.Text = UBound(Split(rTmp.Text, "brown"))
.Cell(4, 2).Range.Text = UBound(Split(rTmp.Text, "fox"))
End With
End Sub