I have a macro with hundreds of find and replace operations formatted as, for example:
With Selection.Find
.Text = "can't"
.Font.Italic = False
.Replacement.Text = "cannot"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
I'm aware that all the .MatchCase = False etcs are unnecessary after the first time they're set to False, as Match Case will stay False until it's turned to True. My question is whether in a large macro like mine with hundreds of Replace operations and thousands of lines, will those unnecessary lines slow it down?
I just want to know if it'll make a difference before I spend ages going through and removing redundant lines.
(please don't shout at me for bad practice, the macro came together quite organically and became an official project when it was already really big)
Cheers!
The redundant lines won’t slow your operations down more than your use of Selection is already doing.
Replacing your hundreds of find and replace operations with code like this will speed things up a lot.
Sub CallingRoutine()
Application.ScreenUpdating = False
FindAndReplace "can't", "cannot"
FindAndReplace "don't", "do not"
Application.ScreenUpdating = True
End Sub
Sub FindAndReplace(findText As String, replaceText As String)
With ActiveDocument.Content.Find
.Text = findText
.Font.Italic = False
.Replacement.Text = replaceText
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = True
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll
End With
End Sub
Your question is essentially will setting a flag to its default value would significantly hinder runtime performance. In short, the answer is no.
I went ahead and performed a test for you and setting a value to a property 1 million times, and here was the result:
Setting the MatchCase property 1 million times was so insignificant that it was quicker than 1 thousandths of a second.
So don't be worried about setting values to properties, even if the value is equal to the property's default.
With all that being said, performance varies greatly depending on your hardware. My testing hardware is probably not what would be used in most scenarios, but it doesn't really change the fact that you shouldn't have concern on setting these values.
For reference, I am running:
CPU: i9-10900KF
Memory: 32GB ADATA Running XMP # 3200 MHz
MB: Asus TUF Z490 Plus
I even ran another test, setting the value to True/False a million times, and obtained the same results:
And for those who want precise numbers:
Related
There seems to be a problem when trying to get different kinds o quote characters when replacing text:
With ActiveDocument.Content.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = "\{QUOTE:(*):QUOTE\}"
.Replacement.Text = Chr(147) & "\1" & Chr(148)
.Forward = True
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
.Execute Replace:=wdReplaceAll
End With
When the document contains: {QUOTE:abc:QUOTE}
the code gives: ”abc”
but expected result is: “abc”
Versions of Word: “Microsoft Office Professional Plus 2013” and “Microsoft Office 365 ProPlus”.
The problem does not happen when File->Options->Proofing->AutoCorrect Options->AutoFormat As You Type->Replace as you type->"Straight quotes" with “smart quotes” is not activated. Of course I want the macro to work regardless of any setting for manual typing.
How can the code be changed to get the expected result?
The way to solve this kind of problem is to turn the option off for the duration of the code, then turn it back on again if it was on.
The following code snippet saves the user's setting, turns off the option, then restores the user's setting (whether or not the option was on or off).
Dim bReplaceQuotes as Boolean
'Save the user's setting
bReplaceQuotes = Options.AutoFormatAsYouTypeReplaceQuotes
Options.AutoFormatAsYouTypeReplaceQuotes = False
'Do the FindReplace
'Restore the user's settings at the end
Options.AutoFormatAsYouTypeReplaceQuotes = bReplaceQuotes
I am having to add some functionality to an existing macro for MS Word. This particular macro finds a specific text "#code_bar#" in an existing MS Word document and replaces it with a different text i.e. 3541589479.
Now, once this text is found and replaced (which the macro is already doing correctly), it is meant to change the font to "Free 3 of 9 Extended",which is already imported into Word.
This is the code, which is working properly except the part where I try to change the font and the size, which is actually not taking place. Could anyone help? Thanks.
Public Function sustituirCodigoBarras(codigo_barras)
Dim codigoDeBarras As String
Set codigoBarras = ActiveDocument.Content
'#barras_pedido# codigo de barras del pedido
codigoDeBarras = "#code_bar#"
With obj_Word.ActiveWindow.Selection.Find
.Text = codigoDeBarras
.Replacement.Text = "*" & codigo_barras & "*"
.Replacement.Font.Name = "Free 3 of 9 Regular"
.Replacement.Font.Size = 34
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll, Forward:=True, Wrap:=wdFindContinue
End With
End Function
After some extra digging and a good-night sleep here's the answer:
.Format needs to = true in order for those changes to actually take place
The font name needs to be correct. In my case I was trying to use the Free 3 of 9 Extended (which was imported into my computer) and not the Regular (which was not imported and therefore not found) as in the code above.
Rookie mistake.
Hope this can help someone else
In my new job I'm sending invoices with personalized, dated letters. Each month I go into a word doc for each client and update the date from whatever date we last send an invoice to the date we're sending the current invoice. I know basically nothing about coding, but I have managed to get something together that will search for a month and replace it with a new month. I did this by googling and piecing it together. I have no idea if its good or not, but it works.
Sub Test()
With Selection.Find
.Text = "April"
.Replacement.Text = "May"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
My question is, is there a way to search for a date like "Month DD, YYYY" and replace it with a date of my choosing? Also, it won't necessarily be the same previous date.
Thanks in advance
Actually, you don't even need VBA if you don't want to use it --- a wildcard search will do.
Open the Replace dialog, hit More (if necessary), then check Use wildcards.
In the "Find what" box, put MMMM[ ^s][0-9]{1,2},[ ^s][0-9]{4,4}, but with the actual month you want in place of MMMM. It's case-sensitive.
In the "Replace with" box, put the new date.
Hit Replace All.
Bingo! E.g., if MMMM=March, any date in March will be replaced with the new date you specify.
Explanation
[ ^s] is a space or nonbreaking space
[0-9]{1,2} is either one or two ({1,2}) digits ([0-9]).
Similarly, [0-9]{4,4} is exactly four digits.
VBA
For completeness, here it is:
Option Explicit
Option Base 0
Sub Test()
With Selection.Find
.Text = "March[ ^s][0-9]{1,2},[ ^s][0-9]{4,4}" ' ###
.Replacement.Text = "April 1, 2018"
.Forward = True
.Wrap = wdFindContinue
.Format = False
'.MatchCase = False ' ### Not relevant when using wildcards
.MatchWholeWord = False
.MatchWildcards = True ' ###
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
PS- Congratulations on starting out in VBA! Your code looks fine to me - it's pretty close to what you'd get from the macro recorder for the same operation, but cleaner. Two tips you don't need just yet :) — always use Option Explicit at the top of every module, and Dim your variables with specific types.
this is my first question,
I have to go over a large number of documents and make sure that several formatting issues are correct. An example of such an issue would be to make sure that all periods, ".", are not bold, italics, underline, etc. Another example would be to make sure that all "etc." are in italics.
I have a list of the needed formatting issues.
Instead of going over each document and using the find/replace function I would rather write a macro that I can apply to each document.
I have no experience with VBA. I do on the other hand, have some experience with programming in C sharp and C in general.
Any help would be greatly appreciated.
BTW, I'm not asking for a complete program, rather a sample from which I can learn and continue with my own.
There are a couple options:
1.Under the Developer tab in Word, you can hit the "Record Macro" button and do a find and replace multiple times while recording the macro using the ctrl + H shortcut.
2.Have multiple smaller macros setup (such as the two below) hit the "Record Macro" and run them in the order that you want.
Sub ItalicizeEct()
Selection.Find.ClearFormatting
Selection.Find.Replacement.ClearFormatting
Selection.Find.Replacement.Font.Italic = True
With Selection.Find
.Text = "ect."
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
End With
Selection.Find.Execute Replace:=wdReplaceAll
End Sub
Sub RemoveBoldPeriods()
Dim PunctAllRng As Word.Range
Set PunctAllRng = ActiveDocument.Range
With PunctAllRng.Find
.Format = True
.Text = "."
.Font.Bold = True
.Replacement.Text = "."
.Replacement.Font.Bold = False
.Execute Replace:=wdReplaceAll
End With
End Sub
3.Or simply write a large macro that will go through all the editing processes you need
In a Word 2007 macro that finds text using wildcards, how do I access the group match values?
For example, if I script a macro that searches for DATE: (<*>)^13, how would I find the value of the match group (<*>)?
Thank you,
Ben
Sub Search()
Selection.Find.ClearFormatting
With Selection.Find
.Text = "DATE: (<*>)^13"
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
End With
Selection.Find.Execute
End Sub
Good question, +1. Match groups aren't available in Word, but you can kind of hacky get around it. See the last entry on http://www.xtremevbtalk.com/archive/index.php/t-128215.html for a solution.
Doesn't look like Word's find feature can do this. However, if I use VBScript Regular Expressions, my script should be able to get match results via the return value of the vbscript.regexp object's Execute method:
http://windowsdevcenter.com/pub/a/windows/excerpt/wdhks_1/index.html?page=4