Replace string and rest of line with other string - vba

So here's what I want to do:
I have a string origStr, which is at the beginning of a line in a Word document. After origStr is an unknown value (e.g. 23 or 2,6)
I want to find that string and replace the value after with another known value, but keep the string.
Example in my Word document:
Diam. diastole, mm: 53
[Running VBA makro where user input is 54,3]
Expected Result:
Diam. diastole, mm: 54,3
Actual result:
Diam. diastole, mm: 54,3 53
So here's what i got:
origStr = LArray(i, j - 1).Caption & ": *"
replStr = LArray(i, j - 1).Caption & ": " & TBArray(i, j).Text
With ActiveDocument.Content.Find
.MatchWildcards = True
.ClearFormatting
.Text = origStr
.Replacement.ClearFormatting
.Replacement.Text = replStr
.Execute Replace:=wdReplaceAll, Forward:=True, Wrap:=wdFindStop
End With
Why isn't my old value being deleted?
Thanks in advance!

Word uses "lazy" pattern matching which is good in this case because otherwise it would just replace the rest of your entire document. Vincent G gave a solution for one word (no more than one space in the rest of the line), here is something more general:
To get Word to replace everything until the end of the line, you need to include the end of the line into the search string. ^l or ^11 is the control code for new line (shift+enter), ^12 is page or section break, ^13 is carriage return.
This is the most "recent" list I found.
So "yourtext*^11" would match everything from "yourtext" until the next new line and so on.
Depending on your formatting, it could be either one of the above so you have to be careful. If you replace "*^12" but your lines end with new line, you will replace the whole paragraph.
To catch all of them, you can group them: yourtext*[^11^12^13] will match everything until the next new line or carriage return. However if we replace that, the end of the line will be replaced as well so we have to include it in the replacement text. How do we know what it was?
We can use () to define a submatch and \1, \2 etc to use these submatches in the replacement text:
origStr = LArray(i, j - 1).Caption & ": *([^11^12^13])"
replStr = LArray(i, j - 1).Caption & ": " & TBArray(i, j).Text & "\1"
Example:
before:
after replacing with origStr = "yourtext*([^11^12^13])" and replStr = "yourtext newtext\1":
Note: These expressions also work with the Find and Replace dialog, just make sure "Use Wildcards" is enabled

Its not really a VBA problem, the same happening in "Find and Replace" dialog.
Replace your original string with:
origStr = LArray(i, j - 1).Caption & ": <*>"

Related

Infinite loop on the currency symbol alt key code 0164

In my sript I use
If Selection.Text Like "* [aAwWzZiIoOuUVQ] *"
but if script check a table falls into infinite loop on the currency symbol alt key code 0164.
I use MsgBox Selection.Text and loops on such a line (and similar with marks 0164):
MsgBox show:
How to skip checking such a line in the table, go further in the code or exit the For Next loop.
Something like:
If Selection.Text = ChrW(164) Then
[EDIT]
Ok my fault.
This is 7 lines not 1.
And selected text is not ChrW(164) but NOTHING.
I try If Selection.Text = "" Then
or
If Selection.Text = ChrW(0) Then
but loop not stop.
[EDIT2]
Dim NumLines As Long
Selection.EndKey Unit:=wdStory, Extend:=wdExtend
NumLines = Selection.Range.ComputeStatistics(wdStatisticLines)
MsgBox "Lines to check " & (NumLines) & " If you want STOP: Press CTRL+Pause Break"
Selection.Collaps
For i = 1 To NumLines...
Now I understand where the mistake is.
The macro did not loop indefinitely, even though it seemed to. It didn't hang on any particular character, it simply counted each table cell as a separate line and took that value as the final digit of the loop counter.

Find and Replace every instances of string with Wildcards

I would like to find and replace a certain pattern in word using VBA. More specifically I would like to find every instance of "Table" followed by a whitespace followed by one or more digits followed by another whitespace and replace it with "Table", the same number, a period and a tab. I tried using the Find and Replace function of VBA with the "MatchWildcard" property set to true. Finding the pattern has been no problem, however I can't figure out how to replace the text, so that the number stays the same. My idea was to use the same wildcard in the replacement string, but in this case it just spells out the wildcard as text. Therefore my question is whether there is any way to use the matched value in the replacement string.
toFind = "Table [1-9]# " & vbTab
Dim replacementStr As String
replacementString = "Table [1-9]#." & vbTab
myRange.Find.Execute FindText:=toFind, replaceWith:=replacementStr, _
Replace:=wdReplaceAll, MatchWildcards:=True
Should produce: "Table 1 " -> "Table 1. "
Does produce: "Table 1 " -> "Table [1-9]#. "
For further detail on using wildcards see: https://wordmvp.com/FAQs/General/UsingWildcards.htm
toFind = "(Table [1-9])# " & vbTab
Dim replacementStr As String
replacementStr = "\1." & vbTab
myRange.Find.Execute FindText:=toFind, replaceWith:=replacementStr, _
Replace:=wdReplaceAll, MatchWildcards:=True

Replace and add at end of the line

I need to replace some starting text with another one and add at the end another text. This is a starting example:
- This is a phrase that match
Another - Phrase
Yes another - one
- This also match
The result i want to have is:
$This is a phrase that match%
Another - Phrase
Yes another - one
$This also match%
So replace "- " with "$" (only if is the first two character of the sentence) and add at the end of the line, if match, "%"
I have search and the the replace function work but i don't know how to add the end of line:
With Selection.Find
.ClearFormatting
.Text = "- "
.Replacement.Text = "$"
.Execute Replace:=wdReplaceAll, Forward:=True, Wrap:=wdFindContinue
End With
I have see there is a InsetAfter method but it create a new line, or i have wrong implemented. Suggestions? Thanks
You don't even need a macro for this! All you need is a wildcard Find/Replace, where:
Find = ^13- ([!^13]#)^13
Replace = ^p$\1%^p

Finding and Replacing with VBA for Word overwrites previous style

I'm writing a VBA script to generate word documents from an already defined template. In it, I need to be able to write headings along with a body for each heading. As a small example, I have a word document that contains only <PLACEHOLDER>. For each heading and body I need to write, I use the find-and-replace feature in VBA to find <PLACEHOLDER> and replace it with the heading name, a newline, and then <PLACEHOLDER> again. This is repeated until each heading name and body is written and then the final <PLACEHOLDER> is replaced with a newline.
The text replacing works fine, but the style I specify gets overwritten by the next call to the replacement. This results in everything I just replaced having the style of whatever my last call to my replacement function is.
VBA code (run main)
Option Explicit
Sub replace_stuff(search_string As String, replace_string As String, style As Integer)
With ActiveDocument.Range.Find
.Text = search_string
.Replacement.Text = replace_string
.Replacement.style = style
.Forward = True
.Wrap = wdFindContinue
.Format = True
.MatchWholeWord = False
.MatchSoundsLike = False
.MatchAllWordForms = False
.Execute Replace:=wdReplaceAll
End With
End Sub
Sub main()
Dim section_names(2) As String
section_names(0) = "Introduction"
section_names(1) = "Background"
section_names(2) = "Conclusion"
Dim section_bodies(2) As String
section_bodies(0) = "This is the body text for the introduction! Fetched from some file."
section_bodies(1) = "And Background... I have no issue fetching data from the files."
section_bodies(2) = "And for the conclusion... But I want the styles to 'stick'!"
Dim i As Integer
For i = 0 To 2
' Writes each section name as wsStyleHeading2, and then the section body as wdStyleNormal
Call replace_stuff("<PLACEHOLDER>", section_names(i) & Chr(11) & "<PLACEHOLDER>", wdStyleHeading2)
Call replace_stuff("<PLACEHOLDER>", section_bodies(i) & Chr(11) & "<PLACEHOLDER>", wdStyleNormal)
Next i
Call replace_stuff("<PLACEHOLDER>", Chr(11), wdStyleNormal)
End Sub
Input document: A word document with only <PLACEHOLDER> in it.
<PLACEHOLDER>
Expected Output:
I expect that each heading will be displayed in the style I specified and can be viewed from the navigation pane like this:
Actual Output: However what I actually get is everything as wdStyleNormal style like this:
I think the problem can be solved by inserting a paragraph break between every style transition, but when I try using vbCrLF or Chr(10) & Chr(13) or vbNewLine instead of the chr(11) I am using now, Each line begins with a boxed question mark like this:
Update from discussion in comments on another answer. The problem described below applies to Word 2016 and earlier. Starting in Office 365 (and probably Word 2019, but that's not been confirmed) the Replace behavior has been changed to "convert" ANSI 13 to a "real" paragraph mark, so the problem in the question would not occur.
Answer
The reason for the odd formatting behavior is the use of Chr(11), which inserts a new line (Shift + Enter) instead of a new paragraph. So a paragraph style applied to any part of this text formats the entire text with the same style.
In this particular case (working with Replace), vbCr or the equivalent Chr(13) also don't work because these are not really Word's native paragraph. A paragraph is much more than just ANSI code 13 - it contains paragraph formatting information. So, while the code is running, Word is not really recognizing these as true paragraph marks and the paragraph style assignment is being applied to "everything".
What does work is to use the string ^p, which in Word's Find/Replace is the "alias" for a complete paragraph mark. So, for example:
replace_stuff "<PLACEHOLDER>", section_names(i) & "^p" & "<PLACEHOLDER>", wdStyleHeading2
replace_stuff "<PLACEHOLDER>", section_bodies(i) & "^p" & "<PLACEHOLDER>", wdStyleNormal
There is, however, a more efficient way to build a document than inserting a placeholder for each new item and using Find/Replace to replace the placeholder with the document content. The more conventional approach is to work with a Range object (think of it like an invisible selection)...
Assign content to the Range, format it, collapse (like pressing right-arrow for a selection) and repeat. Here's an example that returns the same result as the (corrected) code in the question:
Sub main()
Dim rng As Range
Set rng = ActiveDocument.content
Dim section_names(2) As String
section_names(0) = "Introduction"
section_names(1) = "Background"
section_names(2) = "Conclusion"
Dim section_bodies(2) As String
section_bodies(0) = "This is the body text for the introduction! Fetched from some file."
section_bodies(1) = "And Background... I have no issue fetching data from the files."
section_bodies(2) = "And for the conclusion... But I want the styles to 'stick'!"
Dim i As Integer
For i = 0 To 2
BuildParagraph section_names(i), wdStyleHeading2, rng
BuildParagraph section_bodies(i), wdStyleNormal, rng
Next i
End Sub
Sub BuildParagraph(para_text As String, para_style As Long, rng As Range)
rng.Text = para_text
rng.style = para_style
rng.InsertParagraphAfter
rng.Collapse wdCollapseEnd
End Sub
The problem is caused by your use of Chr(11) which is a manual line break. This results in all of the text being in a single paragraph. When the paragraph style is applied it applies to the entire paragraph.
Replace Chr(11) with vbCr to ensure that each piece of text is in a separate paragraph.

Remove paragraph mark from string

I have a macro that finds all of the 'Heading 1' styles within my document and lists them in a ComboBox on a UserForm.
My problem is that the Find routine I am using is also selecting the paragraph mark (ΒΆ) after the text I wish to copy, and that is being displayed in the ComboBox.
How can I remove this from the string? I've tried useing replace(), replacing vbCrLf, vbCr, vbLf, vbNewLine, ^p, v, Chr(244) and Asc(244) with "", but nothing has succeeeded. For example -
sanitizedText = Replace(Selection.Text, "^v", "")
Can anyone please help with this problem? Thanks.
Here is how my form looks -
You should use ChrW$() for unicode characters:
sanitizedText = Replace(Selection.Text, ChrW$(244), "")
Or, if the paragraph mark is always at the end maybe you can just remove the last character using
myString = Left(myString, Len(myString) - 1)
I used sanitizedText = Replace(Selection.Text, Chr(13), "") successfully; 13 is the ASCII value for 'carriage return'.
This tiny script replaces, in a piece of text selected in the document (i.e. marked using the cursor) hyphens that are at the beginning of a line. It replaces them by an improvised bullet point: (o)
The script searches for occurances of "Paragraph mark followed by hyphen".
I had a similar problem as in the question above, as I was sure paragraph marks should be 'Chr(13) & Chr(10)', which is equal 'VbCrLF', which is equal 'Carriage Return, Line Feed'. However, 'Chr(13) & Chr(10)' were wrong. The naked Chr(13) did the job.
Sub MakeAppFormListPoints()
'Replace list hyphens by (o)
Dim myRange As Range
Set myRange = Selection.Range 'What has been marked with the cursor
Debug.Print myRange ' Just for monitoring what it does
myRange = replace(myRange, Chr(13) & "-", Chr(13) & "(o)")
Debug.Print myRange ' Just for monitoring what it does
End Sub
(I use this for adjusting text written in Word to the insanely restricted character set of the official application form for the European Union Erasmus+ programme to promote lifelong learning activities. Well, I learned something.)