7

How do I pass an object to a private sub as a reference in Excel VBA? Below is what I am trying to do:

Sub main()
    Dim r As Range
    Set r = Sheets("Sheet1").Range(Cells(1, 1), Cells(27, 27))
    r.Select 'this works
    select_cells (r) 'this doesn't work
End Sub

Private Sub select_cells(a As Range)
    a.Select 'prompts Object Required error
End Sub
1
  • 3
    try call in front of select_cells: call select_cells (r) worked for me on a local test Commented Nov 21, 2014 at 4:37

2 Answers 2

10
select_cells (r) 'this doesn't work

You can't use parentheses to pass object parameters to a procedure. Just do this:

select_cells r

The archaic, obsolete Call keyword can be used, if you really want to keep the parentheses.

Sign up to request clarification or add additional context in comments.

3 Comments

Is there any particular reason why should avoid parentheses when passing Object as parameter?
@HowToTellAChild objects can (and a lot do!) have default properties - parentheses are forcing the evaluation of an expression, so what the procedure gets isn't the intended object but its default property. Usually that causes a type mismatch error, but things can get ugly/tricky with Variant parameters. Drop the parentheses, they're not just "for readability" - they change the meaning of your code. For non-object arguments, they're purely redundant.
If the object doesn't have a default member, then VBA fails with an error that means "I can't find that member", and execution stops.
6

There are severla errors in your code

  1. Unqualified range references refer to the ActiveSheet. So

    Set r = Sheets("Sheet1").Range(Cells(1, 1), Cells(27, 27))
    

    will error if Sheet1 is not active.

  2. r.Select will error if Sheet1 is not active.

  3. select_cells (r) with the brackets is incorrect. Use

    select_cells r
    
  4. a.Select in the Private Sub will error if Sheet1 is not active.

Here's an modified version

Sub main()
    Dim r As Range
    With Sheets("Sheet1")
        Set r = .Range(.Cells(1, 1), .Cells(27, 27))
    End With
    Debug.Print r.Address ' for diagnostic purposes
    select_cells r
End Sub

Private Sub select_cells(a As Range)
    ' Activate the worksheet first, so you can select a range on it
    a.Worksheet.Select
    a.Select
End Sub

Note on bracketed parameters

When a Sub or Function parameter is a non-object variable, bracketing the parameter overrides the ByRef/ByVal definition and passes the parameter ByVal

When a Sub or Function parameter is an object variable, bracketing the parameter causes an the default property to be passed to the Sub/Function. In the case of the OP, this is r.Value, which causes a type missmatch.

1 Comment

"passing an Object by value has no meaning" That's not really true - most events pass objects ByVal, for example. It just means you pass a copy of the pointer, not the original pointer. Using the parens forces the compiler to try and evaluate the default property of the object and pass that result-which may be an object or data type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.