Plain text being pasted instead of table - vba

Using some of the code on this website, I am trying to make a simple VBA that:
Finds the first table in the document
Finds "find text"
Duplicates the table where "Find text" is.
However, when I try to use the code below, it pastes the contents of the table without pasting the table itself.
Can you please help??
Sub Duplicate_Table()
Dim doc As Word.Document
Dim tbl As Word.Table
Dim rngTableTarget As Word.Range
Set doc = ActiveDocument
Set tbl = doc.Tables(1)
Set rngTableTarget = doc.Content
'Copy the table to the current selection
Selection.FormattedText = tbl.Range.FormattedText
Dim rngStory As Range
For Each rngStory In ActiveDocument.StoryRanges
With rngStory.Find
.ClearFormatting
.Text = "Find text"
.Replacement.Text = tbl.Range.FormattedText
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next rngStory
End Sub

.Replacement.Text is just a string. It cannot be used to apply formatted text.
However, you can copy the table and then use Find to replace the found text with the clipboard contents.
Sub Duplicate_Table()
Dim doc As Word.Document
Set doc = ActiveDocument
doc.Tables(1).Range.Copy
Dim rngStory As Range
For Each rngStory In ActiveDocument.StoryRanges
With rngStory.Find
.ClearFormatting
.Text = "Find text"
.Replacement.Text = "^c"
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
Next rngStory
End Sub

Related

Find And Replace with Conversion

I am trying to convert all the text "0.236" in the find object but not all the instances it finds are changing.
Some help to fix this macro would be great.
Thank you.
Sub ConvertTO6MM()
Dim wrdFind As Find
Dim wrdRng As Range
Dim wrdDoc As Document
Set wrdDoc = Application.ActiveDocument
Set wrdRng = wrdDoc.Content
Set wrdFind = wrdRng.Find
With wrdFind
.Forward = True
.MatchPhrase = True
.Wrap = wdFindContinue
.Execute FindText:="0.236"
End With
Do While wrdFind.Execute = True
wrdRng.Text = Round(0.236 * 25.4, 0) & " MM"
Loop
End Sub
You need to use the Replacement object which represents the replace criteria for a find and replace operation. The properties and methods of the Replacement object correspond to the options in the Find and Replace dialog box (Edit menu).
The Replacement object is available from the Find object. The following example replaces all occurrences of the string "0.236" with "6 MM". The selection changes when the find criteria is found because the Find object is accessed from the Selection object.
With Selection.Find
'.ClearFormatting
.Text = "0.236"
'.Replacement.ClearFormatting
.Replacement.Text = "6 MM"
.Execute Replace:=wdReplaceAll, Forward:=True, Wrap:=wdFindContinue
End With

Macro to find string in table in defined paragraph

I have MS Word document that structure is defined:
I use 3-level numbered item Heading:
5 Heading1
5.1 Heading2
5.1.1 Heading3
.
.
.
5.1.7 Heading3
in Item 5.X.7 I have table with results of my experiment
"X" can start from 1 up to approx 20
I need to search in all items "5.X.7" for tables with results.
Any idea how to select first row, first column in first table in item "5.X.7"?
Since you are new, and even though StackOverflow is not a free coding service ... try something like this to get you started.
Sub FindTables()
Dim doc As Word.Document, rng As Word.Range, hRng As Word.Range
Dim splitStr() As String, tbl As Word.Table
Set doc = ActiveDocument
Set rng = doc.Content
With rng.Find
.ClearFormatting
.Format = True
.Forward = True
.Style = doc.Styles("Heading 3").NameLocal
.Text = ""
.Wrap = wdFindStop
.Execute
Do While .found = True
splitStr = Split(rng.ListParagraphs(1).Range.ListFormat.ListString, ".")
If splitStr(0) = 5 And splitStr(2) = 7 Then
Set hRng = rng.Bookmarks("\HeadingLevel").Range
If hRng.Tables.Count > 0 Then
Set tbl = hRng.Tables(1).Range
'do something with the table
End If
rng.Collapse Word.WdCollapseDirection.wdCollapseEnd
Else
rng.Collapse Word.WdCollapseDirection.wdCollapseEnd
End If
.Execute
Loop
End With
End Sub

Finding and replacing within selection is replacing the whole document

I'm trying to iterate through all the paragraphs which are not within a table and highlighting the text as such:
'Iterate All Paragraphs
Dim p
objWord.Options.DefaultHighlightColorIndex = finalColor
For Each p In objDoc.Paragraphs
p.Range.Select
If Not objWord.Selection.Information(wdWithInTable) Then
With objWord.Selection.Range.Find
.ClearFormatting
.Highlight = False
.Forward = True
.Wrap = wdFindStop
.Replacement.ClearFormatting
.Replacement.Highlight = True
.Execute , , , , , , True, wdFindStop, , , wdReplaceAll
End With
End If
Next
The condition objWord.Selection.Information(wdWithInTable) works just fine, however the Find/Execute is replacing all non highlighted text throughout the document, even if within tables.
Any guesses as why?
I don't really think you should be using the Find object for this, but if you insist, perhaps you should store the Selection.Range in a variable first, then use the .Find property of that.
I would do it something like this:
Sub HighlightNonTableParagraphs()
Dim oDocument As Document
Dim oParagraph As Paragraph
Dim oRange As range
Set oDocument = ActiveDocument
For Each oParagraph In oDocument.Paragraphs
With oParagraph.range
If Not .Information(wdWithInTable) Then
.HighlightColorIndex = wdBlue
End If
End With
Next
End Sub

Find all text formatted with given color

I am looking for a way to create a new document containing all the text with a specific format from my document.
See below for what I wrote so far, but I'm stuck here:
how do I stop my loop when end of document is reached? or how do I add intelligence to my code to avoid a static loop, and rather do a "scan all my document"?
Option Explicit
Sub Macro1()
Dim objWord As Application
Dim objDoc As Document
Dim objSelection As Selection
Dim mArray() As String
Dim i As Long
Dim doc As Word.Document
For i = 1 To 100
ReDim Preserve mArray(i)
With Selection.Find
.ClearFormatting
.Font.Color = wdColorBlue
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = True
.Execute
End With
mArray(i) = Selection.Text
Next
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add
objWord.Visible = True
Set objSelection = objWord.Selection
For i = 1 To 100
objSelection.TypeText (mArray(i))
Next
End Sub
Thanks to Cindy's nice tip (I could also have found relevant information in Loop through Word document, starting from beginning of file at start of each loop), and in case this could help someone some day:
define the format you are looking for thanks to Word's Macro Recorder
position yourself at the beginning of your document
Use a while loop checking wdFindStop -- It also demonstrate how to use Array of String in VBA--:
...
Sub Macro2()
Dim mArray() As String
Dim i As Long, n As Long
Dim doc As Word.Document
Dim isFound As Boolean
isFound = True
i = 1
'For i = 1 To 40
Do While (isFound)
ReDim Preserve mArray(i)
With Selection.Find
.ClearFormatting
.Font.Color = wdColorBlue
.Text = ""
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindStop
.Format = True
isFound = .Execute
End With
mArray(i) = Selection.Text
i = i + 1
Loop
'Next
n = i - 2
MsgBox n & " occurrences found."
'
' create a new document with the phrases found
Dim objWord As Application
Dim objDoc As Document
Dim objSelection As Selection
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add
objWord.Visible = True
Set objSelection = objWord.Selection
For i = 1 To n 'mArray's Size
objSelection.TypeText (mArray(i))
objSelection.TypeParagraph
Next
End Sub
NB: I could also have greatly benefited from https://msdn.microsoft.com/en-us/library/office/aa211953%28v=office.11%29.aspx that explains how to find without changing the selection:
With ActiveDocument.Content.Find
.Text = "blue"
.Forward = True
.Execute
If .Found = True Then .Parent.Bold = True
End With
And from here: Find text only of style "Heading 1" (Range.Find to match style)

To delete everything except for words between a start and end point

I happen to have problems trying to manipulate the below code to my liking.
First off, the code below deletes everything in between the start and end conditions I have stipulated in my program.
I would like to change this, to delete everything besides those stipulated between the start and end words.
Sub SomeSub()
Dim StartWord As String, EndWord As String
Dim Find1stRange As Range, FindEndRange As Range
Dim DelRange As Range, DelStartRange As Range, DelEndRange As Range
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'Setting up the Ranges
Set Find1stRange = ActiveDocument.Range
Set FindEndRange = ActiveDocument.Range
Set DelRange = ActiveDocument.Range
'Set your Start and End Find words here to cleanup the script
StartWord = "From: Research.TA#traditionanalytics.com|Tradition Analytics Commentary| | |"
EndWord = "This message has been scanned for malware by Websense. www.websense.com"
'Starting the Find First Word
With Find1stRange.Find
.Text = StartWord
.Replacement.Text = ""
.Forward = True
.Wrap = wdFindAsk
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.MatchSoundsLike = False
.MatchAllWordForms = False
'Execute the Find
Do While .Execute
'If Found then do extra script
If .Found = True Then
'Setting the Found range to the DelStartRange
Set DelStartRange = Find1stRange
'Having these Selections during testing is benificial to test your script
DelStartRange.Select
'Setting the FindEndRange up for the remainder of the document form the end of the StartWord
FindEndRange.Start = DelStartRange.End
FindEndRange.End = ActiveDocument.Content.End
'Having these Selections during testing is benificial to test your script
FindEndRange.Select
'Setting the Find to look for the End Word
With FindEndRange.Find
.Text = EndWord
.Execute
'If Found then do extra script
If .Found = True Then
'Setting the Found range to the DelEndRange
Set DelEndRange = FindEndRange
'Having these Selections during testing is benificial to test your script
DelEndRange.Select
End If
End With
'Selecting the delete range
DelRange.Start = DelStartRange.Start
DelRange.End = DelEndRange.End
'Having these Selections during testing is benificial to test your script
DelRange.Select
'Remove comment to actually delete
DelRange.Delete
End If 'Ending the If Find1stRange .Found = True
Loop 'Ending the Do While .Execute Loop
End With 'Ending the Find1stRange.Find With Statement
End Sub
Hah! That's a new twist There's certainly more than one way to go about it; my inclination would be to work with (at least) three Ranges. Something like this:
Sub FindAndDeleteEverythingElse()
Dim strFind1 As String, strFind2 As String
Dim rngDoc As word.Range, rngFind1 As word.Range
Dim rngFind2 As word.Range
Dim bFound As Boolean
strFind1 = "You"
strFind2 = "directly."
Set rngDoc = ActiveDocument.content
Set rngFind1 = rngDoc.Duplicate
Set rngFind2 = rngDoc.Duplicate
With rngFind1.Find
.Text = strFind1
bFound = .Execute
End With
If bFound Then
With rngFind2.Find
.Text = strFind2
bFound = .Execute
End With
If bFound Then
rngDoc.End = rngFind1.Start
rngDoc.Delete
rngDoc.Start = rngFind2.End
rngDoc.End = ActiveDocument.content.End
rngDoc.Delete
End If
End If
End Sub
The "main" Range is that of the entire document: ActiveDocument.Content. The Range object is a bit different than other objects, if you set one Range to another it becomes that Range, not a copy. So you need the Duplicate method to make a copy of a Range. This lets you use Find independently for the various Ranges.
If the first Find is successful, the second one is executed. If that is also successful then the Document Range's end-point is set to the starting point of the successful Find and the content of the Range deleted. The Document Range is then re-defined to start at the end-point of the second found Range and end at the end of the Document, and deleted.
You will probably have to set more Range.Find properties than I did in this code snippet - I used the absolute minimum to make working with the Ranges clearer.
There maybe another way but till then you can do this.
try to add dummy character after and before your string like this
With ActiveDocument.Range
With .Find
.ClearFormatting
.Replacement.ClearFormatting
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchWildcards = False
.Text = "From: Research.TA#traditionanalytics.com|Tradition Analytics Commentary| | |"
.Replacement.Text = "From: Research.TA#traditionanalytics.com|Tradition Analytics Commentary| | |######"
.Execute Replace:=wdReplaceAll
.Text = "This message has been scanned for malware by Websense. www.websense.com"
.Replacement.Text = "######This message has been scanned for malware by Websense. www.websense.com"
.Execute Replace:=wdReplaceAll
End With
End With
End Sub
Then try to set range between ###### and ######
this is best answer to set range select a range of text from one Word document and copy into another Word document
Please note that in my word 2007 it is not possible to find within hyperlinks. Try to remove all hyperlink or within range before doing replacement.
another best answer for that: How do you remove hyperlinks from a Microsoft Word document?