Find Text strings containing "_" - vba

I am looking the for the correct syntax to use a text function to find strings that contain underscores. I have a very large document that has numerous tables names with underscores. They are in the format abc_def or abc_def_ghi or abc_def_ghi_jkl etc.
I have tried various combinations and cannot get anything to work as I expect it to. Below is my latest iteration.
Sub ExtractTablesToNewDocument()
'=========================
'Macro created 2008 by Lene Fredborg, DocTools - www.thedoctools.com
'THIS MACRO IS COPYRIGHT. YOU ARE WELCOME TO USE THE MACRO BUT YOU MUST KEEP THE LINE ABOVE.
'YOU ARE NOT ALLOWED TO PUBLISH THE MACRO AS YOUR OWN, IN WHOLE OR IN PART.
'=========================
'The macro creates a new document,
'finds all words consisting of 3 or more uppercase letters
'in the active document and inserts the words
'in column 1 of a 3-column table in the new document
'Each acronym is added only once
'Use column 2 for definitions
'Page number of first occurrence is added by the macro in column 3
'Minor adjustments are made to the styles used
'You may need to change the style settings and table layout to fit your needs
'=========================
Dim oDoc_Source As Document
Dim oDoc_Target As Document
Dim strListSep As String
Dim strAcronym As String
Dim oTable As Table
Dim oRange As Range
Dim n As Long
Dim strAllFound As String
Dim Title As String
Dim Msg As String
Title = "Extract Acronyms to New Document"
'Show msg - stop if user does not click Yes
Msg = "This macro finds all words consisting of 3 or more " & _
"uppercase letters and extracts the words to a table " & _
"in a new document where you can add definitions." & vbCr & vbCr & _
"Do you want to continue?"
If MsgBox(Msg, vbYesNo + vbQuestion, Title) <> vbYes Then
Exit Sub
End If
Application.ScreenUpdating = False
'Find the list separator from international settings
'May be a comma or semicolon depending on the country
strListSep = Application.International(wdListSeparator)
'Start a string to be used for storing names of acronyms found
strAllFound = "#"
Set oDoc_Source = ActiveDocument
'Create new document for acronyms
Set oDoc_Target = Documents.Add
With oDoc_Target
'Make sure document is empty
.Range = ""
'Insert info in header - change date format as you wish
.PageSetup.TopMargin = CentimetersToPoints(3)
.Sections(1).Headers(wdHeaderFooterPrimary).Range.Text = _
"Acronyms extracted from: " & oDoc_Source.FullName & vbCr & _
"Created by: " & Application.UserName & vbCr & _
"Creation date: " & Format(Date, "MMMM d, yyyy")
'Adjust the Normal style and Header style
With .Styles(wdStyleNormal)
.Font.Name = "Arial"
.Font.Size = 10
.ParagraphFormat.LeftIndent = 0
.ParagraphFormat.SpaceAfter = 6
End With
With .Styles(wdStyleHeader)
.Font.Size = 8
.ParagraphFormat.SpaceAfter = 0
End With
'Insert a table with room for acronym and definition
Set oTable = .Tables.Add(Range:=.Range, NumRows:=2, NumColumns:=3)
With oTable
'Format the table a bit
'Insert headings
.Range.Style = wdStyleNormal
.AllowAutoFit = False
.Cell(1, 1).Range.Text = "Acronym"
.Cell(1, 2).Range.Text = "Definition"
.Cell(1, 3).Range.Text = "Page"
'Set row as heading row
.Rows(1).HeadingFormat = True
.Rows(1).Range.Font.Bold = True
.PreferredWidthType = wdPreferredWidthPercent
.Columns(1).PreferredWidth = 20
.Columns(2).PreferredWidth = 70
.Columns(3).PreferredWidth = 10
End With
End With
With oDoc_Source
Set oRange = .Range
n = 1 'used to count below
With oRange.Find
'Use wildcard search to find strings consisting of 3 or more uppercase letters
'Set the search conditions
'NOTE: If you want to find acronyms with e.g. 2 or more letters,
'change 3 to 2 in the line below
.Text = "<*>[_]<*>"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWildcards = True
'Perform the search
Do While .Execute
'Continue while found
strAcronym = oRange
'Insert in target doc
'If strAcronym is already in strAllFound, do not add again
If InStr(1, strAllFound, "#" & strAcronym & "#") = 0 Then
'Add new row in table from second acronym
If n > 1 Then oTable.Rows.Add
'Was not found before
strAllFound = strAllFound & strAcronym & "#"
'Insert in column 1 in oTable
'Compensate for heading row
With oTable
.Cell(n + 1, 1).Range.Text = strAcronym
'Insert page number in column 3
.Cell(n + 1, 3).Range.Text = oRange.Information(wdActiveEndPageNumber)
End With
n = n + 1
End If
Loop
End With
End With
'Sort the acronyms alphabetically - skip if only 1 found
If n > 2 Then
With Selection
.Sort ExcludeHeader:=True, FieldNumber:="Column 1", SortFieldType _
:=wdSortFieldAlphanumeric, SortOrder:=wdSortOrderAscending
'Go to start of document
.HomeKey (wdStory)
End With
End If
Application.ScreenUpdating = True
'If no acronyms found, show msg and close new document without saving
'Else keep open
If n = 1 Then
Msg = "No acronyms found."
oDoc_Target.Close savechanges:=wdDoNotSaveChanges
Else
Msg = "Finished extracting " & n - 1 & " acronymn(s) to a new document."
End If
MsgBox Msg, vbOKOnly, Title
'Clean up
Set oRange = Nothing
Set oDoc_Source = Nothing
Set oDoc_Target = Nothing
Set oTable = Nothing
End Sub

Try:
.Text = "[! ]#_[! ]{1,}"
This will find strings containing however many underscores there might be, including where those strings start or end with an underscore.

Try:
Sub AcronymLister()
Application.ScreenUpdating = False
Dim StrTmp As String, StrAcronyms As String, i As Long, j As Long, k As Long, Rng As Range, Tbl As Table
StrAcronyms = "Acronym" & vbTab & "Page" & vbCr
With ActiveDocument
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWildcards = True
.Wrap = wdFindStop
.Text = "[! ^13^t^11]#_[! ^13^t^11]{1,}"
.Replacement.Text = ""
.Execute
End With
Do While .Find.Found = True
If InStr(1, StrAcronyms, .Text, vbBinaryCompare) = 0 Then
StrAcronyms = StrAcronyms & .Text & vbTab & .Information(wdActiveEndAdjustedPageNumber) & vbCr
End If
If Len(.Text) = 0 Then .End = .Paragraphs(1).Range.Next.Start
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
With .Range
Set Rng = .Characters.Last
With Rng
If .Characters.First.Previous <> vbCr Then .InsertAfter vbCr
.InsertAfter Chr(12)
.Collapse wdCollapseEnd
.Style = "Normal"
.Text = StrAcronyms
Set Tbl = .ConvertToTable(Separator:=vbTab, NumRows:=.Paragraphs.Count, NumColumns:=2)
With Tbl
.Columns.AutoFit
.Rows(1).HeadingFormat = True
.Rows(1).Range.Style = "Strong"
.Rows.Alignment = wdAlignRowCenter
End With
.Collapse wdCollapseStart
End With
End With
End With
Set Rng = Nothing: Set Tbl = Nothing
Application.ScreenUpdating = True
End Sub
Note: The above code puts the acronym table at the end of the current document. I've modified the Find expression to exclude tabs, paragraph breaks & line breaks.

Sub AcronymLister()
Application.ScreenUpdating = False
Dim StrTmp As String, StrAcronyms As String, i As Long, j As Long, k As Long, Rng As Range, Tbl As Table
StrAcronyms = "Acronym" & vbTab & "Page" & vbCr
With ActiveDocument
With .Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.MatchWildcards = True
.Wrap = wdFindStop
.Text = "[! ^13^t^11]#_[! ^13^t^11]{1,}"
.Replacement.Text = ""
.Execute
End With
Do While .Find.Found = True
If InStr(.Text, "_") = 0 Then
If InStr(1, StrAcronyms, .Text, vbBinaryCompare) = 0 Then
StrAcronyms = StrAcronyms & .Text & vbTab & .Information(wdActiveEndAdjustedPageNumber) & vbCr
Else
.End = .Paragraphs(1).Range.Next.Start
End If
End If
If InStr(.Text, "_") > 0 Then
If InStr(1, StrAcronyms, .Text, vbBinaryCompare) = 0 Then
StrAcronyms = StrAcronyms & .Text & vbTab & .Information(wdActiveEndAdjustedPageNumber) & vbCr
Else
.End = .Paragraphs(1).Range.Next.Start
End If
End If
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
With .Range
Set Rng = .Characters.Last
With Rng
If .Characters.First.Previous <> vbCr Then .InsertAfter vbCr
.InsertAfter Chr(12)
.Collapse wdCollapseEnd
.Style = "Normal"
.Text = StrAcronyms
Set Tbl = .ConvertToTable(Separator:=vbTab, NumRows:=.Paragraphs.Count, NumColumns:=2)
With Tbl
.Columns.AutoFit
.Rows(1).HeadingFormat = True
.Rows(1).Range.Style = "Strong"
.Rows.Alignment = wdAlignRowCenter
End With
.Collapse wdCollapseStart
End With
End With
End With
Set Rng = Nothing: Set Tbl = Nothing
Application.ScreenUpdating = True
End Sub
#macropod i added a loop to handle zero length strings and the code appears to be working. I know this is not the most efficient method, do you have any suggestions for improvement? Thank you again for walking me through this i really appreciate all your help and knowledge.

Related

VB.NET MS Word - How to store a ms word table cell corresponding to a FOUND word.range into a table.Cell variable

I am trying to find a string in my word document header table. I can find the range but I want to store the specific cell which this found range is located in into a table.cell variable.
How can I do it?
In VBA, for example, to retrieve the cell's table#, row # & column #:
Sub GetCellRef()
Application.ScreenUpdating = False
Dim Rng As Range, t As Long, r As Long, c As Long
With ActiveDocument.Sections.First.Headers(wdHeaderFooterPrimary)
Set Rng = .Range
With .Range
With .Find
.Text = "Text to Find"
.Forward = True
.Wrap = wdFindStop
.MatchCase = False
.MatchWholeWord = True
.Execute
End With
If .Find.Found = True Then
If .Information(wdWithInTable) = True Then
Rng.End = .Cells(1).Range.End - 1
t = Rng.Tables.Count
Rng.Start = .Start
r = .Cells(1).RowIndex
c = .Cells(1).ColumnIndex
MsgBox Chr(34) & Rng.Text & Chr(34) & vbCr & _
"Found in table " & t & " at row " & r & " column " & c
End If
End If
End With
End With
Application.ScreenUpdating = True
End Sub

Change cross-reference text in middle of the text to lowercase using showfieldcodes

I want to change all the cross-reference text that are in middle of the text to lowercase, but not the ones at the beginning of a sentence.
The problem is that ActiveDocument.Paragraphs(row).Range.Text is going through the original text, not the ShowFieldCodes (or Alt+F9 view), which generates longer paragraphs and rows.
Sub SetLowerCase()
Dim bBig As Boolean
Dim txt As String, row As String, pos As Integer
ActiveWindow.View.ShowFieldCodes = True
Selection.HomeKey unit:=wdStory
With Selection.Find
.ClearFormatting
.Text = "^d REF"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = False
Do While .Execute
pos = Selection.Information(wdFirstCharacterColumnNumber)
row = Selection.Information(wdFirstCharacterLineNumber)
'The problem is that "ShowFieldCodes" generates longer paragraphs and more rows, which the next line does not take into account
txt = ActiveDocument.Paragraphs(row).Range.Text
If pos = 1 Then
bBig = True
ElseIf Mid(txt, pos - 2, 2) = ". " Then
bBig = True
ElseIf Mid(txt, pos - 1, 1) = "." Then
bBig = True
End If
If bBig = False Then
If Not Selection.Text Like "*Lower*" Then
With Selection
.MoveRight unit:=wdCharacter, Count:=1
.MoveLeft unit:=wdCharacter, Count:=1
.TypeText Text:="\*Lower "
.Fields.Update
End With
End If
Else
bBig = False
End If
Selection.Collapse wdCollapseEnd
Loop
End With
ActiveWindow.View.ShowFieldCodes = False
End Sub
For example:
Sub Demo()
Application.ScreenUpdating = False
Dim Fld As Field, Rng As Range, StrRef As String
With ActiveDocument
.ActiveWindow.View.ShowFieldCodes = False
For Each Fld In .Range.Fields
With Fld
If .Type = wdFieldRef Then
Set Rng = .Result: StrRef = Split(Trim(.Code.Text), " ")(1)
Rng.MoveStart wdSentence, -1
Rng.MoveEnd wdSentence, 1
If Rng.Sentences.Count = 1 Then
.Code.Text = "REF " & StrRef & " \* Lower \h"
Else
.Code.Text = "REF " & StrRef & " \* FirstCap \h"
End If
End If
End With
Next
.Fields.Update
End With
Application.ScreenUpdating = True
End Sub
Whichever approach you take, you'll run up against VBA's ignorance of what a grammatical sentence is. For example, consider the following:
Mr. Smith spent $1,234.56 at Dr. John's Grocery Store, to buy: 10.25kg of potatoes; 10kg of avocados; and 15.1kg of Mrs. Green's Mt. Pleasant macadamia nuts.
For you and me, that would count as one sentence; for VBA it counts as 5...

Determine if a word is within 125 words of a match

I want to loop through a document, and for each word, see if there is a match within 250 words (125 behind and 125 ahead).
If there is a match(s), highlight it. Certain words are excluded. These are stored in a dictionary.
To test the loop I am using,
For Each para In ActiveDocument.Paragraphs
For Each wrd In para.Range.Words
Debug.Print wrd & "----" & wrd.Start
Next wrd
Next para
The problem:
"World" in the sentence "I hate traveling to the spirit world", prints 32 when I am looking for 7.
I want to do something like:
If wrd < 125 Then
Set wrdRng = ActiveDocument.Range(Start:=wrd - 125, End:=ActiveDocument.Words(wrd + 125).End)
Else
Set wrdRng = ActiveDocument.Range(Start:=0, End:=ActiveDocument.Words(250 - wrd).End)
End if
Edit:
The current code I'm using completes a loop on a 50,000 word document in about 13 minutes. That is entirely too long. Anyone have a better alternative?
Sub Demo()
Application.ScreenUpdating = False
Dim i As Long
Dim StartTime As Double
Dim MinutesElapsed As String
StartTime = Timer
For Each Para In ActiveDocument.Paragraphs
For Each wrd In Para.Range.Words
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "<(McKnight)*\1>"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWildcards = True
End With
Do While .Find.Execute
If .ComputeStatistics(wdStatisticWords) < 100 Then
i = i + 1
.Words.First.HighlightColorIndex = wdBrightGreen
.Words.Last.HighlightColorIndex = wdBrightGreen
End If
.End = .End - Len(.Words.Last)
.Collapse wdCollapseEnd
Loop
End With
Application.ScreenUpdating = True
'MsgBox i & " instances found."
Debug.Print wrd
Next wrd
Next Para
MinutesElapsed = Format((Timer - StartTime) / 86400, "hh:mm:ss")
MsgBox "This code ran successfully in " & MinutesElapsed & " minutes", vbInformation
End Sub
EDIT:
Sub Demo()
Application.ScreenUpdating = False
Dim i As Long
Dim StartTime As Double
Dim MinutesElapsed As String
StartTime = Timer
For Each para In ActiveDocument.Paragraphs
For Each wrd In para.Range.Words
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "<(wrd)*\1>"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWildcards = True
End With
Do While .Find.Execute
If .ComputeStatistics(wdStatisticWords) < 100 Then
i = i + 1
.Words.First.HighlightColorIndex = wdBrightGreen
.Words.Last.HighlightColorIndex = wdBrightGreen
End If
.End = .End - Len(.Words.Last)
.Collapse wdCollapseEnd
Loop
End With
Application.ScreenUpdating = True
'MsgBox i & " instances found."
'Debug.Print wrd
Next wrd
Next para
MinutesElapsed = Format((Timer - StartTime) / 86400, "hh:mm:ss")
MsgBox "This code ran successfully in " & MinutesElapsed & " minutes", vbInformation
End Sub
Try the following. Amongst other things, it allows you to specify words to ignore (e.g. prepositions, articles, etc.). Additionally different highlights are used to identify all 'hits' on a given word. A progress report is given on the status bar. On my laptop, it takes about 6:40 for a 50,000 word 'lorem' document.
Option Explicit
Dim ArrOut() As String
Sub Demo()
' Turn Off Screen Updating
Application.ScreenUpdating = False
Dim eTime As Single
' Start Timing
eTime = Timer
Dim wdDoc As Document, StrFnd As String, StrTmp As String, Rng As Range
Dim SBar As Boolean, bTrk As Boolean, h As Long, i As Long, j As Long
' Store current Status Bar status, then switch on
SBar = Application.DisplayStatusBar
Application.DisplayStatusBar = True
Set wdDoc = ActiveDocument
With wdDoc
' Store current Track Changes status, then switch off
bTrk = .TrackRevisions: .TrackRevisions = False
'Display status
Application.StatusBar = "Building word list"
'Compile the Find list
Call BuildWordList(.Range.Text)
With .Range.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = ""
.Replacement.Text = ""
.Format = False
.MatchCase = False
.MatchWholeWord = True
.Wrap = wdFindStop
.Execute
End With
End With
'Process all words in the concordance
For i = 0 To UBound(ArrOut())
StrFnd = ArrOut(i)
h = i Mod 14
If h < 6 Then
h = h + 2
Else
h = h + 3
End If
'Display current word
Application.StatusBar = "Processing: " & StrFnd
'Use wildcards, if possible, for extra speed
If Len(StrFnd) < 4 Then
StrTmp = ""
For j = 1 To Len(StrFnd)
StrTmp = StrTmp & "[" & UCase(Mid(StrFnd, j, 1)) & Mid(StrFnd, j, 1) & "]"
Next
StrFnd = StrTmp
With wdDoc.Range
With .Find
.MatchWildcards = True
.Text = "<(" & StrFnd & ")>*<(" & StrFnd & ")>"
.Forward = True
.Wrap = wdFindStop
End With
Do While .Find.Execute
If .ComputeStatistics(wdStatisticWords) < 100 Then
If .Words.First.HighlightColorIndex <> h Then .Words.First.HighlightColorIndex = h
.Words.Last.HighlightColorIndex = h
End If
.End = .End - Len(.Words.Last)
.Collapse wdCollapseEnd
Loop
End With
Else
With wdDoc.Range
With .Find
.MatchWildcards = False
.Text = StrFnd
.Forward = True
.Wrap = wdFindStop
.Execute
End With
Set Rng = .Duplicate
Do While .Find.Execute
Rng.End = .Duplicate.End
With Rng
If .ComputeStatistics(wdStatisticWords) < 100 Then
If .Words.First.HighlightColorIndex <> h Then .Words.First.HighlightColorIndex = h
.Words.Last.HighlightColorIndex = h
End If
End With
Set Rng = .Duplicate
.Collapse wdCollapseEnd
Loop
End With
End If
DoEvents
Next
' Restore original Track Changes status
wdDoc.TrackRevisions = bTrk
' Clear the Status Bar
Application.StatusBar = False
' Restore original Status Bar status
Application.DisplayStatusBar = SBar
' Restore Screen Updating
Application.ScreenUpdating = True
' Calculate elapsed time
eTime = (Timer - eTime + 86400) Mod 86400 ' Just in case execution time spans midnight
MsgBox "Execution took " & Format(eTime / 86400, "hh:mm:ss") & " to process"
End Sub
Sub BuildWordList(StrIn As String)
Dim StrFnd As String, i As Long, j As Long, k As Long
'Define the exlusions list
Const StrExcl As String = "a,am,and,are,as,at,be,but,by,can,cm,did,do,does,eg," & _
"en,eq,etc,for,get,go,got,has,have,he,her,him,how,i,ie,if,in,into,is," & _
"it,its,me,mi,mm,my,na,nb,no,not,of,off,ok,on,one,or,our,out,re,she," & _
"so,the,their,them,they,t,to,was,we,were,who,will,would,yd,you,your"
'Strip out unwanted characters
For i = 1 To 255
Select Case i
Case 1 To 31, 33 To 64, 91 To 96, 123 To 144, 147 To 191, 247
Do While InStr(StrIn, Chr(i)) > 0
StrIn = Replace(StrIn, Chr(i), " ")
Loop
End Select
Next
'Convert smart single quotes to plain single quotes & delete any at the start/end of a word
StrIn = Replace(Replace(Replace(Replace(StrIn, Chr(145), "'"), Chr(146), "'"), "' ", " "), " '", " ")
'Convert to lowercase
StrIn = " " & LCase(StrIn) & " "
'Process the exclusions list
For i = 0 To UBound(Split(StrExcl, ","))
StrFnd = " " & Split(StrExcl, ",")(i) & " "
Do While InStr(StrIn, StrFnd) > 0
StrIn = Replace(StrIn, " " & Split(StrExcl, ",")(i) & " ", " ")
Loop
Next
'Clean up any duplicate spaces
Do While InStr(StrIn, " ") > 0
StrIn = Replace(StrIn, " ", " ")
Loop
i = 0
Do While UBound(Split(StrIn, " ")) > 1
StrFnd = " " & Split(StrIn, " ")(1) & " ": j = Len(StrIn)
'Find how many occurences of each word there are in the document
StrIn = Replace(StrIn, StrFnd, " ")
k = (j - Len(StrIn)) / (Len(StrFnd) - 1)
'If there's more than one occurence, add the word to our Find list
If k > 1 Then
ReDim Preserve ArrOut(i)
ArrOut(i) = Trim(StrFnd)
i = i + 1
End If
Loop
WordBasic.SortArray ArrOut()
End Sub

How to work with selection

I am trying to convert perfectly working macro to hyperlink with activedoccument.range to selection.range.
code is
With Selection.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "String String1"
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
.Execute
End With
Do While .Find.Found
strtxt = Split(.Text, " ")(1)
strtxt = Right(strtxt, 2) & "/" & Left(strtxt, 4) & "/" & Mid(strtxt, 8, 2) & "/" & Mid(strtxt, 5, 3)
.Hyperlinks.Add Anchor:=.Duplicate, Address:="Address" & strtxt & "/0.pdf", TextToDisplay:=.Text
.End = .Fields(1).Result.End
.Collapse wdCollapseEnd
.Find.Execute
Loop
End With
How to collapse correctly to make this work. Currently it hyperlinks all in the doccument instead selection.
As far as I can tell, the problem is basically that the found range's end needs to be increased by 1 when the hyperlink is inserted. But I believe you also have to check that you have not gone past the original Selection.Range end, so you need an additional test.
This seemed OK in Tables, but (a) I am currently testing in Mac Word 2011, which may well be different, and (b), if you actually select a column or noncontiguous ranges, you would have to work a lot harder to make the changes only in the selection (because of well-known lack of support for such selections).
Sub fandr()
Const strText As String = "String String1"
Dim dr As Word.Range
Dim sr As Word.Range
Set sr = Selection.Range
'Debug.Print sr.Start, sr.End
Set dr = sr.Duplicate
' Try to deal with the problem where Find fails to find
' the Find text if it is exactly the same as the selection
sr.Collapse wdCollapseStart
With sr.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = strText
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
Do While .Execute(Replace:=False)
If sr.InRange(dr) Then
'Debug.Print sr.Start, sr.End, dr.Start, dr.End
strtxt = Split(.Text, " ")(1)
strtxt = Right(strtxt, 2) & "/" & Left(strtxt, 4) & "/" & Mid(strtxt, 8, 2) & "/" & Mid(strtxt, 5, 3)
sr.Hyperlinks.Add Anchor:=sr, Address:="Address" & strtxt & "/0.pdf", TextToDisplay:=.Text
sr.Collapse wdCollapseEnd
sr.End = sr.End + 1
sr.Start = sr.End
'Debug.Print sr.Start, sr.End, dr.Start, dr.End
Else
Exit Do
End If
Loop
End With
Set sr = Nothing
Set dr = Nothing
End Sub
So I have changed a few things. Somehow the Range was getting messed up after adding the HyperLink. so I just reset the SearchRange after adding the hyperlink.
This will work perfectly if the selection is not part of a Table I have added some checks to see if its in side the table but dont have time now to complete the cell shift.
Sub SearchTextAddHyperLink()
Dim SearchRange As Range
Dim OriginalRange As Range
Dim FoundRange As Range
Set SearchRange = Selection.Range
Set OriginalRange = Selection.Range
Dim strtxt As String
Dim SearchText As String
Dim CellPosition As String
SearchText = "String String1"
With SearchRange
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = SearchText
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
Do While .Find.Execute
'.Select
If .Find.Found = True Then
Set FoundRange = SearchRange
FoundRange.Select
strtxt = Split(.Text, " ")(1)
strtxt = Right(strtxt, 2) & "/" & Left(strtxt, 4) & "/" & Mid(strtxt, 8, 2) & "/" & Mid(strtxt, 5, 3)
.Hyperlinks.Add Anchor:=.Duplicate, Address:="Address" & strtxt & "/0.pdf", TextToDisplay:=.Text
If Not FoundRange.Information(wdWithInTable) Then
'Resetting the SearchRange for outside a table
'For some reason the Hyperlink messes up the Range
'Len(SearchText) + 1 just caters for the changing the Search Text
'and adding an additional character to move passed the hyperlink
SearchRange.Start = FoundRange.End + Len(SearchText) + 1
SearchRange.End = OriginalRange.End
Else
'Resetting the SearchRange for inside a table
'Need to then be clever with determinign which cell you are in and then moving to the next cell
'SearchRange.Start = FoundRange.End 'Len(SearchText) + 1
'SearchRange.End = OriginalRange.End
End If
End If
'Just to check the SearchRange
SearchRange.Select
Loop
End With
End Sub
NOTE: Also, remember to also Dim all your variables going forward.

Search for text and check for underline

How can i search for text and check the same text for underline in the word document.
Can anyone help me out??
Sub Underline()
Dim fnd As String
Dim n As Long
fnd = InputBox("Enter text to search" & vbCr & vbCr _
& "Click OK to search the entire workbook for all instances of the search text.")
Dim x As Integer
x = 0
Do While x = 0
With Selection.Find
.ClearFormatting
End With
If fnd = False Then
x = 1
Exit Do
End If
Selection.Find.Execute
If .Underline = False Then
Selection.Comments.Add Range:=Selection.Range, Text:="pls underline text"
Selection.Find.Execute
End If
Loop
End Sub
Is this what you are trying?
Sub Sample()
Dim c As Range
Dim fnd As String
fnd = InputBox("Enter text to search" & vbCr & vbCr _
& "Click OK to search the entire document for all instances of the search text.")
If fnd = "" Then Exit Sub
Set c = ActiveDocument.Content
c.Find.ClearFormatting
c.Find.Replacement.ClearFormatting
With c.Find
.Text = fnd
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
End With
c.Find.Execute
While c.Find.Found
If c.Font.Underline = wdUnderlineNone Then
c.Select
c.Comments.Add Range:=Selection.Range, Text:="pls underline text"
End If
c.Find.Execute
Wend
End Sub
comment the below line in code from Siddharth Rout
c.Comments.Add Range:=Selection.Range, Text:="pls underline text"