With Sheets("").Range("B:B"); Variable range when searching - vba

Here´s the thing, I have a code that uses a fixed range in a fixed sheet to search for a value. I need now to make the sheet variable. I´ve tried couple of things with no luck so far.
The name of the sheet where I need to search is determined by a cell in another sheet. Replacing the 3rd line with something like: "With Sheets("Sheets("asd").range("A1")").Range("B:B") does not work.
My code:
FindString = W
If Trim(FindString) <> "" Then
With Sheets(**"CARS"**).Range("B:B")
Set Rng = Cells.Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
MsgBox "Nothing found"
End If
End With
End If
Let me know if more info is required.
Thanks!

Try omitting some of the doublequotes: With Sheets(Sheets("asd").range("A1")).Range("B:B")
Explanation
When you do this, you'll get a compile error: Expected list separator or ):
With Sheets("Sheets("asd").range("A1")").Range("B:B")
This is because the double-quotes encapsulate a string literal, so in this case the string literal is "Sheets(", which raises an error at asd (and subsequent errors, too).
The solution is to simply refer to the Sheets("asd") object, there is no need to qualify that object within quotes :)
NOTE Brad identifies another potential error in your code, see his answer below.

replace "With Sheets("Sheets("asd").range("A1")").Range("B:B")
by:
dim VAR_Sheet as string
Var_Sheet=Sheets("asd").range("A1").value
With Sheets(Var_Sheet).Range("B:B")
...code...
end with
works also like this (same result):
With Sheets(Sheets("asd").range("A1").value).Range("B:B") 'removed quotes that made error

It looks like, while you types With you are actually not using it.
With Sheets("CARS").Range("B:B")
Set Rng = Cells.Find(What:=FindString, _ <~~ Cells references the active sheet
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
MsgBox "Nothing found"
End If
End With
You need to start the statement with a dot to signify you are continuing the reference established int eh With
With Sheets("CARS").Range("B:B")
Set Rng = .Find(What:=FindString, _ <~~ .Cells
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
MsgBox "Nothing found"
End If
End With
I assume the double * was for emphasis (Sheets(**"CARS"**) --> Sheets("CARS"))

Related

VBA Do (delete column where find is true) Until Find is False then exit do

I have an excel file that has the text "Income from Trans" where I will need to delete the entire column.
This is my current code in VBA 2010 that works until there are no more cells with "Income from Trans"; I can't get it to break out of the loop.
Any idea why?
Dim rng1 As Range
Dim target1 As String
target1 = "Income From Trans"
Set rng1 = Cells.Find(What:=target1, _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
Do Until rng1 Is Nothing
Cells.Find(What:=target1, After:=ActiveCell, _
LookIn:=xlValues, LookAt:=xlPart, SearchOrder:=xlByRows,
SearchDirection _
:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.EntireColumn.Delete
Loop
Your code Set rng1 = Cells.Find... will set rng1 to be a range object, assuming it finds your value. Next is your loop which will ultimately cause rng1 to be deleted. It continues to loop because even though rng1 is deleted it still was assigned and therefore isn't Nothing. It ends with an run time error message of 91 because rng1 was set but deleted. You can see in the locals window View>Locals Window that its type is still Range\Range even though it's actually been deleted.
You have implicit cell references from the unqualified Cells usage. That means this code will run on whatever worksheet happens to be the ActiveSheet. Implicit references can have unintended side effects when you don't realize this. It's best to fully qualify them so there's no ambiguity as to which sheet they reside on. I'm assuming ActiveCell falls into this category too since you want it to wrap delete until there "Income from Trans" is no longer found.
The code .Activate followed by ActiveCell. isn't needed and can be shortened by removing both so it ends up as SearchFormat:=False).EntireColum.... Selecting a range object isn't usually necessary. Joining the two makes it apparent what you're doing.
Below you'll find a simpler version that uses .Find is in your original to find the first instance. After that it uses .FindNext() to continue looping until all are found. This eventually exits because it is setting the range variable found after every deletion, ultimately leaving found as Nothing after it's deleted the last. The RemoveColumns has parameters which allow you to use this on more than just a single sheet.
Sub Test()
RemoveColumns Sheet1, "Income From Trans"
End Sub
Sub RemoveColumns(ByVal sheetToSearch As Worksheet, ByVal value As String)
Dim found As Range
Set found = sheetToSearch.Cells.Find(What:=value, After:=sheetToSearch.Range("A1"), LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, _
MatchCase:=False)
Do Until found Is Nothing
found.EntireColumn.Delete
Set found = sheetToSearch.Cells.FindNext
Loop
End Sub
Check the search result inside the loop as well
Dim rng1 As Range, target1 As String, firstFound As String
target1 = "Income From Trans"
Set rng1 = Cells.Find(What:=target1, After:=ActiveCell, LookIn:=xlFormulas, _
LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not rng1 Is Nothing Then
Do
firstFound = rng1.Address
Set rng1 = Cells.Find(What:=target1, After:=ActiveCell, LookIn:=xlValues, _
LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
If Not rng1 Is Nothing Then rng1.EntireColumn.Delete
Loop While Not rng1 Is Nothing And rng1.Address <> firstFound
End If

How to get column number in Excel VBA using regex?

I know how to return column number using .Match, .Find and with iteration (yuck).
Is it possible to have it done more quickly using regex?
Try Debug.Print Cells(5,7).Column, it'll output 7!
Here is an example of a .Find method and it'll output the column of the found cells!
Sub test_Eswemenasja()
Dim FirstAddress As String, cF As Range, SearchedStr as String
SearchedStr = "Cat"
ActiveSheet.Range("A1").Activate
With ActiveSheet.Cells
'First, define properly the Find method
Set cF = .Find(What:=SearchedStr, _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
'If there is a result, keep looking with FindNext method
If Not cF Is Nothing Then
FirstAddress = cF.Address
Do
'Message with the column number!
MsgBox "Found in column : " & cF.column
Set cF = .FindNext(cF)
'Look until you find again the first result
Loop While Not cF Is Nothing And cF.Address <> FirstAddress
End If
End With
End Sub

Find if a value in a cell exists in another range/cell

I need a piece of code that takes the value from a cell and checks another column for that value and then returns a true/false answer or similar.
Then I will use a conditional to say something like
If "Value in cell B1" exists in Column C Then
Do nothing
Else
Msgbox "Please enter existing/valid value in B1"
End if
I simply cannot figure out how to do this. Thanks in advance for any help!
Rgards
Jim
You can use Range.Find to do this.
Dim rng as Range
Set rng = Range("C:C").Find(What:=Range("B1").Value), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If rng is nothing Then
Msgbox "Please enter existing/valid value in B1"
Else
' value of b1 found in column C
' do something else
End If
This will check whether the value of cell B1 is in any cell of column C.
The rng variable will point to the first occurence of the b1 value in column C.
More about all parameters of .find can be found at msdn: https://msdn.microsoft.com/de-de/library/office/ff839746.aspx
Something like this should work. Insert into a new module in your VBA editor, then use the custom function in a Worksheet like so:
=find_string(B1,C:C)
Function Find_String(ByVal SearchTerm As String, ByVal Rng As Range) As String
Dim FindString As String
If Trim(SearchTerm) <> "" Then
With Rng
Set Rng = .Find(What:=SearchTerm, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
'Do something!
'Examples:
Application.Goto Rng, True
Find_String = "Found in cell " + Rng.Address
Else
MsgBox "Please enter existing/valid value in B1"
Find_String = "Nothing Found"
End If
End With
End If
End Function

coding a VBA excel function to search a string in a range

I am a rookie on excel...
I am trying to create a function that takes a text string as parameter, trims it (ie removes the extra spaces at the end and at the beginning), searches for the first occurrence of the string in a range (on another spreadsheet), and returns the actual content of that cell..
I've written the code below but however I tweak it, it never returns anything!!
Any help would be much appreciated !
Note: online I've found several examples of "subs" that do similar things, but when I try to convert them to a "function", they never work...
Public Function Find_First2(FindString As String) As String
Dim Rng As Range
If Trim(FindString) <> "" Then
With Sheets("Sheet1").Range("A:A")
Set Rng = .Find(What:=FindString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Find_First2 = Rng.Value
Else
Find_First2 = ""
End If
End With
End If
End Function
You verify that trimming won't empty the whole string but you still use it as is. I changed a few things, but I don't get what this is supposed to do. You search for a string and if you find it, you return the same string? In any case, here is the code. I tested it and it works. It will look in column A of sheet Feuil1 right now. Modify to suit your needs.
Sub test()
MsgBox Find_First2("aa")
End Sub
Public Function Find_First2(FindString As String) As String
Dim Rng As Range
Dim TrimString As String
TrimString = Trim(FindString)
If TrimString <> "" Then
With Sheets("Feuil1").Range("A:A") 'This is what you need to modify
Set Rng = .Find(What:=TrimString, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
If Not Rng Is Nothing Then
Find_First2 = Rng.Value
MsgBox ("Found at: " & Rng.Address)
Else
Find_First2 = ""
End If
End With
End If
End Function

find a cell with specific text, multiple occurences, and past active cell in all cells containing specific text

I am currently working on a report, originating in Infoview (SAP business Objects)
This is a report that provides valuable information on a weekly basis, to enhance awareness of current shop performance.
Like the tile of the post might show i want to find a cell with specific text. It has multiple occurrences, and I want to past a previously selected cell in all of those instances.
I can reach the same result by Ctrl-F, "Search all" ( for the "specific text") and than Paste (the previously selected cell)
( http://www.extendoffice.com/documents/excel/816-excel-select-cells-with-specific-text.html)
But i would like to automate this.
I want to use:
Cells.Find(What:="[ö]", After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
and
Cells.FindNext(After:=ActiveCell).Activate
But I can't incorporate the two in one macro that gives me the result i describes above.
The previously selected cell contains a formula, containing index(match) and a reference to a cell on the same row as the "specific text".
In my opinion this way of doing stuff saves me a lot of trouble with dynamic cell references ect.
I hope you can help
Your request is a little vague, but I believe this will get you started
Dim PasteValue as string 'this is what you're pasting in
Dim WS as Worksheet
Dim FirstCell as string
Dim rng as range
PasteValue = 'do something here to get your value
set rng = Cells.Find(What:="[ö]", LookIn:=xlFormulas, LookAt:= xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
while not rng is nothing 'make sure you found something
if len(FirstCell) = 0 then
firstcell = rng.address 'save this spot off so we don't keep looping
end if
rng.value = PasteValue
'now find the next one
set rng = Cells.Find(What:="[ö]", LookIn:=xlFormulas, LookAt:= xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
if rng.address = FirstCell then 'back at the first cell
set rng = nothing 'so get out of the loop
endif
end while
Thanks for the code above, it helped a lot.
This is the final code, in case anyone needs it. The
If rng Is Nothing Then Exit Do
Loop While rng.Address <> strFirstAddress
is particulary usefull.
Sub Fill_VCNC()
Dim formula_ö As String
Dim rng As Range
Dim strFirstAddress As String
With Range("S:S")
Set rng = Cells.Find(What:="[ö]", LookIn:=xlValues, LookAt:=xlPart, _
SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, _
SearchFormat:=False)
If Not rng Is Nothing Then
strFirstAddress = rng.Address
Do
rng.formula = formula_ö
.NumberFormat = "0.00"
Set rng = .FindNext(rng)
If rng Is Nothing Then Exit Do
Loop While rng.Address <> strFirstAddress
End If
End With
End Sub
( source : https://social.msdn.microsoft.com/Forums/en-US/958fca4e-b19d-4b50-8235-e05adc7f25d5/loop-through-a-range-until-value-not-found?forum=exceldev)