Hi Please help me with the below,
Sub movedata()
Call select_data(.Range("B6:B12"))
End Sub
Function select_data(C As Range)
Worksheets("sheet1").Range("I6:I16") = Worksheets("Sheet1").Range(C).Value
End Function
I can't see where I am going wrong,
Thanks,
C already is a Range object so there's no need to pass it to the Range() function (which expects a string anyway) to create it.
Change:
Worksheets("sheet1").Range("I6:I16") = Worksheets("Sheet1").Range(C).Value
To:
Worksheets("sheet1").Range("I6:I16") = C
You are confusing the range as a Range object with its Address property.
Method 1:
Sub movedata()
Call select_data(Range("B6:B12").address)
End Sub
Function select_data(C As string)
with Worksheets("sheet1")
.Range("I6:I16") = .Range(C).Value
end with
End Function
Method 2:
Sub movedata()
Call select_data(Worksheets("sheet1").Range("B6:B12"))
End Sub
Function select_data(C As range)
C.parent.Range("I6").resize(C.rows.count, C.columns.count) = C.Value
End Function
fwiw, there is going to be some difficulties stuffing B6:B12's values into I6:I16's cells. There seem to be 4 missing values.
Related
In Python, we normally pass arguements in the function when we have to call them multiple times as below:
def function_add(a,b):
print(a+b)
function_add(4,5)
function_add(5,7)
function_add(10,4)
function_add(4,6)
Do we have a similar way to implement it in VBA too? I tried to implement it but I couldn't make it. Below is my code.
Private Sub SearchAndInsertRows()
Dim rng As Range
Dim cell As Range
Dim search As String
Dim kk As String
Set rng = ActiveSheet.Columns("A:A")
search = ""
Call searchGetKey(search)
Set cell = rng.Find(What:=search, LookIn:=xlFormulas, LookAt:=xlWhole, MatchCase:=False)
If cell Is Nothing Then
MsgBox "Not Found"
Else
kk = ""
Call searchSetKey(kk)
cell.Value = kk
End If
End Sub
Sub searchGetKey(ByRef getKey As String)
getKey = "a"
End Sub
Sub searchSetKey(ByRef setKey As String)
setKey = "b"
End Sub
Sub searchGetKey and searchSetKey modifies one cell but I need to do the same for number of cells. Is there any other ways to do it?
Please fell free to optimize the code wherever necessary.
Thank you very much and much appreciated. :)
A function in VBA must return something. Otherwise, you should use a Sub:
Function function_add(a As Long, b As Long) As Long
function_add = a + b
End Function
Sub TestFunction()
MsgBox function_add(3, 5)
End Sub
You can use a function without arguments, just returning according to a specific calculation algorithm. For instance:
Function tomorrow_Date() As Date
tomorrow_Date = Date + 1
End Function
It can be called as:
Sub testTommorrow_Date()
MsgBox tomorrow_Date
End Sub
Or a Sub which by default takes arguments ByRef, if not specified ByVal:
Sub Sub_add(a As Long, b As Long, c As Long)
c = a + b
End Sub
And test it as:
Sub TestSub_Add()
Dim c As Long
Sub_add 3, 2, c
MsgBox c
End Sub
Of course, a and b may be declared in the testing Sub and used like arguments, but I wanted saying that they are not relevant against c which was updated after the call...
see the basic function structure
function test (first as range)
whatever I do inside
end function
calling the function and first is the address of the first cell, for example, B2, like this:
first=ActiveCell.address (0,0)
test (first)
calling the function results with a run time error 424 "object required"
no idea what I'm doing wrong
You just want the first cell's address? There are lots of ways to do this. Here is one.
Sub test(first As Range)
Dim r As Range
For Each r In first
Debug.Print r.Address
Exit Sub
Next
End Sub
OR as a function that returns the address:
Function GetFirstAddress(first As Range) As String
Dim r As Range
For Each r In first
GetFirstAddress = r.Address
Exit Function
Next
End Function
Another approach allowing optional external references might be:
Function GetFirstAddress(rng As Range, Optional IsQualified As Boolean = True) As String
GetFirstAddress = rng.Parent.cells(rng.Row, rng.Column).Address(external:=IsQualified)
End Function
where rng.Parent qualifies the needed worksheet reference.
I am in the middle of switching my code over from using .active and .select to something more reliable at the recommendation of the internet. I was wondering about the functionality of with statements, and if they follow into a created function.
'---Which way is more proper?
'1.
Sub TestCase()
With ThisWorkbook.Worksheets("TestWorksheet")
TestFunction()
End With
End Sub
Function TestFunction()As Integer
Dim I As Integer
I = .cells(1,1)
End function
'--2.
Sub TestCase()
With ThisWorkbook.Worksheets("TestWorksheet")
TestFunction()
End With
End Sub
Function TestFunction()As Integer
Dim I As Integer
With ThisWorkbook.Worksheets("TestWorksheet")
I = .cells(1,1)
End With
End function
Unfortunately, With statements do not follow to called functions. For that functionality, you'd need to pass an argument to the function. Here's an example that replicates your provided psuedo-code in a valid manner:
Sub TestCase()
MsgBox TestFunction(ThisWorkbook.Worksheets("TestWorksheet"))
End Sub
Function TestFunction(ByRef ws As Worksheet) As Double
With ws
TestFunction = Val(.Cells(1, 1).Value)
End With
End Function
Note that the Sub is calling the Function and passing the argument which is a worksheet object. Then in the function you can use the With statement on the passed argument.
Most proper (building on #BigBen's very correct comment):
Sub TestCase()
'Integer variable to catch the return of the function
Dim somVar as Integer
'Call the function, pass the worksheet.
somVar = TestFunction(ThisWorkbook.Worksheets("TestWorksheet"))
'Do something with the return
Debug.print somVar
End Sub
Function TestFunction(ws as Worksheet) As Integer
Dim I As Integer
I = ws.cells(1,1)
'Return the integer to the caller
TestFunction = I
End function
I´m trying to use a sub to determine a dynamic range which serves as the input to a number of functions. The simplest version of what I´m trying to do looks like this
This approach gives me errors. Putting the subs and functions in different modules doesn´t help. What´s the mistake I´m making?
Global Info As Range
Sub InfoSetter()
Worksheets("Example").Activate
ActiveSheet.UsedRange.Select
Set Info = Selection
End Sub
Function Test() As Variant
Test = Info.Address
End Function
Try the below. This calls the sub from the function that sets the value of info. This means that your info will always be the current UsedRange when the function calculates. Also, using .Activate and .Select is generally considered bad practice. The below code does the same without using either.
Global Info As Range
Sub InfoSetter()
Set Info = Worksheets("Example").UsedRange
End Sub
Function Test() As Variant
Application.Volatile 'Added so function updates automatically when sheet calculates
Call InfoSetter
Test = Info.Address
End Function
Edit: Adding Application.Volatile at the beginning of your function will make it so this updates every time the worksheet calculates.
As per the comment from omegastripes, your error is likely to be because your range is empty. Given Test is a variant suggest you test for an empty range as below
Global Info As Range
Sub TryMe()
MsgBox Test
End Sub
your code
Sub InfoSetter()
Set Info = Worksheets("Example").UsedRange
End Sub
Function Test() As Variant
If Info Is Nothing Then
Test = "Ï'm empty"
Else
Test = Info.Address
End If
End Function
I have a button someone can click. This button will create a range and pass it to another function that changes the value of that range.
Sub CommandButton21_Click()
Dim example As Range
Set example = Range("A1")
test (example)
End Sub
This function does not work. For some reason the range cannot be used by the other function.
Function test(x As Range)
x.Value = "changed"
End Function
Any help? The error says "Object required". I have tried to pass stuff like [A1] or making it a variant with no luck.
You can't "Call" a function, you Call a sub.....try this:
Sub CommandButton21_Click()
Dim example As Range
Set example = Range("A1")
MsgBox test(example)
End Sub
Function test(r As Range) As String
r.Value = "Changed"
test = "O.K."
End Function
Use Call:
Call test(example)
If you will not return any value, use Sub rather than Function.