I am working with Word Docs containing quite a lot of pages and formulas.
I have an array containing expressions
dim YellowWord(1 to 100) as string
I want to start at the beginning of the word text to look for every of those words and have a look the instances where that word or expression is followed by a number or numbers into brackets
EXMAPLE:
yellowword(2)="the blue table"
using wildcards I can find: the blue table (34, 23) in the text.
what I want is filling another array that would be:
yellowwood_reference(2) = "(34, 23)"
the code I have is so:
for i=1 to NRofYellowWords
with active document.content.find
.clearformating
.text = yellowWord(i) & " " & "\((*)\)"
with .replacement
.clearformating
.text = yellowWord(i) & "(\1)"
'HERE IS WHERE I WANT TO SAY TO WORD:
'PUT THAT PART "(\1)" INTO A VARIABLE YELLOWWORD_REFERENCE(i)
'HOWW??????
.font.color = wdcolorred
'here i changed the color of the string with the references into red.
end with
.fordward = true
.wrap = wdfindcontinue
.format = true
.matchcase = false
.matchewholeword = false
.matchwildcards = true
.matchsoundslike = false
.matchallwordforms= false
.execute replace:=wdreplaceall
end with
next i
In the above code there are several problems:
the first one I wrote it in capital letters, getting that reference of the wild card into a variable.
The second one is that there might be many appearances of the YellowWord(2) in the text, I only need/want the first reference, not the rest. That means that the first time the code finds the blue table (24,26) after passing the value "(24, 26)" into another array the code should move on and not look for more instances of the blue table in the text.
btw, i used wildcards because there might be the case that the references are simple not into brackets, so i would have to run everything twice with a different wildcard.
By the way as you can imagine, once I get the array yellowWord_reference(i) I would add the references there where there are instances of YellowWord without refferences.
I would really appreciate help since I really clicked many websites with little success.
thanks a lot
cheers
PS: If you think that there is a better way to do all that without using .find just mention it please, i am quite new in Ms-Word and coming from VBA Excel i get headaches figuring out where is the selection point.
I modified your code so that if it finds your 'words', it will capture the numbers that follow.
The code you posted would never work due to the number of compile errors ... strongly suggest you start using "Option Explicit" and posting actual code rather than typing in in yourself.
Other notes:
The numbers are enclosed in parenthesis () - not brackets []
You were using a 'ReplaceAll'; if you only wanted the first occurance, change from '...All'
I removed the 'red font' and 'Replace' ... add it back if needed.
Your code would remove the space between the word and the number - is that what you wanted?
Here's the code:
Option Explicit
Sub Find_Words()
Dim yellowWord(100) As String
Dim yellowwood_reference(100) As String
Dim NRofYellowWords As Integer
Dim i As Integer
Dim lS As Long
Dim lE As Long
Dim sFound As String
Dim rng As Range
yellowWord(1) = "blue table"
yellowWord(2) = "little"
yellowWord(3) = "big"
yellowWord(4) = "xxx last xxx"
NRofYellowWords = 4
Set rng = ActiveDocument.Range
For i = 1 To NRofYellowWords
With rng.Find
.Text = yellowWord(i) & " " & "\((*)\)"
With .Replacement
.Text = yellowWord(i) & "(\1)"
End With
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = True
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute
If .Found Then
' Find (numbers) & save
lS = InStr(rng.Start, ActiveDocument.Range.Text, "(")
If lS > 0 Then
lE = InStr(lS, ActiveDocument.Range.Text, ")")
sFound = Mid(ActiveDocument.Range.Text, lS, lE - lS + 1)
yellowwood_reference(i) = sFound
Debug.Print "Found: " & yellowWord(i) & vbTab & sFound
Else
MsgBox "Bad format; missing '('" & vbTab & Mid(ActiveDocument.Range.Text, lS, 50)
End If
Else
Debug.Print "Not Found: " & yellowWord(i)
End If
End With
Next i
Debug.Print "Finished"
End Sub
Related
I'm trying to create a macro that can flag up instances of the prefix 'pre' being used. I can create one that highlights all instances of 'pre' appearing but this then flags words like "present", "pretend" etc.
My plan to go about this was to create an array with words that I wouldn't want to be flagged (like "present") and then use an AND operation so the text equals "pre" and is NOT equal to the words I don't want flagged. My code is below, when running there is a syntax error on the .Text <> Exceptions line. Is there a better way to go about this? Thanks!
Sub NeedPrefix()
Dim range As range
Dim i As Long
Dim TargetList
Dim Exception
TargetList = Array(" pre")
Exceptions = Array("prepare", "preparation", "present", "presentation", "presented", "prepared", "pretense", "pretend")
For i = 0 To UBound(TargetList)
Set range = ActiveDocument.range
With range.Find
.Text = TargetList(i)
.Text <> Exceptions
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
Do While .Execute(Forward:=True) = True
ActiveDocument.Comments.Add range, "Is the use of a prefix appropriate?"
Loop
End With
Next
End Sub
Here's one possibility to compare a list of terms with a found Range.
Looping an array for each "hit" would be possible, although time-consuming. Instead, it's possible to compare the found Range with the list using Instr. This returns 0 if the found Range isn't present in the string.
In order for this to work, the found Range needs to be extended to encompass the entire word, so Range's end-point is extended until a space is found.
If you don't need to do anything if a term in the list is found you can, of course, leave out the Else part of the code snippet.
range.Collapse wdCollapseEnd puts the starting point for the next Find loop after the found term - otherwise the loop would repeat endlessly on the same " pre".
I've changed the variable name from range to rng - it's always a bad idea in VBA to use a reserved word (the name of an object, method or property belonging to Word or VBA) as a variable name. Notice, also, the inclusion of .Wrap = wdFindStop - this is important as otherwise the code could continue again from the start of the document.
Sub NeedPrefix()
Dim rng As Range
Dim i As Long
Dim TargetList
Dim Exceptions As String
Dim theException As String
TargetList = Array(" pre")
Exceptions = "prepare preparation present presentation presented prepared pretense pretend"
For i = 0 To UBound(TargetList)
Set rng = ActiveDocument.Content
With rng.Find
.Text = TargetList(i)
.Format = False
.Wrap = wdFindStop
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
Do While .Execute(Forward:=True) = True
Debug.Print "Characters moved: " & rng.MoveEndUntil(" " & Chr(13))
If InStr(Exceptions, rng.Text) = 0 Then
ActiveDocument.Comments.Add rng, "Is the use of a prefix appropriate?"
Else
theException = Mid(Exceptions, InStr(Exceptions, rng.Text))
theException = Mid(theException, 2)
theException = Left(theException, InStr(theException, " ") - 1)
Debug.Print "An exception was found: " & theException
End If
rng.Collapse wdCollapseEnd
Loop
End With
Next
End Sub
I am trying to replace all and then to lock only replace words, not all.
For example:
Sentence: "I am going to market"
Find: "market"
Replace: "school"
Then, lock word "school".
Dim Datas(500) As String
Dim CariKata As String
Datas(1) = "Shop"
Datas(2) = "Office"
Selection.WholeStory
Selection.Editors.Add wdEditorEveryone
For h = 1 To 2
CariKata = Datas(h)
For i = 1 To CountWordPhrase(CariKata)
Selection.find.ClearFormatting
Selection.find.Replacement.ClearFormatting
With Selection.find
.Text = CariKata
.Replacement.Text = "school"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.MatchPhrase = True
End With
Selection.find.Execute
Selection.Editors(wdEditorEveryone).Delete
Next i
ActiveDocument.Protect Password:="123", NoReset:=False, Type:= _
wdAllowOnlyReading, UseIRM:=False, EnforceStyleLock:=False
Next h
End Sub
Function CountWordPhrase(ByVal KataDicari As String)
Dim Response, ExitResponse
Dim y As Integer
On Error Resume Next
With ActiveDocument.Content.find
Do While .Execute(FindText:=KataDicari, Forward:=True, Format:=True, _
MatchWholeWord:=True) = True
' Display message in Word's Status Bar.
StatusBar = "Word is counting the occurrences of the text " & _
Chr$(34) & x & Chr$(34) & "."
y = y + 1
Loop
End With
End Function
This script successfully find and lock, but it can't find, replace, and lock.
How to find, replace, and lock?
Protecting small bits of text in Word can be tricky. With 2010 you have two basic options:
Use "Read-Only" protection. This lets you lock down the document, specifying certain areas as editable for selected people (or "Everyone"). You'll find the basic functionality in the Developer tab, Restrict Editing button, that displays the task pane. You'd select and mark the entire document as editable, then set the ranges you change as protected.
Use content controls, setting the two "Locking" checkboxes. Since I see a line with ContentControls in your code, I'm assuming you're already familiar with them, to a certain extent. The advantage of this approach is that you wouldn't need to be constantly changing the protection level on the document.
In either case, you can no longer use ReplaceAll. You'd need to put the Find in a Loop and after each "hit", do the insertion/protection step, then loop again. There are lots of code examples on the Internet for looping with Find. Search: Word Find Loop
I am attempting to write a macro which will find text based on a checklist (you will see it in the code named checklist) in the current active document. I have pasted snippets of code together to make the macro found below. My problem lies in counting. I am trying to find out how many times the macro highlights something. Later this count will be used in conjunction with categories to count the amount of highlighted objects in a certain category (hopefully!). I have to admit, I can only vaguely follow what this code is actually doing as I am new to VBA. Any help would be much appreciated. All of my attempts to get an accurate count have failed.
To add to this, does anyone know of a method of counting for multiple lists? Say, I have a few words Apple and orange which belong to the fruit list and celery and broccoli which belong to the vege list. Each time Apple (or orange) is used it adds one to the count for fruit. The same goes for vegetables. I then want to have this data exported to an excel sheet. I know it sounds complicated. I am sorry. Thanks again for any help.
Sub CompareWordList()
'This macro will find all of the words or phrases in the checklist document (to be developed) and highlight them.
'Further to this, the macro will provide a word count which is to be added to certain assessment criteria
'which will be provided by ___ once the development of this macro is complete.
Dim sCheckDoc As String
Dim docRef As Document
Dim docCurrent As Document
Dim wrdRef As Object
Dim count As Integer
sCheckDoc = "C:\Users\Nathaniel\Documents\checklist.docx"
Set docCurrent = Selection.Document
Set docRef = Documents.Open(sCheckDoc)
Set Range = ActiveDocument.Range
Application.ScreenUpdating = False
docCurrent.Activate
Options.DefaultHighlightColorIndex = wdYellow
count = 0
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
'.Replacement.Font.Bold = True
.Replacement.Highlight = True
.Replacement.Text = "^&"
.Forward = True
.Format = True
.MatchWholeWord = True
.MatchCase = False
.MatchWildcards = False
' I TRIED HERE* count = count +1
End With
For Each wrdRef In docRef.Words
If Asc(Left(wrdRef, 1)) > 32 Then
With Selection.Find
.Wrap = wdFindContinue
.Text = wrdRef
.MatchCase = False
.Execute Replace:=wdReplaceAll
End With
End If
'and here *count = count + 1
Next wrdRef
count = count + 1
If count <> 0 Then
MsgBox _
count & " item(s) highlighted "
Else
MsgBox "Nothing was not found in the document/selection matching the checklist"
End If
docRef.Close
docCurrent.Activate
Application.ScreenUpdating = True
End Sub
You can determine the number of possible replacements using RegEx. Assign the entire content of your document to a string, and then count the number of RegEx matches. Something like this would work
Sub CountReplacements() ' Make sure you add a reference to Microsoft VBScript Regular Expressions 5.5
Dim rex As New RegExp
rex.Pattern = "[0-9]" ' Change RegEx pattern to whatever works for you
rex.Global = True
Dim str As String: str = ActiveDocument.Content
Debug.Print Rex.Execute(str).Count
End Sub
I have 2 headers or markers that are a part of my RTF document. In my example I am showing a sentence when in reality it will be multiple sentences or paragraphs. I have used brackets instead of less than and greater than signs as they disappear in my question. All I want to do is replace the text between the 2 markers with the following sentence, "text goes here", without quotation marks.
[EmbeddedReport]Lots of text, thousands of character, multiple paragraphs[/EmbeddedReport]
I want replace all the text between the 2 markers replaced with "text goes here".
It would end up looking like this...
"[EmbeddedReport]text goes here[/EmbeddedReport]"
I've literally spent 2 days trying to solve this. Any help would be appreciated.
This is the last thing I tried...
Sub RemoveReport()
Dim c As Range
Dim StartWord As String, EndWord As String
Selection.HomeKey Unit:=wdStory
StartWord = "<ImageTable>"
EndWord = "</ImageTable>"
Set c = ActiveDocument.Content
c.Find.ClearFormatting
c.Find.Replacement.ClearFormatting
With c.Find
.Text = StartWord & "*" & EndWord
' MsgBox (.Text)
.Replacement.Text = "<ImageTable>text goes here</ImageTable>"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = True
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
c.Find.Execute
While c.Find.Found
Debug.Print c.Text
'~~> I am assuming that the start word and the end word will only
'~~> be in the start and end respectively and not in the middle
Debug.Print Replace(Replace(c.Text, StartWord, ""), EndWord, "")
c.Find.Execute
Wend
End Sub
Word VBA is not my area of expertise, but it seems similar to a question I answered a few days ago.
Turns out the wildcard match was not doing what I hoped it would do, or at least it was not reliable. Also, I ran in to some trouble using angle brackets, so this uses square brackets. I suspect that word treats the angle brackets as markup/syntax, and thus does not interpret them as text in the Find object. There is probably a way around this, but Word VBA is not my specialty. There is also probably a more elegant solution, but again, Word VBA is not my specialty :)
Try something like this:
Option Explicit
Sub Test()
Dim doc As Document
Dim txtRange As Range
Dim startTag As String
Dim endTag As String
Dim s As Long
Dim e As Long
startTag = "[EmbeddedReport]"
endTag = "[/EmbeddedReport]"
Set doc = ActiveDocument
Set txtRange = doc.Content
'Find the opening tag
With txtRange.Find
.Text = startTag
.Forward = True
.Execute
If .Found Then
s = txtRange.Start
Else
GoTo EarlyExit
End If
End With
'Find the closing tag
Set txtRange = doc.Range(txtRange.End, doc.Content.End)
With txtRange.Find
.Text = endTag
.Forward = True
.Execute
If .Found Then
e = txtRange.End
Else
GoTo EarlyExit
End If
End With
Set txtRange = doc.Range(s, e)
txtRange.Text = startTag & "text goes here" & endTag
Exit Sub
EarlyExit:
MsgBox "Header not found in this document!", vbInformation
End Sub
It takes some time to figure it out at first, but learning to navigate the object model reference documentation for VBA will make these tasks a lot easier to figure out in the future.
I have a word document with numerical references spread throughout the body of my text. For example "text string 1" ###:### "text string 2". Note the colon in the middle of the numberical reference. The numerical references may range from 1-999 on either side of the colon, but every reference has at least one number on each side of the colon with no more than 3 numbers on either side.
I need a routine that scans the entire document, identifies each numeral reference and then enters a carriage return BEFORE the numerical reference.... so every numerical reference would start a paragraph in the document. To illustrate this, the example above would be transformed to...
"Text string 1"
"###:###" "Text String 2"
I've tried modifying a Find/Replace operation to do this (to the point I'm going cross eyed) but can't seem to figure it out.
Any help would be greatly appreciated. Thank you!
I think using RegExp is a bit complicated here as long as there is Find-Replace feature in MS Word. Try with this code:
Sub Find_Replace_Macro()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
With Selection.Find
.Text = "([ ])([0-9]{1;3}:[0-9]{1;3})" 'solution for non-English version of MS-Word
.Text = "([ ])([0-9]{1,3}:[0-9]{1,3})" 'solution for English version of MS-Word
.Replacement.Text = "^13\2"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
You can do this with a simple Regular Expression Replace Function...
Sub TestSub()
Dim StrText
StrText = "Blajdflajdflaj 123:133 lajdflkaj123:343 alkdjflakjd 444:78 alkjdlfajkdlksjalk"
Debug.Print AddNewLine(StrText)
End Sub
Function AddNewLine(strInput)
Dim objRegEx
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.IgnoreCase = True
objRegEx.Global = True
objRegEx.Pattern = "\d{1,3}\:\d{1,3}"
'Remove one of the vbCrLf's if you only want a single New Line
AddNewLine = objRegEx.Replace(strInput, vbCrLf & vbCrLf & "$&")
End Function
The above routine will create the below output:
Blajdflajdflaj
123:133 lajdflkaj
123:343 alkdjflakjd
444:78 alkjdlfajkdlksjalk
If your working with a MS Word Document, you can test with:
StrText = ActiveDocument.Content.Text
For some extra reading on Substitutions in Regular Expressions please see:
http://msdn.microsoft.com/en-us/library/ewy2t5e0.aspx