vba Word how to get sentences in a table - vba

I have a Word document, with the first two sentences as normal text and sentences three and four in a table (in one cell):
My first sentence. My second sentence.
My third sentence. My fourth sentence.
My code is the following:
Option Explicit
Sub test()
Dim sentence As Variant
Dim i As Long: i = 0
Selection.Expand wdSentence
Debug.Print "--------->" & ActiveDocument.ActiveWindow.Selection.Sentences.Count
Debug.Print "selection: " & ActiveDocument.ActiveWindow.Selection
For Each sentence In ActiveDocument.ActiveWindow.Selection.Sentences
i = i + 1
Debug.Print i & " sentence: " & sentence
Next
End Sub
If I select the first two sentences, the debug output is correct:
--------->2
selection: My first sentence. My second sentence.
1 sentence: My first sentence.
2 sentence: My second sentence.
If I select the two sentences in the table, the debug output is strange (or wrong?):
--------->2
selection: My third sentence. My fourth sentence.
1 sentence: My third sentence.
Why is the output of the table content different from normal text? How can I get the same result for the table content as for the normal text?

Tables bring a another whole dimension of complexity to what Word recognizes as a sentence. Paragraph, end of cell marks, and end of row markers all factor into the confusion of what constitutes a sentence to VBA.
Here is some code that should work, but I can’t claim with 100% certainty that it will work in all situations. In other words, I know it can be improved upon, but it should give you a good start for your own debugging sessions.
Sub ParseBySentence()
Dim doc As Word.Document
Dim i As Long, s As Long, para As Word.Paragraph
Dim rng As Word.Range, sRng As Word.Range
Application.ScreenUpdating = False
On Error Resume Next
Set doc = ActiveDocument
For i = 1 To doc.Paragraphs.Count
Set para = doc.Paragraphs(i)
If para.Range.Information(wdWithInTable) Then
Set rng = para.Range
Do While Asc(rng.Characters.Last) = 13
rng.MoveEnd unit:=wdCharacter, Count:=-1
Loop
If rng.Text = vbNullString Or _
Asc(rng.Text) = 13 Then
'do nothing
Else
For s = 1 To rng.Sentences.Count
Set sRng = rng.Sentences(s)
Do While Asc(sRng.Characters.Last) = 13
sRng.MoveEnd unit:=wdCharacter, Count:=-1
Loop
sRng.Select
Debug.Print Selection.Text
Selection.Collapse Word.WdCollapseDirection.wdCollapseEnd
Next
End If
End If
Next
Selection.HomeKey unit:=wdStory
Application.ScreenUpdating = True
MsgBox "Action Complete"
End Sub

#Rich Michaels: Thanks for the hint with the paragraphs. I made a fast and minimalistic macro that also works in tables:
Sub Par2Sen()
Dim s0, s1, smax As Long
Dim para As Word.Paragraph
Dim r() As Byte
For Each para In ActiveDocument.Paragraphs
r = para.Range
Debug.Print "> Paragraph= " & para.Range;
smax = UBound(r) - 1
s0 = 0
s1 = 0
Do Until s1 > smax
If r(s1) = 46 Or s1 = smax Then
Debug.Print "-> Sen from" & (s0 / 2) + 1 & " to " & (s1 / 2) + 1 & MidB$(r, s0 + 1, s1 - s0 + 3)
s0 = s1 + 2
End If
s1 = s1 + 2
Loop
Next
End Sub

Related

How to split cells containing "hard returns"

How to split cells containing "hard returns" (paragraph marks)
as in the picture below?
the desired result:
Here is my code
Sub SplitCells()
'
Dim selT As String
Dim arr
Dim i As Integer
selT = selection.Range.Text
arr = Split(selT, ChrW(13))
selection.Range.Cut
selection.Cells.Split NumRows:=UBound(arr) + 1, NumColumns:=1, MergeBeforeSplit:=False
selection.MoveDown wdLine, 1
For i = UBound(arr) To 0 Step -1
selection.MoveUp wdLine, 1
selection.TypeText arr(i)
Next
End Sub
It works, but I feel this code is clumsy and hope someone can tell me a elegant way.
Try the following; it will split all affected rows in the selected table.
Sub Demo()
Application.ScreenUpdating = False
Dim Tbl As Table, RngA As Range, RngB As Range
Dim i As Long, l As Long, r As Long, c As Long, p As Long
With Selection
If .Information(wdWithInTable) = False Then
MsgBox "Please select a table/cell and try again."
Exit Sub
End If
Set Tbl = .Tables(1)
With Tbl
l = .Columns.Count
For i = .Range.Cells.Count To 1 Step -1
With .Range.Cells(i).Range
Do While .Characters.Last.Previous = vbCr
.Characters.Last.Previous = vbNullString
Loop
End With
Next
For r = .Rows.Count To 1 Step -1
With .Rows(r)
If .Range.Paragraphs.Count > l + 1 Then
For c = 1 To .Cells.Count
If .Cells(c).Range.Paragraphs.Count > p Then p = .Cells(c).Range.Paragraphs.Count
Next
If p > 1 Then .Cells.Split Numrows:=p, Numcolumns:=1, MergeBeforeSplit:=False
For c = 1 To .Cells.Count
Set RngA = .Cells(c).Range
If RngA.Paragraphs.Count > 1 Then
For p = RngA.Paragraphs.Count To 2 Step -1
Set RngB = RngA.Paragraphs(p).Range
RngB.End = RngB.End - 1
If Len(RngB.Text) > 0 Then
With Tbl.Cell(r + p - 1, c).Range
.FormattedText = RngB.FormattedText
RngB.Delete
End With
End If
RngA.Paragraphs(p - 1).Range.Characters.Last = vbNullString
Next
End If
Next
End If
End With
Next
End With
End With
Application.ScreenUpdating = True
End Sub
Compared to your approach, the above code also has the advantage of preserving any text formatting.
There's nothing wrong with it, really. In order to move up/down in a table with split/merged cells you need Selection...
Here's code that uses the object model instead of Selection as much as possible. But I'm not sure I'd term it "more elegant" or "less clumsy". Possibly, it's more self-documenting since it uses Word objects where ever possible.
One change I did make is to test whether the selection is in a table before doing anything. If the user would forget to select a cell without such a test a cryptic error messsage would display, which is always annoying...
Sub SplitCells()
'
Dim cel As Word.Cell
Dim selT As String
Dim arr
Dim i As Integer
Dim nrCells As Long
If Selection.Information(wdWithInTable) Then
Set cel = Selection.Cells(1)
selT = cel.Range.Text
arr = Split(selT, ChrW(13))
nrCells = UBound(arr)
cel.Range.Delete
cel.Split NumRows:=nrCells, NumColumns:=1 ', _
'MergeBeforeSplit:=False
cel.Select
Selection.MoveDown wdLine, nrCells - 1
For i = nrCells - 1 To 0 Step -1
Set cel = Selection.Cells(1)
cel.Range.Text = arr(i)
cel.Select
Selection.MoveUp wdLine, 1
Next
Else
MsgBox "Please select a table cell and try again."
End If
End Sub

Word macro doesn't work as soon as I use With...End With

I've experienced something weird today while making a macro.
I have a lot of documents using the same template so my macro scan one of them and do some stuff depending on the title (level and number). Anyway, it doesn't realy matter. Here is the code
Private Sub MyMacro()
Selection.HomeKey Unit:=wdStory
While Not (Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 1) = "3") 'go to Title n°3
Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
Wend
While ((Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 1) = "3")) 'do not go further than title n°3
'if the curent title level is 2 and ended with 1,2 or 3 then
If Selection.Paragraphs(1).Range.ListFormat.ListLevelNumber = 2 And Selection.Paragraphs(1).Range.ListFormat.ListValue < 4 Then
'Do Something
ElseIf Selection.Paragraphs(1).Range.ListFormat.ListLevelNumber = 3 And Selection.Paragraphs(1).Range.ListFormat.ListValue <> 4 And Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 4) = "3.1." Then
'Do something else
ElseIf Selection.Paragraphs(1).Range.ListFormat.ListLevelNumber = 4 And Left(Selection.Paragraphs(1).Range.ListFormat.ListString, 5) = "3.2.1" Then
'and a last one
End If
'go to the next title in the document
Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
Wend
End Sub
This code works but as you can see it's not very easy to read...
I try to insert a With...End With statement to improve this.
With Selection.Paragraphs(1).Range.ListFormat
'isert here the same code as before with only .ListString and .ListLevelNumber
End With
Unfortunately, this makes my While loops failed, and I can't figure out why.
I monitored the outputs and it appears ListString always return the first title (where the macro starts).
Have you got any idea why?
Thanks a lot in advance
Regards
EDIT :
The final code is supposed to look like this
Private Sub MyMacro()
Selection.HomeKey Unit:=wdStory
With Selection.Paragraphs(1).Range.ListFormat
While Not (Left(.ListString, 1) = "3") 'go to Title n°3
Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
Wend
While ((Left(.ListString, 1) = "3")) 'do not go further than title n°3
'if the curent title level is 2 and ended with 1,2 or 3 then
If .ListLevelNumber = 2 And .ListValue < 4 Then
'Do Something
ElseIf .ListLevelNumber = 3 And .ListValue <> 4 And Left(.ListString, 4) = "3.1." Then
'Do something else
ElseIf .ListLevelNumber = 4 And Left(.ListString, 5) = "3.2.1" Then
'and a last one
End If
'go to the next title in the document
Selection.GoTo what:=wdGoToHeading, which:=wdGoToNext
Wend
End With
End Sub
The reason what you've attempted is not working is that With is always referencing Selection.Paragraphs(1).Range at the time this line is called and testing whether the left-most character is "3". Since the number at the beginning of that first paragraph never changes, the code doesn't work as you hope. If you put Debug.Print .ListString just before the Wend you can see that it never changes.
Here's a different way to write your code to make it easier to follow, just to give you an idea how to work with a Range object. It loops all the numbered ("list") paragraphs in the document and will skip any non-numbered paragraphs. This may not be optimal in your case - since you don't give any details about the document, it's hard to know.
Sub MyMacro()
Dim rng As Word.Range
Dim paras As Word.ListParagraphs
Dim para As Word.Paragraph
Dim lvl As Long, listVal As Long
Set paras = ActiveDocument.ListParagraphs
For Each para In paras
Set rng = para.Range
If Left(rng.ListFormat.ListString, 1) = "3" Then
lvl = rng.ListFormat.ListLevelNumber
listVal = rng.ListFormat.ListValue
Select Case lvl
Case 2
If listVal < 4 Then
Debug.Print "Case 2: lvl " & lvl & "; listVal " & listVal
End If
Case 3
If listVal <> 4 And Left(rng.ListFormat.ListString, 4) = "3.1." Then
Debug.Print "Case 3: lvl " & lvl & "; listVal " & listVal
End If
Case 4
If Left(rng.ListFormat.ListString, 5) = "3.2.1" Then
Debug.Print "Case 4: lvl " & lvl & "; listVal " & listVal
End If
Case Else
Debug.Print "Case else"
End Select
End If
Next
End Sub

Looping through cell values in Excel VBA

I have been trying to write a program that will loop through all the cells in an excel sheet and if one starts with a '#' it should display a message. here's the code:
(template is a worksheet variable)
Private Function processTemplate()
Dim total As Long
total = template.UsedRange.count
Dim count As Integer
count = 0
While count <= total
If template.Cells(count).Value Like "[#]*" Then 'Here I get a error
MsgBox "Found #"
End If
count = count + 1
Wend
End Function
I have isolated the error to using a variable inside of cells(). If I replace count with some number (like 8) it works fine. I am getting error 1004 on the line If template.Cells(count).Value Like "[#]*" Then
If I make total an Integer it has the same error at the same place. After about 2-3 hrs of research/banging my head on the wall I have no idea. I initially got the error when assigning template.cells(row, col).Value to a string variable.
Here's my code now:
Private Sub processTemplate()
MsgBox Len("")
Dim str As String
Dim rows As Long
Dim cols As Long
rows = template.UsedRange.Height
cols = template.UsedRange.Width
Dim row As Integer
row = 1
While row < rows
Dim col As Integer
col = 1
While col < cols
str = template.Cells(row, col).Text
If Len(str) > 0 Then
If Left(template.Cells(row, col).Text, 1) = "#" Then
MsgBox "Found IT"
End If
End If
Rem MsgBox template.Parent.Name & ": " & template.Name & ", Cell(" & row & ", " & col & "): " & template.Cells(row, col).Value
col = col + 1
Wend
row = row + 1
Wend
End Sub
Now I get the error on str = template.Cells(row, col).Text
We can use a sub rather than a function
We loop over all the cells in UsedRange looking for a # as the first character in the cell.
Sub FindThePound()
Dim r As Range, pound As String, template As Worksheet
pound = "#"
Set template = ActiveSheet
For Each r In template.UsedRange
If Left(r.Value, 1) = pound Then
MsgBox "Found # in " & r.Address(0, 0)
End If
Next r
End Sub
EDIT#1
This version loops over all the cells, but does not test cells containing formulas
Sub FindThePound()
Dim r As Range, pound As String, template As Worksheet
pound = "#"
Set template = ActiveSheet
For Each r In template.UsedRange
If r.HasFormula = False Then
If Left(r.Value, 1) = pound Then
MsgBox "Found # in " & r.Address(0, 0)
End If
End If
Next r
End Sub
You could use find/ find next function which i guess bit faster than looping through each cell and do string comparison.
With Worksheets(1).Range("a1:a500") 'Provide the search range
Set c = .Find(2, lookin:=xlValues) ' searching for 2 in cell value
If Not c Is Nothing Then
firstAddress = c.Address 'first occurance
Do
'do whatever you want to do with the matches even replace them
c.Value = 5
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End With
Reference:
http://msdn.microsoft.com/en-us/library/office/ff196143(v=office.15).aspx

MS Word 2010 VBA - how to parse non-latin characters?

I have a VBA script that prints out the word frequency in a document.
Sub WordFrequency()
Const maxwords = 9000 'Maximum unique words allowed
Dim SingleWord As String 'Raw word pulled from doc
Dim Words(maxwords) As String 'Array to hold unique words
Dim Freq(maxwords) As Integer 'Frequency counter for unique words
Dim WordNum As Integer 'Number of unique words
Dim ByFreq As Boolean 'Flag for sorting order
Dim ttlwds As Long 'Total words in the document
Dim Excludes As String 'Words to be excluded
Dim Found As Boolean 'Temporary flag
Dim j, k, l, Temp As Integer 'Temporary variables
Dim ans As String 'How user wants to sort results
Dim tword As String '
' Set up excluded words
Excludes = "[the][a][of][is][to][for][by][be][and][are]"
' Find out how to sort
ByFreq = True
ans = InputBox("Sort by WORD or by FREQ?", "Sort order", "WORD")
If ans = "" Then End
If UCase(ans) = "WORD" Then
ByFreq = False
End If
Selection.HomeKey Unit:=wdStory
System.Cursor = wdCursorWait
WordNum = 0
ttlwds = ActiveDocument.Words.Count
' Control the repeat
For Each aword In ActiveDocument.Words
SingleWord = Trim(LCase(aword))
'Out of range?
If SingleWord < "a" Or SingleWord > "z" Then
SingleWord = ""
End If
'On exclude list?
If InStr(Excludes, "[" & SingleWord & "]") Then
SingleWord = ""
End If
If Len(SingleWord) > 0 Then
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
If WordNum > maxwords - 1 Then
j = MsgBox("Too many words.", vbOKOnly)
Exit For
End If
End If
ttlwds = ttlwds - 1
StatusBar = "Remaining: " & ttlwds & ", 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
' Now write out the results
tmpName = ActiveDocument.AttachedTemplate.FullName
Documents.Add Template:=tmpName, NewTemplate:=False
Selection.ParagraphFormat.TabStops.ClearAll
With Selection
For j = 1 To WordNum
.TypeText Text:=Trim(Str(Freq(j))) _
& vbTab & Words(j) & vbCrLf
Next j
End With
System.Cursor = wdCursorNormal
j = MsgBox("There were " & Trim(Str(WordNum)) & _
" different words ", vbOKOnly, "Finished")
End Sub
However, this VBA script is not picking up non-latin characters in the document.
I am using Arial Unicode MS and another unicode font
What do I need in the macro to pick up these words?
-Thanks
It can't work with this...
If SingleWord < "a" Or SingleWord > "z" Then
SingleWord = ""
End If
Remove that, and you should at least see non-Latin words. Beyond that, it's more a question of what you are trying to filter out. If it's stuff like "'words' starting with a digit or a punctuation mark" then you probably need to have a look through the Unicode tables and work out a better set of things to filter out (bearing in mind that some transliterated scripts may even use digits at the beginnings of words).

Highlight (not delete) repeat sentences or phrases

I am getting the impression that this is not possible in word but I figure if you are looking for any 3-4 words that come in the same sequence anywhere in a very long paper I could find duplicates of the same phrases.
I copy and pasted a lot of documentation from past papers and was hoping to find a simple way to find any repeated information in this 40+ page document there is a lot of different formatting but I would be willing to temporarily get rid of formatting in order to find repeated information.
To highlight all duplicate sentences, you can also use ActiveDocument.Sentences(i). Here is an example
LOGIC
1) Get all the sentences from the word document in an array
2) Sort the array
3) Extract Duplicates
4) Highlight duplicates
CODE
Option Explicit
Sub Sample()
Dim MyArray() As String
Dim n As Long, i As Long
Dim Col As New Collection
Dim itm
n = 0
'~~> Get all the sentences from the word document in an array
For i = 1 To ActiveDocument.Sentences.Count
n = n + 1
ReDim Preserve MyArray(n)
MyArray(n) = Trim(ActiveDocument.Sentences(i).Text)
Next
'~~> Sort the array
SortArray MyArray, 0, UBound(MyArray)
'~~> Extract Duplicates
For i = 1 To UBound(MyArray)
If i = UBound(MyArray) Then Exit For
If InStr(1, MyArray(i + 1), MyArray(i), vbTextCompare) Then
On Error Resume Next
Col.Add MyArray(i), """" & MyArray(i) & """"
On Error GoTo 0
End If
Next i
'~~> Highlight duplicates
For Each itm In Col
Selection.Find.ClearFormatting
Selection.HomeKey wdStory, wdMove
Selection.Find.Execute itm
Do Until Selection.Find.Found = False
Selection.Range.HighlightColorIndex = wdPink
Selection.Find.Execute
Loop
Next
End Sub
'~~> Sort the array
Public Sub SortArray(vArray As Variant, i As Long, j As Long)
Dim tmp As Variant, tmpSwap As Variant
Dim ii As Long, jj As Long
ii = i: jj = j: tmp = vArray((i + j) \ 2)
While (ii <= jj)
While (vArray(ii) < tmp And ii < j)
ii = ii + 1
Wend
While (tmp < vArray(jj) And jj > i)
jj = jj - 1
Wend
If (ii <= jj) Then
tmpSwap = vArray(ii)
vArray(ii) = vArray(jj): vArray(jj) = tmpSwap
ii = ii + 1: jj = jj - 1
End If
Wend
If (i < jj) Then SortArray vArray, i, jj
If (ii < j) Then SortArray vArray, ii, j
End Sub
SNAPSHOTS
BEFORE
AFTER
I did not use my own DAWG suggestion, and I am still interested in seeing if someone else has a way to do this, but I was able to come up with this:
Option Explicit
Sub test()
Dim ABC As Scripting.Dictionary
Dim v As Range
Dim n As Integer
n = 5
Set ABC = FindRepeatingWordChains(n, ActiveDocument)
' This is a dictionary of word ranges (not the same as an Excel range) that contains the listing of each word chain/phrase of length n (5 from the above example).
' Loop through this collection to make your selections/highlights/whatever you want to do.
If Not ABC Is Nothing Then
For Each v In ABC
v.Font.Color = wdColorRed
Next v
End If
End Sub
' This is where the real code begins.
Function FindRepeatingWordChains(ChainLenth As Integer, DocToCheck As Document) As Scripting.Dictionary
Dim DictWords As New Scripting.Dictionary, DictMatches As New Scripting.Dictionary
Dim sChain As String
Dim CurWord As Range
Dim MatchCount As Integer
Dim i As Integer
MatchCount = 0
For Each CurWord In DocToCheck.Words
' Make sure there are enough remaining words in our document to handle a chain of the length specified.
If Not CurWord.Next(wdWord, ChainLenth - 1) Is Nothing Then
' Check for non-printing characters in the first/last word of the chain.
' This code will read a vbCr, etc. as a word, which is probably not desired.
' However, this check does not exclude these 'words' inside the chain, but it can be modified.
If CurWord <> vbCr And CurWord <> vbNewLine And CurWord <> vbCrLf And CurWord <> vbLf And CurWord <> vbTab And _
CurWord.Next(wdWord, ChainLenth - 1) <> vbCr And CurWord.Next(wdWord, ChainLenth - 1) <> vbNewLine And _
CurWord.Next(wdWord, ChainLenth - 1) <> vbCrLf And CurWord.Next(wdWord, ChainLenth - 1) <> vbLf And _
CurWord.Next(wdWord, ChainLenth - 1) <> vbTab Then
sChain = CurWord
For i = 1 To ChainLenth - 1
' Add each word from the current word through the next ChainLength # of words to a temporary string.
sChain = sChain & " " & CurWord.Next(wdWord, i)
Next i
' If we already have our temporary string stored in the dictionary, then we have a match, assign the word range to the returned dictionary.
' If not, then add it to the dictionary and increment our index.
If DictWords.Exists(sChain) Then
MatchCount = MatchCount + 1
DictMatches.Add DocToCheck.Range(CurWord.Start, CurWord.Next(wdWord, ChainLenth - 1).End), MatchCount
Else
DictWords.Add sChain, sChain
End If
End If
End If
Next CurWord
' If we found any matching results, then return that list, otherwise return nothing (to be caught by the calling function).
If DictMatches.Count > 0 Then
Set FindRepeatingWordChains = DictMatches
Else
Set FindRepeatingWordChains = Nothing
End If
End Function
I have tested this on a 258 page document (TheStory.txt) from this source, and it ran in just a few minutes.
See the test() sub for usage.
You will need to reference the Microsoft Scripting Runtime to use the Scripting.Dictionary objects. If that is undesirable, small modifications can be made to use Collections instead, but I prefer the Dictionary as it has the useful .Exists() method.
I chose a rather lame theory, but it seems to work (at least if I got the question right cuz sometimes I'm a slow understander).
I load the entire text into a string, load the individual words into an array, loop through the array and concatenate the string, containing each time three consecutive words.
Because the results are already included in 3 word groups, 4 word groups or more will automatically be recognized.
Option Explicit
Sub Find_Duplicates()
On Error GoTo errHandler
Dim pSingleLine As Paragraph
Dim sLine As String
Dim sFull_Text As String
Dim vArray_Full_Text As Variant
Dim sSearch_3 As String
Dim lSize_Array As Long
Dim lCnt As Long
Dim lCnt_Occurence As Long
'Create a string from the entire text
For Each pSingleLine In ActiveDocument.Paragraphs
sLine = pSingleLine.Range.Text
sFull_Text = sFull_Text & sLine
Next pSingleLine
'Load the text into an array
vArray_Full_Text = sFull_Text
vArray_Full_Text = Split(sFull_Text, " ")
lSize_Array = UBound(vArray_Full_Text)
For lCnt = 1 To lSize_Array - 1
lCnt_Occurence = 0
sSearch_3 = Trim(fRemove_Punctuation(vArray_Full_Text(lCnt - 1) & _
" " & vArray_Full_Text(lCnt) & _
" " & vArray_Full_Text(lCnt + 1)))
With Selection.Find
.Text = sSearch_3
.Forward = True
.Replacement.Text = ""
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
Do While .Execute
lCnt_Occurence = lCnt_Occurence + 1
If lCnt_Occurence > 1 Then
Selection.Range.Font.Color = vbRed
End If
Selection.MoveRight
Loop
End With
Application.StatusBar = lCnt & "/" & lSize_Array
Next lCnt
errHandler:
Stop
End Sub
Public Function fRemove_Punctuation(sString As String) As String
Dim vArray(0 To 8) As String
Dim lCnt As Long
vArray(0) = "."
vArray(1) = ","
vArray(2) = ","
vArray(3) = "?"
vArray(4) = "!"
vArray(5) = ";"
vArray(6) = ":"
vArray(7) = "("
vArray(8) = ")"
For lCnt = 0 To UBound(vArray)
If Left(sString, 1) = vArray(lCnt) Then
sString = Right(sString, Len(sString) - 1)
ElseIf Right(sString, 1) = vArray(lCnt) Then
sString = Left(sString, Len(sString) - 1)
End If
Next lCnt
fRemove_Punctuation = sString
End Function
The code assumes a continuous text without bullet points.