Word Field needed to count number of words in a given bookmark - Wrong Answers

This is relative to http://www.experts-exchange.com/Software/Office_Productivity/Office_Suites/MS_Office/Word/Q_23483179.html?cid=239#a21782050

Working with GrahamSkan:

The routine is producing what appears to be the wrong answer for the following instance

In Word Edit>GoTo>Bookmark>Abstract in order to select the text being counted
In Immediate window ?ActiveDocument.Bookmarks("Abstract").Range gives [See the resulting text in snippet below]
In Immediate window ?selection.Words.Count gives  328
In Immediate window?ActiveDocument.Bookmarks("Abstract").Range.Words.Count gives 328
In Word the menu command Tools>Word Count gives 265
In Immediate window ?ubound(split(ActiveDocument.Bookmarks("Abstract").Range," ")) gives 270 (Origin is 0)
The correct answer is 270 manually counting and also counted in Excel to be 270.

What accounts for all the discrepancies?
328 from the routine;
265 from the builtin function;
270 by counting the words 3 other ways (manual, excel, VBA function Split)
I know - it's the ¿¿Twilight Zone?? Friday 13th, who knows.
Strategies for vascular control and limiting warm ischemia time vary between institutions for laparoscopic live donor nephrectomy (LLDN).  We refined our technique and retrospectively determined whether it safely provides an allograft of comparable quality to published series. Bla Bla Bla.
Patients and Methods:
Fifty consecutive LLDN between February 2003 and November 2006 were reviewed.  Key technical aspects include placing the perfused kidney and transected ureter entirely within an endocatch bag, with the string externalized through an extended lateral port site incision.  Vessels are then controlled with clips, or a Satinsky clamp for right sided veins.  The extraction incision is completed and the bag immediately withdrawn and placed on ice. Warm ischemia time (WIT) ends with perfusion with cold UW solution.
The series includes 42 left and 8 right kidneys.  13/50 (26%) demonstrated anatomical complexity (more than one artery, vein and/or ureter).  Average operative time was 178 minutes.  Average WIT was 129 seconds.  Conversion to open surgery occurred in 2 patients, one to define challenging anatomy, and another for hemorrhage from the renal artery stump.  Average blood loss was 120 ml.  Average length of stay was 3.6 days.
Average recipient creatinine was 1.26 mg/dl at discharge.  Delayed graft function occurred in three recipients.  ATN/slow normalization of creatinine occurred in four.  Ureteral injury occurred in one patient. Graft survival at 1 year was 96%.
The refined technique of LLDN mimics important principles of open donor nephrectomy.  Controllable variables which may impact graft function are optimized.  WIT is amongst the lowest reported for pure laparoscopy, without increasing complication rates, blood loss, or operative time.

Open in new window

Who is Participating?
GrahamSkanConnect With a Mentor RetiredCommented:
Yes as I said, it depends on what you mean by 'Word'.

This attempt is based on changing formatting characters to spaces and then splitting the text.

In my experiments it gives the same result as the document property, without the 'kludge' of creating a temporary document.
Function CountWords3(rngText As Range) As Long
    Dim strWords() As String
    Dim strText As String
    Set rngText = ActiveDocument.Range
    strText = Application.CleanString(rngText)
    strText = Replace(strText, vbCr, " ")
    strText = Replace(strText, vbVerticalTab, " ")
    strText = Replace(strText, vbTab, " ")
    Do While InStr(strText, "  ")
        strText = Replace(strText, "  ", " ")
    strText = Trim$(strText)
    If Len(strText) > 0 Then
        strWords = Split(strText, " ")
        CountWords3 = UBound(strWords) + 1
    End If
End Function

Open in new window

As you can probably guess, the short answer is in the definition of what constitutes a Word.

The Words collection of ranges is created by splitting everything in its contained range into a word item. It seems that the splitting is done at a change from letters and numbers to something else. Trailing spaces are included with the item, but other characters are not, and thus become separate words.

This is obviously different from splitting at spaces.

I doubt that Microsoft publish the exact criteria for  the whole document word count in Tools or Properties, but the code in the snippet is gets closer to it.

I suspect that punctuation that could be embedded in a word such as a hyphenation characters and a dot when it is decimal point would account for some of the differences.
Function CountWords(rngText As Range) As Long
    Dim rngWord As Range
    Dim rngChar As Range
    For Each rngWord In rngText.words
        Set rngChar = rngWord.Characters.First
        Select Case rngChar.Text
            Case "0" To "9", "A" To "Z", "a" To "z"
                CountWords = CountWords + 1
        End Select
    Next rngWord
End Function

Open in new window

If you want to guarantee consistency, you could copy the relevant section to a temporary document and check the relevant document property.
Function CountWords2(rngText As Range) As Long
    Dim Doc As Document
    Set Doc = Documents.Add
    Doc.Range.Text = rngText.Text
    CountWords2 = Doc.BuiltInDocumentProperties(wdPropertyWords)
    Doc.Close wdDoNotSaveChanges
End Function

Open in new window

Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

canesbrAuthor Commented:
Interesting (not so much)
"He/She was: 2.34"
I tried the same string a few different ways (see snippet)
3 words using function in Tools
Using the following method
Gives 9 if in one paragraph
Gives 20 if in a vertical stream
Gives 28 if each in a table

I guess that's what the documentation says, but  VBA nomenclature in MS-Word uses the word 'word' in a misleading way. Just fine to define a / as a word? I don't think so. An invisible paragraph mark as a word? Not so much. Call it a token.count  or something, but not a word.count.
Jeez Louize.
He/She was: 2.34								
Per Tools>Word Count&					
3 Words	 { He/She | was: | 2.34 }				
Per ActiveDocument.Bookmarks(MyBkmrk).Range.Words.Count 	
9 Words	 { He | / | She | was | : | 2 | . | 34 | ^p }
If in paragraphs					
20 Words							
	He	^p					
	/	^p					
	She	^p					
	Was	^p					
	:	^p					
	2	^p					
	.	^p					
	34	^p

Open in new window

canesbrAuthor Commented:
So it seems that there is no VB function that will replicate the Tools>Word Count..."
One has to use a kluge like creating a new doc?
canesbrAuthor Commented:
Also continue to feel that definition of word here is so divergent as to demand a different word, like token, as I said.
I find that a lot of solutions to my more tricky problems involve an iterative exchange (exactly). This one was particularly satisfying.
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.