VBA Trouble going back and activating original workbook - vba

VBA noob. Script to search input data, match criteria, go into existing spreadsheet, copy to latest row, and then go back to original input workbook to repeat.
I can get everything working with absolute paths (ie "Book1.csv") but I will have to replace these every time I run the macro with a new input data workbook. Pretty sure I have the dim/set part figured out but every time I call the Windows().Activate I always get subscript out of range. Code:
Dim wb1 As Workbook
Set wb1 = ThisWorkbook
' Search Title column (B) for match
Cells.Find(What:="A154L-T031-#1590", After:=ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
' Select date and copy
ActiveCell.Offset(0, 1).Range("A1:Q1").Copy
' Activate and select correct sheet in NCRP spreadsheet and then select row after latest data
Windows("Approach_North.xlsx").Activate
Worksheets("T031").Activate
Range("T1048576").End(xlUp).Select
' Select row below it and paste
ActiveCell.Offset(1, 0).Range("A1").Select
ActiveSheet.Paste
' To repeat have to go back to the original data sheet
Windows(wb1).Activate
ActiveCell.Select
Selection.Font.Bold = True
The debugger lands on Windows(wb1).Activate.
Any help what doing wrong?

No need for select/activate:
Dim f As Range
Set f = Cells.Find(What:="A154L-T031-#1590", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If Not f Is Nothing Then
f.Copy Workbooks("Approach_North.xlsx").Worksheets("T031").Cells(Rows.Count, "T").End(xlUp).Offset(1, 0)
f.Bold = True
End If

Related

Searching for a string of text in a specific worksheet

Im trying to make excel search for a text string in a specific column in a specific worksheet that is not the active worksheet. VBA gives me an error that says i cannot use this method of selection. so my question is, do you have a suggestion to do it in another way?
Worksheets("Parts for renovation").Columns("Q:Q").Select
Set cell = Selection.Find(What:="Total transfer price", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If cell Is Nothing Then
Exit Sub
Else
Worksheets("Internal").Cells(29, 4) = Worksheets("Parts for Renovation").ActiveCell.Offset(0, 4)
End If
There is no need to select anything there:
With Worksheets("Parts for renovation").Columns("Q:Q")
Set cell = .Find(What:="Total transfer price", After:=.Cells(1), LookIn:=xlFormulas, _
LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
If cell Is Nothing Then
Exit Sub
Else
Worksheets("Internal").Cells(29, 4) = Cell.Offset(0, 4)
End If
End With
Your error comes, because you select a range on a non-active worksheet. This is one of the reasons, why you should be avoiding select in general.
However, if you want to make your code working (which is strongly not advisable), you may consider selecting the worksheet before selecting the range:
Worksheets("Parts for renovation").Select
Columns("Q:Q").Select
For the advisable part, try to avoid the usage of "Select" -
How to avoid using Select in Excel VBA

VBA: Pasting clipboard data into the "Find" feature

I'm an IT noob and have been tasked with creating an Excel macro that will cross-reference an employee number from one sheet to another. After finding a matching employee number it needs to copy the info from that employee (Name,etc) and finally take it to the result page and paste the info.
This is my first time making a VBA macro, or programming in general so bear with me.
Sub Macro2()
'
' Macro2 Macro
' 1st attempt
'
Dim DataObj As New MSForms.DataObject
Dim S As String
DataObj.GetFromClipboard
S = DataObj.GetText
For x = 1 To 10
Sheets("ad").Select
Cells(11 + x, 7).Select
Selection.Copy
Sheets("sp").Select
Cells.Find(What:=S, After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveCell.Offset(0, -1).Range("Table_GetJobs4[#Headers]").Select
ActiveCell.Offset(0, 1).Range("Table_GetJobs4[[#Headers],[Company_Code]]"). _
Activate
Application.CutCopyMode = False
Selection.Copy
Sheets("adtospresult").Select
ActiveCell.Offset(0, -2).Range("A1").Select
Cells.Find(What:="33620", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
ActiveCell.Offset(0 + x, -9).Range("A1").Select
ActiveSheet.Paste
ActiveCell.Offset(0, 2).Range("A1").Select
Next x
End Sub
Quite simply, I haven't been able to get the clipboard to find function to work. Any help/directions would be much appreciated, thanks.
Instead of trying to pass the clipboard information to s you could just pass the value of the range to S like this:
s = Cells(11 + x, 7).Value
and when you copy it to the other worksheet reverse it.
some_range = s
Also you don't need to select any worksheets or cells this would be completely valid:
Sheets("sp").found_range = Sheets("ad").Cells(11 + x, 7).Value
Found range would be the range in the other sheet that you want to paste the first sheet's value.
FYI, http://www.techrepublic.com/blog/software-engineer/train-users-to-follow-best-practices-when-writing-vba-code/ This would be helpful to read over to learn best practices for writing code. It'll save you in the future when you have to go back and try to decipher what you were doing in you code later down the road.

Using Worksheet CodeName and Avoiding .Select & .Activate

In my workbook I frequently need to activate some sheets by using their CodeName then search for some texts within that sheet and use the row or column number of the cell that contains the text I'm looking for.
In that situations, I am using below kind of codes:
Sheet16.Select '(Using codename)
Cells.Find(What:="FIRST TEXT I'M LOOKING FOR", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
FirstRow= ActiveCell.Row
Cells.Find(What:="SECOND TEXT I'M LOOKING FOR", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
SecondRow = ActiveCell.Row
Rows(FirstRow & ":" & SecondRow + 1).EntireRow.Hidden = False
Eveything works well, but nowadays I am trying to improve my codes and I'd like to run my codes faster.
Now,
1- How can I reference my WorkSheets' CodeName easily?
(I'm looking for answer like ThisWorkbook.Worksheets("Sheet1") - not a function
Dim wb as Workbook, ws as Worksheet
set wb = ThisWorkbook
set ws = wb.CodeName(Sheet16) or wb.Sheet16 or sheet16
'then
ws.Cells.Find(What .......... rest of the code ...... )
none of them working for CodeName property.
Fully reference a worksheet by codename or Referencing sheets in another workbook by codename using VBA didn't answer my question.
2- How can I avoid using .Activate to use the result cell of Cells.Find() formula.
Again in that example I firstly search for specific text, which is :="FIRST TEXT I'M LOOKING FOR" in the first part of my code, and then I need to use that cell to get it's row number or use offset or anything , and because of that I feel myself obligated to use .Activate because,
FirstRow = Cells.Find(What:="FIRST TEXT I'M LOOKING FOR", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Row
kind of codes do not work as well. How to avoid using Select in Excel VBA macros here in that answer there are couple of suggestions but none of them helps me in this case. I tried to get an answer from the owner of this answer to avoid any duplicate question but he suggested me to ask a new question. (And as long as both of my questions belong to my example code and I'll connect them, I asked them together in one question.)
While setting a sheet variable to the codename, the limitation is you can use the codename in ThisWorkbook only i.e. the workbook which contains the code.
Consider this code...
Dim ws As Worksheet
Set ws = wsData 'where wsData is the CodeName of a sheet.
Now in your code you can manipulate or perform actions on ws sheet without activating or selecting it.
Actually in case of CodeNames, you don't need to declare a sheet variable, you can directly refer to the sheet by using it's codename irrespective of which sheet is currently active.
like...
wsData.Cells.Clear
Set Rng = wsData.Range("A1").CurrentRegion
e.g. with your another example code
Dim ws As Worksheet
Set ws = wsData 'where wsData is the CodeName of a sheet.
FirstRow = ws.Cells.Find(What:="FIRST TEXT I'M LOOKING FOR", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Row
'Or just (without declaring the ws sheet variable where wsData is the sheet code name)
FirstRow = wsData.Cells.Find(What:="FIRST TEXT I'M LOOKING FOR", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Row

Macro search in a range of cells

Want to write a Macro that would search for a particular word in a range of cells (or after a cell), let's say "hello" in our case. Suppose my spreadsheet looks like this:
Hello user
Hello Nancy
Hello count 2
The content of the spread sheet change daily, so that I may have different number of 'Hello's everyday. I want to copy the number (2) beside the last 'Hello' to another cell. If the word count of hello doesn't exits, it will put 0 in that cell(Note that even if the word count is 0, there might still be 'hello' in this spread sheet). The location of the last Hello will always be after Cell A17.
I was thinking about setting the parameter After to cell A17, and change SearchOrder to xlByColumns, but When the search reaches the end of the search range, it wraps around to the beginning of the range.
How should I stop the search when this wraparound occurs?
I also try to use the Find method within With to search within range A17 to B22:
With Sheets("Data").Range("A17:B22")
Set hello = Cells.Find(What:="hello", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False)
End With
If Not hello Is Nothing Then
With Sheets("Data").Range("A17:B22")
Cells.Find(What:="Hello", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Offset(0, 1).Range("A1").Select
Application.CutCopyMode = False
Selection.Copy
Range("B17").Select
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
End With
Else
Range("B17").Select
ActiveCell.FormulaR1C1 = "0"
End If
But it will still locate the search to the first 'Hello' in the spreadsheet.
Try This:
Function GetLastNumber(TheRange As Range, TheWord As String) As Variant
Dim Finder
'You can add LookAt:=xlWhole if you want entire word only
Set Finder = TheRange.Find(TheWord, SearchDirection:=xlPrevious)
If Finder Is Nothing Then
GetLastNumber = CVErr(xlErrNA)
Else
'Return the value of the cell one column to the right of our search word
GetLastNumber = Finder.Offset(0, 1).Value
End If
End Function
You can use it like this:
Sub Test()
Range("D1") = GetLastNumber(Range("A1:A11"), "Hello")
End Sub
You can also use it as a formula:
=GetLastNumber(A1:A11,"Hello")
Results:

In Visual Basic for Excel 2007, how do I select rows that contain a certain pattern?

I want to write a program in Visual Basic where I look at Column L of a worksheet and search for cells in Column L that contain "123." I then want to select the rows that contain "123" in Column L, copy them, and paste them into a new worksheet. How would I do this? I created a macro, but I'm not sure how to change it so that I can find multiple items and get all of the rows for those multiple items. Here's part of what the macro gave me:
Columns("L:L").Select
Selection.Find(What:="123", After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False, SearchFormat:=False).Activate
Rows("1058:1058").Select
Selection.Copy
Sheets("123").Select
Rows("4:4").Select
range("C4").Activate
Selection.Insert Shift:=xlDown
Rows("5:5").Select
range("C5").Activate
Finds all 123s in the L column and copies the corresponding rows to Sheet2.
Tweak as needed.
Sub CopyRows()
Dim FoundRange As Range
Dim c As Range
For Each c In Application.Intersect(Columns("L"), UsedRange)
If c.Value like "*123*" Then
If FoundRange Is Nothing Then
Set FoundRange = c
Else
Set FoundRange = Application.Union(FoundRange, c)
End If
End If
Next
If Not FoundRange Is Nothing Then
FoundRange.EntireRow.Copy Worksheets("Sheet2").Range("A4")
End If
End Sub