Problems passing parameters between subs - vba

I have my main sub as per below:
Option Explicit
Public y As String
Public xCell As Range
Sub BenAppMr()
Call SearchFor("Award")
Call ConvertToLetter(xCell)
MsgBox "The column letter is " & y
End Sub
and then my two other subs which I call from above:
Sub SearchFor(z As String)
xCell = Cells.Find(What:=z, After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False)
End Sub
and
Sub ConvertToLetter(x As Range)
y = Split(x.Address(1, 0), "$")(0)
End Sub
Am I missing something here? I can't quite understand why this won't work.
I'm looking to search of "Award" in my excel sheet and convert the column number to a letter. I'm looking to pass these parameters as I'll be calling a few searches and a few conversions in my main sub (once it's working)
It's been a long time since I used this kind of set up, normally I just call procedures without passing a parameter but it would be a lot cleaner this way.
Any help would be much appreciated.

Using Sub's to set Global variables is not a good coding pattern - you would be much better off using functions to return the values directly to the calling code:
Sub BenAppMr()
Dim y As String, xCell As Range
Set xCell = SearchFor("Award")
If Not xCell Is Nothing Then
y = ConvertToLetter(xCell)
MsgBox "The column letter is " & y
Else
MsgBox "Search value not found!"
End If
End Sub
Function SearchFor(z As String) As Range
Dim xCell As Range
Set xCell = ActiveSheet.Cells.Find(What:=z, After:=ActiveCell, LookIn:= _
xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:= _
xlNext, MatchCase:=False, SearchFormat:=False)
Set SearchFor = xCell
End Function
Function ConvertToLetter(x As Range) As String
ConvertToLetter = Split(x.Address(1, 0), "$")(0)
End Function
...and use Set for object-type variables as Rory pointed out.

Related

Transfer macro to UDF

I want the macro below transferred to a UDF but I do not know how.
I want a udf where I select the Findstring and return it in the cell where is place the udf.
Can someone help me?
Sub Find_pipe()
Dim Findstring As String
Dim Location As String
Dim Rng As Range
Sub Find_First()
Dim Findstring As String
Dim Rng As Range
Findstring = InputBox("vul naam van leiding in")
If Trim(Findstring) <> "" Then
With Sheets("scenario 1V2").Range("A1:BP150")
Set Rng = .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.Offset(1), True
Application.Goto ThisWorkbook.Worksheets("D en L berekening").Range("A1"), True
ThisWorkbook.Worksheets("D en L berekening").Range("U10").Value = Rng.Offset(1).Value
Else
MsgBox "Nothing found"
End If
End With
End If
End Sub
Try this:
Function FindPipe(Findstring As String)
Application.Volatile 'You need this if your UDF needs to update after changes in
' the search range
Dim f As Range
If Trim(Findstring) <> "" Then
With ThisWorkbook.Sheets("scenario 1V2").Range("A1:BP150")
Set f = .Find(What:=Findstring, _
After:=.Cells(.Cells.Count), _
LookIn:=xlValues, _
LookAt:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False)
End With
If Not f Is Nothing Then
FindPipe = f.Offset(1).Value
Else
FindPipe = "Not found"
End If
Else
FindPipe = ""
End If
End Function
Note the range to be searched is hard-coded in the UDF, so Excel doesn't know to recalculate your UDF if the search range is updated. I added Application.Volatile to take care of that but it may slow your workbook if you have a lot of formulas pointing to that UDF.

VBA, goto cell with a certain value (type: date)

I have code as follow:
Sub Find_First()
Dim FindString As String
Dim Rng As Range
FindString = Range("A1")
If Trim(FindString) <> "" Then
With Sheets("Kalendarz").Range("A5:LY5")
Set Rng = .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
End Sub
but it doesn't work with date format, any suggestion?
More details: In A1 cell I will enter a date, In 5. row I have a list of every day in 2016. I want to (after run macro) go to cell with date from cell A1.
Using the Find function to locate a date is notoriously tricky in Excel VBA. The function relies on your search date being formatted in the same way as Excel's default setting. In addition, you need to ensure that the search string is converted to a date within the Find function, using CDate. Ozgrid has a good article on it: http://www.ozgrid.com/VBA/find-dates.htm
I have amended your code below to accommodate those requirements and added an extra With Sheets... statement to ensure the FindString uses the Range from your target sheet.
However, because of the unpredictability of users' adjusting date formats, I prefer a VBA loop, using Value2 which is Excel's numerical representation of the date, so cannot be fiddled with. The Ozgrid article prefers not to use VBA loops when a Find function is so much faster, but I guess it's a matter of personal preference and I feel a bespoke loop is more reliable.
Up to you which one you want to go with.
The Find method:
Sub Find_First()
Dim FindString As String
Dim Rng As Range
With Sheets("Kalendarz")
FindString = .Range("A1")
If Trim(FindString) <> "" Then
With .Range("A5:LY5")
Set Rng = .Find(What:=CDate(FindString), _
After:=.Cells(1), _
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
End With
End Sub
The VBA loop method:
Sub Find_First_VBA_Loop()
Dim dateVal As Long
Dim cell As Range
With Sheets("Kalendarz")
dateVal = .Range("A1").Value2
For Each cell In .Range("A5:LY5").Cells
If dateVal = cell.Value2 Then
Application.Goto cell, True
Exit For
End If
Next
End With
End Sub

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

How to make the "what" ARG in find read data from a cell

I am trying to fill a table with Input boxes with respect to date.
I am using the find and offset function to determine location through VBA but I want the "WHAT" to find to be dependent on date I put in a cell.
See my code below.
Public userMsg As String, Rng As Range
Private Sub Button1_Click()
Dim Data_Cell As Variant
userMsg = InputBox("How many brews were mashed?", "No of brews", "Enter your value here", 500, 700)
Data_Cell = Range("B2").Value
Set Rng = Sheet2.Range("A3:A34").Find(What:=Data_Cell, LookIn:=xlValues, LookAt:=xlWhole, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
If Not Rng Is Nothing Then
MsgBox "Captured"
Rng.Offset(0, 1) = userMsg
End If
End Sub
I found my problem, my source cell was a list from data validation, i used active x controls to do my list and it worked.

Excel VBA highlight entire column according to today's date

I have the following data in my excel table. My requirements is to highlight the the entire column of my current date.
I have found a code where it search through my dates and select the today's date. However when i try to move to another cell to input some data, it keeps on going back to the selected date and i was unable to do key in. Below is my code.
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim TodaysDate As Date
Dim Rng As Range
TodaysDate = CLng(Date)
With Rows("1:1")
Set Rng = .Find(what:=TodaysDate, _
after:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
lookat:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not Rng Is Nothing Then
Application.Goto Rng, True
Else
'Give a message that today's date was not found
MsgBox "Nothing found"
End If
End With`
The above code doesn't include the highlighting part yet since i have no idea how to do it since i just learn to do VBA since yesterday.
Any help will be appreciated.
To use VBA:
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim TodaysDate As Date
Dim Rng As Range
TodaysDate = CLng(Date)
With Rows("1:1")
Set Rng = .Find(what:=TodaysDate, _
after:=.Cells(.Cells.Count), _
LookIn:=xlFormulas, _
lookat:=xlWhole, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False)
If Not Rng Is Nothing Then
Rng.EntireColumn.Interior.Color = vbMagenta
Else
'Give a message that today's date was not found
MsgBox "Nothing found"
End If
End With
End Sub
You can skip the whole VBA and use conditional formatting. See screenshot: