How to manipulate clipboard string using before pasting it? - vba

I'm trying to write two VBA codes.
The first one is to add parentheses around the quotes text and remove line breaks and paragraph breaks.
The copied text always has a line break and then paragraph break near the end.
I would like to remove this, add in two double spaced, and put parentheses at the start of the text and right before where the line break was, and add a period at the end and then paste it.
An example would be:
A mandamus is the proper remedy[line break][paragraph break] Marburg v. Madison, 5 U.S. 137, 139 (1803)
Pasted To:
"A mandamus is the proper remedy." Marburg v. Madison, 5 U.S. 137, 139 (1803).
My second code would do the same thing, but flip it and add parentheses as well.
The finished product would like like:
Marburg v. Madison, 5 U.S. 137, 139 (1803) ("A mandamus is the proper remedy.").
How do I manipulate a string on the clipboard like this.
Sub Test()
Application.ScreenUpdating = False
Dim Rng As range
Set Rng = Selection.range
Rng.PasteAndFormat (wdFormatSurroundingFormattingWithEmphasis)
With Rng
.InsertBefore Chr(147)
.MoveStartUntil Chr(11), wdForward
.End = .Start + 2
.Text = Chr(148) & " "
End With
Selection.MoveStartUntil ")", wdForward
Application.ScreenUpdating = True
End Sub
For the Demoflipped, I tried
Rng.PasteAndFormat (wdFormatSurroundingFormattingWithEmphasis)

Try:
Sub DemoStraight()
Application.ScreenUpdating = False
Dim Rng As Range
Set Rng = Selection.Range
With Rng
.Paste
.Text = Chr(34) & Replace(.Text, Chr(11) & vbCr, Chr(34) & ". ")
End With
Application.ScreenUpdating = True
End Sub
and:
Sub DemoFlipped()
Application.ScreenUpdating = False
Dim Rng As Range, StrTmp As String
Set Rng = Selection.Range
With Rng
.Paste
StrTmp = Replace(.Text, Chr(11), "")
.Text = Split(StrTmp, vbCr)(1) & " (" & Chr(34) & Split(StrTmp, vbCr)(0) & Chr(34) & ".)"
End With
Application.ScreenUpdating = True
End Sub
Format retention requires a different approach. For example:
Sub DemoStraight()
Application.ScreenUpdating = False
Dim Rng As Range
Set Rng = Selection.Range
With Rng
.Paste
.InsertBefore Chr(34)
.MoveStartUntil Chr(11), wdForward
.End = .Start + 2
.Text = Chr(34) & ". "
End With
Application.ScreenUpdating = True
End Sub
and:
Sub DemoFlipped()
Application.ScreenUpdating = False
Dim RngA As Range, RngB As Range, StrTmp As String
Set RngA = Selection.Range
With RngA
.Paste
Do While .Characters.Last Like "[ " & Chr(11) & vbCr & "]"
.End = .End - 1
Loop
.InsertBefore " (" & Chr(34)
Set RngB = .Duplicate
With RngB
.MoveStartUntil Chr(11), wdForward
.End = .Start + 2
.Text = Chr(34) & ".) "
.Collapse wdCollapseEnd
.End = RngA.End
End With
.Collapse wdCollapseStart
.FormattedText = RngB.FormattedText
RngB.Text = vbNullString
End With
Application.ScreenUpdating = True
End Sub

Related

Extract the text from a Range to use as the name of a document

I have found a macro that searches for a Heading1 format and splits my Word document based on that tag.
I want to extract the text from the H1 tag and use that to name the document - I can Debug print the text but I cannot get it to convert to a string.
Im sure its really simple but I cannot get it to work.
Here is my Macro as it stands (kudos to the original author) - It currently asks for a new name for the docs and uses that, I want to replace the ans$ with a string in the naming function
``
Sub Hones()
Dim aDoc As Document
Dim bDoc As Document
Dim Rng As Range
Dim myRng As Range
Dim Rng1 As Range
Dim Rng2 As Range
Dim Counter As Long
Dim Ans$
Dim Foundtext As String
Ans$ = InputBox("Enter Filename", "Incremental number added")
If Ans$ <> "" Then
Set aDoc = ActiveDocument
Set Rng1 = aDoc.Range
Set Rng2 = Rng1.Duplicate
Do
With Rng1.Find
.ClearFormatting
.MatchWildcards = False
.Forward = True
.Format = True
.Style = "Heading 1"
.Execute
End With
If Rng1.Find.Found Then
Foundtext = Rng1.Find.Found
Debug.Print Foundtext
Counter = Counter + 1
Rng2.Start = Rng1.End + 1
With Rng2.Find
.ClearFormatting
.MatchWildcards = False
.Forward = True
.Format = True
.Style = "Heading 1"
.Execute
End With
If Rng2.Find.Found Then
Rng2.Select
Rng2.Collapse wdCollapseEnd
Rng2.MoveEnd wdParagraph, -1
Set Rng = aDoc.Range(Rng1.Start, Rng2.End)
Set bDoc = Documents.Add
bDoc.Content.FormattedText = Rng
bDoc.SaveAs Counter & ". " & Ans$ & ".docx", 16
'bDoc.SaveAs Counter & ". " & Foundtext & ".docx", wdFormatDocumentDefault
bDoc.Close
Else
'This collects from the last Heading 1 to the end of the document.
If Rng2.End < aDoc.Range.End Then
Set bDoc = Documents.Add
Rng2.Collapse wdCollapseEnd
Rng2.MoveEnd wdParagraph, -2
Set Rng = aDoc.Range(Rng2.Start, aDoc.Range.End)
bDoc.Content.FormattedText = Rng
'bDoc.SaveAs Counter & ". " & Foundtext & ".docx", wdFormatDocumentDefault
bDoc.SaveAs Counter & ". " & Ans$ & ".docx", wdFormatDocumentDefault
bDoc.Close
End If
End If
End If
Loop Until Not Rng1.Find.Found
'This is closing End If from Ans$
End If
End Sub
I believe the string contained a return at the end of it which the SaveAs function did not like
I replaced this
Foundtext = Rng1.Find.Found
Debug.Print Foundtext
with this
ftext = CStr(Rng1.Text)
namelength = Len(ftext)
Foundtext = Left(ftext, namelength - 2)
to trim the end off

How to loop through files in a folder?

I'm attempting to Loop my Dir subroutine rather than copying the code all over again.
The code prompts a user for a search word.
A count is given in the document. Black (1 time), red (2 times), or bolded red (3+ times).
Images in the file are doubled in size. If there are no images a MsgBox says "no images in file".
To modify multiple documents with this program, I need to input a directory (Dir) and then loop through the files of the directory.
Sub austinolson()
Dim WordInput As String
Dim WordCount As Integer
Dim Range As word.Range
WordInput = InputBox("Search for a word")
'Everything below this code
Set Range = ActiveDocument.Content
WordCount = 0
With Range.Find
.ClearFormatting
.Format = False
.Forward = True
.MatchWholeWord = True
.Text = WordInput
.Wrap = wdFindStop
.Execute
Do While .Found
WordCount = WordCount + 1
Range.Collapse word.WdCollapseDirection.wdCollapseEnd
.Execute
Loop
End With
MsgBox ("The word: '" & "" & WordInput & "" & "' shows up " & WordCount & " times in the document")
ActiveDocument.Content.InsertParagraphAfter
Set Range = ActiveDocument.Content
Range.Collapse word.WdCollapseDirection.wdCollapseEnd
Range.Text = "Number occurrences: " & WordCount
If WordCount >= 3 Then
Range.Font.ColorIndex = wdRed
Range.Font.Bold = True
ElseIf WordCount >= 2 Then
Range.Font.ColorIndex = wdRed
Range.Font.Bold = False
Else
Range.Font.ColorIndex = wdBlack
Range.Font.Bold = False
End If
'Inline shape count below'
Dim h As Long
Dim w As Long
Dim rng As Range
Dim Ishape As InlineShape
Set rng = ActiveDocument.Content
If rng.InlineShapes.Count = 0 Then
MsgBox "No images to modify"
End If
For Each Ishape In ActiveDocument.InlineShapes
h = Ishape.Height
w = Ishape.Width
Ishape.Height = 2 * h
Ishape.Height = 2 * w
Next Ishape
'location input:
Dim Path As String
Dim currentFilename As String
currentFilename = ""
Path = ""
Do While (Path = "")
Path = InputBox("Location of documents e.g. C:\203\: ")
If (Path = "") Then
MsgBox ("No location entered, ending program")
Exit Sub
End If
Loop
'Everything above this code:
currentFilename = Dir(Path & "*.docx")
Do While (currentFilename <> "")
MsgBox (currentFilename)
If (currentFilename <> "") Then
Documents.Open (Path & currentFilename)
'
' Need to apply loop inbetween "Above and below code" HERE to the opened word documents.
'
ActiveDocument.Close (wdSaveChanges)
End If
currentFilename = Dir
Loop
End Sub
Here's what I mean - your main Sub gets user input and loops over the files, but the other tasks are split out into discrete Subs/Functions.
Compiled, but not tested, so you may need to fix some things...
Sub MainProgram()
Dim WordInput As String
Dim WordCount As Long, ImageCount As Long
Dim doc As Document
Dim Path As String
Dim currentFilename As String
currentFilename = ""
'get a path from the user
Path = Trim(InputBox("Location of documents e.g. 'C:\203\'"))
If Path = "" Then
MsgBox "No location entered, ending program"
Exit Sub
End If
If Right(Path, 1) <> "\" Then Path = Path & "\" 'ensure trailing slash
'get the search word
WordInput = Trim(InputBox("Search for a word"))
If Len(WordInput) = 0 Then Exit Sub 'maybe add a message here...
'start looping over the folder
currentFilename = Dir(Path & "*.docx")
Do While currentFilename <> ""
Set doc = Documents.Open(Path & currentFilename)
WordCount = CountTheWord(doc, WordInput) 'count the words
TagWordCount doc, WordInput, WordCount 'insert count to doc
ImageCount = ResizeInlineShapes(doc)
Debug.Print "'" & WordInput & "' shows up " & WordCount & " times in '" & doc.Name & "'"
Debug.Print "...and there were " & ImageCount & " images resized"
doc.Close wdSaveChanges
currentFilename = Dir
Loop
End Sub
Function CountTheWord(doc As Document, theWord As String) As Long
Dim WordCount As Long, rng As Range
Set rng = doc.Content
WordCount = 0
With rng.Find
.ClearFormatting
.Format = False
.Forward = True
.MatchWholeWord = True
.Text = theWord
.Wrap = wdFindStop
.Execute
Do While .Found
WordCount = WordCount + 1
rng.Collapse wdCollapseEnd
.Execute
Loop
End With
CountTheWord = WordCount
End Function
'append a word count to the end of the document
Sub TagWordCount(doc As Document, theWord As String, theCount As Long)
Dim rng As Range
doc.Content.InsertParagraphAfter
Set rng = doc.Content
rng.Collapse wdCollapseEnd
rng.Text = "Number occurrences for '" & theWord & "': " & theCount
rng.Font.Bold = (theCount >= 3)
rng.Font.ColorIndex = IIf(theCount >= 2, wdRed, wdBlack)
End Sub
Function ResizeInlineShapes(doc As Document) As Long
Dim rv As Long, Ishape As InlineShape
For Each Ishape In doc.InlineShapes
Ishape.Height = 2 * Ishape.Height
Ishape.Height = 2 * Ishape.Height
rv = rv + 1
Next Ishape
ResizeInlineShapes = rv '<< number of shapes resized
End Function

Excel automatically add comment with cell edit history

I have the following code in the "sheet macros" (right click sheet - view code). It used to work but now it's not adding comments in my specified range A5:AQ155.
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
'If (Target.Row > 3 And Target.Row < 155) Then Cells(Target.Row, "AT") = Now()
Const sRng As String = "A5:AQ155" ' change as required
Dim sOld As String
Dim sNew As String
Dim sCmt As String
Dim iLen As Long
Dim bHasComment As Boolean
With Target(1)
If Intersect(.Cells, Range(sRng)) Is Nothing Then Exit Sub
sNew = .Text
sOld = .Text
.Value = sNew
Application.EnableEvents = True
sCmt = "Edit: " & Format$(Now, "dd Mmm YYYY hh:nn:ss") & " by " & Application.UserName & Chr(10) & "Previous Text :- " & sOld
If Target(1).Comment Is Nothing Then
.AddComment
Else
iLen = Len(.Comment.Shape.TextFrame.Characters.Text)
End If
With .Comment.Shape.TextFrame
.AutoSize = True
.Characters(Start:=iLen + 1).Insert IIf(iLen, vbLf, "") & sCmt
End With
End With
End Sub
What have I done wrong?
The code stopped firing because Event Firing was disabled and never turned back on. The way the code is written, as soon as someone makes a change to the worksheet outside the range A5:AQ155, the Events become disabled without being turned back on, which means subsequent event triggers will not be fired (ie. - the next time you edit a cell).
If you make these slight tweaks in the code it should work as intended going forward.
However, before you do this type Application.EnableEvents = True in the immediate window and hit Enter to turn events back on so that the code begins to fire again.
Private Sub Worksheet_Change(ByVal Target As Range)
Const sRng As String = "A5:AQ155" ' change as required
Dim sOld As String
Dim sNew As String
Dim sCmt As String
Dim iLen As Long
If Not Intersect(Target, Me.Range(sRng)) Is Nothing Then
Application.EnableEvents = False
With Target
sNew = .Value2
Application.Undo
sOld = .Value2
.Value2 = sNew
Application.EnableEvents = True
sCmt = "Edit: " & Format$(Now, "dd Mmm YYYY hh:nn:ss") & " by " & Application.UserName & Chr(10) & "Previous Text :- " & sOld
If .Comment Is Nothing Then
.AddComment
Else
iLen = Len(.Comment.Shape.TextFrame.Characters.Text)
End If
With .Comment.Shape.TextFrame
.AutoSize = True
.Characters(Start:=iLen + 1).Insert IIf(iLen, vbLf, "") & sCmt
End With
End With
End If
End Sub
Here is the final code that got me the desired behavior. I changed the first IF statement according to #Scott Holtzman's comment. The IF statement now resets Application.EnableEvents = True before ending the macro with End Sub
EDIT: Included "Me." in "Me.range(sRng)"
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
'If (Target.Row > 3 And Target.Row < 155) Then Cells(Target.Row, "AT") = Now()
Const sRng As String = "A5:AQ155" ' change as required
Dim sOld As String
Dim sNew As String
Dim sCmt As String
Dim iLen As Long
Dim bHasComment As Boolean
With Target(1)
If Intersect(.Cells, Me.Range(sRng)) Is Nothing Then
Application.EnableEvents = True
Exit Sub
End If
sNew = .Text
sOld = .Text
.Value = sNew
Application.EnableEvents = True
sCmt = "Edit: " & Format$(Now, "dd Mmm YYYY hh:nn:ss") & " by " & Application.UserName & Chr(10) & "Previous Text :- " & sOld
If Target(1).Comment Is Nothing Then
.AddComment
Else
iLen = Len(.Comment.Shape.TextFrame.Characters.Text)
End If
With .Comment.Shape.TextFrame
.AutoSize = True
.Characters(Start:=iLen + 1).Insert IIf(iLen, vbLf, "") & sCmt
End With
End With
End Sub
Sub Hide_Comments_in_Workbook_Completely()
'This macro hides the comments and comment indicators - users wont know there is a comment within the excel workbook
Application.DisplayCommentIndicator = xlNoIndicator
End Sub

How to convert string to range [WORD VBA]

How to convert string to temporary range so that we can get functionality of range object to work with string.
For example I am doing something like this.
Edit
I have in word table cell 2
With ActiveDocument.Range
For Each Tbl In .Tables
With Tbl
For i = 1 To .Rows.Count
With .Cell(i, 2).Range
If .Hyperlinks.Count > 0 Then
HttpReq.Open "GET", .Hyperlinks(1).Name, False
HttpReq.send
oHtml.body.innerHTML = HttpReq.responseText
StrTxt = oHtml.body.innerText
'missing lne something like set rng.Text = StrTxt
'this part is also not working, but I think I will be able to do it if I get above part working
If rng.Find.Execute(findText:="Abstract:") Then
Set Rng1 = rng( _
Start:=docnew.Paragraphs(1).Range.Start, _
End:=docnew.Paragraphs(2).Range.End)
MsgBox Rng1.Text
With Tbl.Cell(i, 3).Range
.FormattedText = Rng1.FormattedText
End With
End If
End if
Next
End with
Next
End With
This macro is not working so I can't say weather this is right or wrong to do by this mehtod. It's just an Idea.
Is it possible to dim a temp rng?
Is there any better option available to my problem?
I know that this is stub but, this is the code that worked for me.
StrTxt = oHtml.body.innerText
'MsgBox StrTxt
Set docnew = Documents.Add
With docnew
.Range.Text = StrTxt
Set drange = ActiveDocument.Range( _
Start:=ActiveDocument.Paragraphs(1).Range.Start, _
End:=ActiveDocument.Paragraphs(150).Range.End)
drange.Delete
Set Rng1 = ActiveDocument.Range
If Rng1.Find.Execute(findText:="Abstract") Then
Set rng2 = ActiveDocument.Range(Rng1.End, ActiveDocument.Range.End)
If rng2.Find.Execute(findText:=".") Then
strTheText = ActiveDocument.Range(Rng1.End, rng2.Start).Text
strTheText = Replace(strTheText, ": ", ":")
'MsgBox strTheText
End If
End If
.Close (Word.WdSaveOptions.wdDoNotSaveChanges)
End With
Set docnew = Nothing
Application.ScreenUpdating = False
End If
With Tbl.Cell(i, 3).Range
.InsertAfter vbCr & "Abstract" & strTheText & "."
End With

Automatic Excel Acronym finding and Definition adding

I regularly have to create documents at work and within the company we almost have a language of our own due to the number of acronyms and abbreviations we use. Consequently I got tired of manually creating an Acronym and abbreviation table before I could publish the document and a quick google search came across a macro that would effectively do it for me. (modified code shown below)
I modified this macro so that the table was pasted into the location of the cursor in the original document (this may not be the msot efficient way, but it was the simplest i could think of as I am not a VBA expert).
Since then I have realised that there must be a simple way to further speed up this process by automatically including the definitions as well. I have an excel spreadsheet with the Acronym in the first column and its definition in the second.
So far I have been able to get as far as opening the excel document but cannot seem to get a search which will return the row number and consequently use this to copy the contents of the definition cell next to it into the corresponding definition section of the table in Word.
** edit - extra explanation **
The current macro searches the word document and finds all the acronyms that have been used and places them in a table in a seperate word document. What i wish to do is have it also then search an excel file (pre-existing) for the definition of each of the found acronyms and add them also to the table or if they are new leave it blank. Finally the macro copies this table back into the original document.
This code currently fails saying the .Find function is not defined? (I have kept the code seperate for now to keep testing simple)
Dim objExcel As Object
Dim objWbk As Object
Dim objDoc As Document
Dim rngSearch As Range
Dim rngFound As Range
Set objDoc = ActiveDocument
Set objExcel = CreateObject("Excel.Application")
Set objWbk = objExcel.Workbooks.Open("P:\ENGINEERING\EL\Global Access\Abbreviations and Acronyms.xls")
objExcel.Visible = True
objWbk.Activate
With objExcel
With objWbk
Set rngSearch = objWbk.Range("A:A")
Set rngFound = rngSearch.Find(What:="AS345", LookIn:=xlValues, LookAt:=xlPart)
If rngFound Is Nothing Then
MsgBox "Not found"
Else
MsgBox rngFound.Row
End If
End With
End With
Err_Exit:
'clean up
Set BMRange = Nothing
Set objWbk = Nothing
objExcel.Visible = True
Set objExcel = Nothing
Set objDoc = Nothing
'MsgBox "The document has been updated"
Err_Handle:
If Err.Number = 429 Then 'excel not running; launch Excel
Set objExcel = CreateObject("Excel.Application")
Resume Next
ElseIf Err.Number <> 0 Then
MsgBox "Error " & Err.Number & ": " & Err.Description
Resume Err_Exit
End If
End Sub
Acronym extraction code
Sub ExtractACRONYMSToNewDocument()
'=========================
'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.
'=========================
'Modified in 2014 by David Mason to place the acronym table in the original document
'=========================
Dim oDoc_Source As Document
Dim oDoc_Target As Document
Dim strListSep As String
Dim strAcronym As String
Dim strDef 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:=2)
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 = "<[A-Z]{3" & strListSep & "}>"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = True
.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
'Copy the whole table, switch to the source document and past
'in the table at the original selection location
Selection.WholeStory
Selection.Copy
oDoc_Source.Activate
Selection.Paste
'make the target document active and close it down without saving
oDoc_Target.Activate
ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
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
You are just missing the Worksheet Object.
Also With objExcel can be ommited since you already pass the Workbook Object to objWbk variable.
With objWbk.Sheets("NameOfYourSheet")
Set rngSearch = .Range(.Range("A1"), .Range("A" & .Rows.Count).End(xlUp))
Set rngFound = rngSearch.Find(What:="AS345", After:=.Range("A1"), LookAt:=xlWhole)
If rngFound Is Nothing Then
MsgBox "Not found"
Else
MsgBox rngFound.Row
End If
End With
In the above code, I assumed your Excel data have headers.
Edit1: Since you are Late Binding Excel, this should work:
With objWbk.Sheets("Sheet1")
Set rngSearch = .Range(.Range("A1"), .Range("A" & .Rows.Count).End(-4162))
Set rngFound = rngSearch.Find(What:="AS345", After:=.Range("A1"), LookAt:=1)
If rngFound Is Nothing Then
MsgBox "Not found"
Else
MsgBox rngFound.Row
End If
End With
Take note that we replaced xlUp with it's equivalent constant -4162 and xlWhole with 1.
To learn more about Early and Late Binding, check THIS out.
For additional information, you can also refer HERE.
Although it is dicussed in the link I provided, you might ask where do I get the constant?
Just open Excel or any other MS application you are binding then view Immediate Window - Ctrl+G
In the immediate window, type ? then the constant you want to get the numeric equivalent.
Example:
?xlUp
-4162
?xlWhole
1
?xlPart
2
Hope this somehow solves your problem.
So it would appear with some searching I found the solution to the problem. A big thank you to L42 who helped solve the problem regarding whether i was using Early or Late binding (I had no idea these were even different).
The remaining problem where the following error occured:
Compile Error: Named Argument not found
Was suprisingly easy to solve once I found the solution... you have to love hindsight. It turns out I had to define my two variables rngFound and rngSearch as objects. As soon as i made that change the code worked beautifully.
Here is the working code which I will then incorporate into my acronym macro. (will add the total code when complete)
Sub openExcel()
Dim objExcel As Object
Dim objWbk As Object
Dim objDoc As Document
Dim rngSearch As Object
Dim rngFound As Object
Dim targetCellValue
Set objDoc = ActiveDocument
Set objExcel = CreateObject("Excel.Application")
Set objWbk = objExcel.Workbooks.Open("C:\Users\DMASON2\Documents\Book1.xlsx")
objExcel.Visible = True
objWbk.Activate
With objWbk.Sheets("Sheet1")
Set rngSearch = .Range(.Range("A1"), .Range("A" & .Rows.Count).End(-4162))
Set rngFound = rngSearch.Find(What:="AA", After:=.Range("A1"), LookAt:=1)
If rngFound Is Nothing Then
MsgBox "Not found"
Else
'MsgBox rngFound.Row
targetCellValue = .Cells(rngFound.Row, 2).Value
MsgBox (targetCellValue)
End If
End With
Err_Exit:
'clean up
Set BMRange = Nothing
Set objWbk = Nothing
objExcel.Visible = True
Set objExcel = Nothing
Set objDoc = Nothing
'MsgBox "The document has been updated"
Err_Handle:
If Err.Number = 429 Then 'excel not running; launch Excel
Set objExcel = CreateObject("Excel.Application")
Resume Next
ElseIf Err.Number <> 0 Then
MsgBox "Error " & Err.Number & ": " & Err.Description
Resume Err_Exit
End If
End Sub
** edit, complete code for searching and finding the acronyms along with their definitions **
Sub ExtractACRONYMSToNewDocument()
Dim oDoc_Source As Document
Dim oDoc_Target As Document
Dim strListSep As String
Dim strAcronym As String
Dim strDef As String
Dim oTable As Table
Dim oRange As Range
Dim n As Long
Dim m As Long
m = 0
Dim strAllFound As String
Dim Title As String
Dim Msg As String
Dim objExcel As Object
Dim objWbk As Object
Dim rngSearch As Object
Dim rngFound As Object
Dim targetCellValue As String
' message box title
Title = "Extract Acronyms to New Document"
' Set message box message
Msg = "This macro finds all Acronyms (consisting of 2 or more " & _
"uppercase letters, Numbers or '/') and their associated definitions. It " & _
"then extracts the words to a table at the current location you have selected" & vbCr & vbCr & _
"Warning - Please make sure you check the table manually after!" & vbCr & vbCr & _
"Do you want to continue?"
' Display message box
If MsgBox(Msg, vbYesNo + vbQuestion, Title) <> vbYes Then
Exit Sub
End If
' Stop the screen from updating
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 = "#"
' give the active document a variable
Set oDoc_Source = ActiveDocument
'Crete a variable for excel and open the definition workbook
Set objExcel = CreateObject("Excel.Application")
Set objWbk = objExcel.Workbooks.Open("C:\Users\Dave\Documents\Test_Definitions.xlsx")
'objExcel.Visible = True
objWbk.Activate
'Create new document to temporarily store the acronyms
Set oDoc_Target = Documents.Add
' Use the target document
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:=2)
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"
'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
End With
End With
With oDoc_Source
Set oRange = .Range
n = 1 'used to count below
' within the total range of the source document
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 = "<[A-Z][A-Z0-9/]{1" & strListSep & "}>"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = True
.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
' Find the definition from the Excel document
With objWbk.Sheets("Sheet1")
' Find the range of the cells with data in Excel doc
Set rngSearch = .Range(.Range("A1"), .Range("A" & .Rows.Count).End(-4162))
' Search in the found range for the
Set rngFound = rngSearch.Find(What:=strAcronym, After:=.Range("A1"), LookAt:=1)
' if nothing is found count the number of acronyms without definitions
If rngFound Is Nothing Then
m = m + 1
' Set the cell variable in the new table as blank
targetCellValue = ""
' If a definition is found enter it into the cell variable
Else
targetCellValue = .Cells(rngFound.Row, 2).Value
End If
End With
' enter the cell varibale into the definition cell
.Cell(n + 1, 2).Range.Text = targetCellValue
End With
' add one to the loop count
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
'Copy the whole table, switch to the source document and past
'in the table at the original selection location
Selection.WholeStory
Selection.Copy
oDoc_Source.Activate
Selection.Paste
' update screen
Application.ScreenUpdating = True
'If no acronyms found set message saying so
If n = 1 Then
Msg = "No acronyms found."
' set the final messagebox message to show the number of acronyms found and those that did not have definitions
Else
Msg = "Finished extracting " & n - 1 & " acronymn(s) to a new document. Unable to find definitions for " & m & " acronyms."
End If
' Show the finished message box
AppActivate Application.Caption
MsgBox Msg, vbOKOnly, Title
'make the target document active and close it down without saving
oDoc_Target.Activate
ActiveDocument.Close SaveChanges:=wdDoNotSaveChanges
'Close Excel after
objWbk.Close Saved = True
'Clean up
Set oRange = Nothing
Set oDoc_Source = Nothing
Set oDoc_Target = Nothing
Set oTable = Nothing
Set objExcel = Nothing
Set objWbk = Nothing
End Sub