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.
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...
The objective is to count the number of comments in a range with a Function (not a sub).
I am trying to convert a Sub into a Function as I would like the range to vary and the user to enter as a formula
I have already searched the internet and got the right function. However for the sake of learning need to know why my Sub works and the Function does not
Function CommentsCounter(myRange3 As Range) As Long
'This one is mine - not working
CommentsCounter = myRange3.SpecialCells(xlCellTypeComments).Count
End Function
Sub working_just_fine()
'This one is working
Dim myRange4 As Range
Set myRange4 = Range("CO1:CO497")
Range("CO505").Value = myRange4.SpecialCells(xlCellTypeComments).Count
End Sub
Its giving the total number of cells and not the number of comments in the range
Interesting question, I tried some wonky stuff like declaring a public variable, then calling a Sub from the Function and putting the result of SpecialCells.Count into the public variable and accessing that from the Function. Surprisingly, calling the Sub from the Function led to a different result than calling the Sub separately. As a solution, this Function should do what you're trying to achieve, although it may be a bit slow on very large ranges, since it goes through every single cell in the range (I haven't done extensive testing on it yet):
Function CommentsCounter(myRange3 As Range) As Long
CommentsCounter = 0
For Each rngCell In myRange3
If Not rngCell.Comment Is Nothing Then CommentsCounter = CommentsCounter + 1
Next
End Function
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.
I have a function that finds any bold words within a specific range. This function is called in the for each loop below. The way it's currently set up it returns true if bold words exist anywhere in the range, or false if no bold words exist in the range. What I want to do is get it so it stops when it finds the bold words so I can do some other actions, then continue on down the list. I was thinking of doing something along these lines, however it throws an error on the second line
dim i as range
set i = range("C11:C6000")
for each i in range("C11:C6000")
FindBoldCharacters(Range(i)) 'throws "run time error 1004 application or object defined error" here
if i = true then
'do some stuff here'
else
end if
next i
here is the function that the piece of code is calling
Function FindBoldCharacters(ByVal aCell As Range) As Boolean
FindBoldCharacters = IsNull(aCell.Font.Bold)
If Not FindBoldCharacters Then FindBoldCharacters = aCell.Font.Bold
End Function
The function works when just called by itself, but doesn't work when I try to call it in this way. What can I do to solve this problem?
As mentioned in my comment there are a couple of things off with your code as is.
The variable i, if undeclared prior to this loop, will be dimensioned at run time as a Range object, not as a string holding the cell address as you appear to be using it as
Related, i is later being used as a Boolean when it is a Range object
Each For.. should only have one Next, your code will throw a Next without For error if you try to run it
First, declare i as a Range object, and then pass it into your function like so FindBoldCharacters(i) (this makes sense as in your function declaration you say you are expecting aCell as a Range)
Second, evaluate the function directly in the If statement
Finally, move the Next i from inside the If statement outside.
Something like this:
Option Explicit
Sub Test()
Dim i As Range
For Each i In Range("C11:C6000")
If FindBoldCharacters(i) = True Then
'do some stuff here'
Else
End If
Next i
End Sub
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.