Object required error when looping through cells in selection - vba

I am looping through some cells, in a vertical selection, in Excel, and then passing that cell as a parameter to a procedure.
I have done it this way, so I don't have the contents of ProcessCells twice, in the code, once for the while loop, and the second time in the For loop.
If I try and get the value of the cell written out, in the for loop, it works.
If I put the contents of the ProcessCells procedure in the for loop, it also works.
But if I try to pass it as a parameter, into ProcessCells, I am getting an error
'Object Required'
Here is the code, if you want to check it out:
Sub loopThroughCells()
Dim c As Range
Dim autoSelect As String
Dim X, Y As Integer
autoSelect = Cells(3, 2).Value
If StrComp(autoSelect, "Y") = 0 Then
Y = 5
X = 4
While Not IsEmpty(Cells(Y, X).Value)
ProcessCells (Cells(Y, X))
Y = Y + 1
Wend
Else
For Each c In Selection
ProcessCells (c)
Next c
End If
End Sub
Sub ProcessCells(ce As Range)
End Sub
How is
Cells(n,m)
different from
c In Selection
?
The error happens in the For loop, but it doesn't happen in the while loop.

Here is how you should do it:
Option Explicit
Sub TestMe()
Dim c As Range
For Each c In Selection
Call ProcessCells(c)
Next c
End Sub
Sub ProcessCells(ce As Range)
End Sub
You should refer with call, because you have an argument in parenthesis.
Or like this, if you do not like the call:
Option Explicit
Sub TestMe()
Dim c As Range
For Each c In Selection
ProcessCells c
Next c
End Sub
Sub ProcessCells(ce As Range)
End Sub
Plus a small edition of your code. Make your declarations like this:
Dim X as Long, Y As long
In your code X is declared as a variant, and integer is slower and smaller than long - Why Use Integer Instead of Long?
Here is some good explanation when to put the argument in parenthesis and when to use the call - How do I call a VBA Function into a Sub Procedure

Related

How to select multiple shapes by similar name in PowerPoint VBA?

Is there any way to select the multiples shape from slide with the same shape name.
For e.g., I have 5 shapes with the name "Textbox 60". And I want run a macro which select all the shapes from a slide named "Textbox 60". Have used the below code.
ActiveWindow.View.Slide.Shapes.Range("Textbox 60").Select
Here's one approach:
Sub Tester()
SelectByName ActivePresentation.Slides(1), "Textbox1"
End Sub
Sub SelectByName(sld As Slide, nm As String)
Dim s As Shape, first As Boolean
first = True
For Each s In sld.Shapes
If s.Name = nm Then
s.Select first 'Argument determines whether to add to
first = False ' existing selection, or replace it
End If
Next s
End Sub
You should try following #TinMan's suggestion though - that is the "better" way to go.
Activating and Selecting Objects should be avoided whenever possible. You are better of working with the Shapes using a ShapeRange.
Sub Main()
Dim ShapeRange As ShapeRange
Set ShapeRange = FindShapes(ActiveWindow.View.Slide, "Textbox 60")
If Not ShapeRange Is Nothing Then
End If
End Sub
Function FindShapes(Slide As Slide, Pattern As String) As ShapeRange
Dim Results() As Long
ReDim Results(1 To Slide.Shapes.Count)
Dim n As Long
Dim Index As Long
For Index = 1 To Slide.Shapes.Count
With Slide.Shapes(Index)
.Name = "Textbox 60"
If .Name Like Pattern Then
n = n + 1
Results(n) = Index
End If
End With
Next
If n > 0 Then
ReDim Preserve Results(1 To n)
Set FindShapes = Slide.Shapes.Range(Results)
End If
End Function
Note: I rewrote the code to handle multiple shapes with the same name.

get an error 'ByRef argument type mismatch'

I have the following code:
sub refresh()
dim result2 as string
dim m as integer
dim activeWS as worksheet
For m = 6 To 10
code = activeWS.Cells(m, 8).Value
result 2 = "lkdsjlfaksj" ;a query, I would just put a random string for now, and it would change every time based on value of m
Call GetOTCStruc(result2, m)
Next m
end sub
'then I do something on the other function, which I just eliminate the code for now
Option Explicit
Public Sub GetOTCStruc(result2 As String, m As Integer)
...
End Sub
However, it has an error highlight the part on Call GetOTCStruc(result2, m); any ideas why?
Thanks!

VBA Range Function/Variable Object error

I can't figure out why I keep getting an object error in VBA when calling a function with a desired range/variable. I want to call the SumSameCells function from a sub with the B8, B9, B10 as desired/destination cells (rng As Range)
Any help would be greatly appreciated. Thanks
Sub MySums()
Call SumSameCells(B8)
Call SumSameCells(B9)
Call SumSameCells(B10)
End Sub
Function SumSameCells(rng As Range)
x = 0
For i = 2 To 3
x = x + Sheets(i).Range(" & rng.Address & ")
Next i
Sheet1.Range(" & rng.Address & ") = x
End Function
This:
Call SumSameCells(B8)
isn't passing the Range B8 but an undeclared variable named B8
Using Option Explicit would warn you about this type of error.
This would be simpler:
Sub MySums()
SumSameCells "B8"
SumSameCells "B9"
SumSameCells "B10"
End Sub
Function SumSameCells(addr As String)
x = 0
For i = 2 To 3
x = x + Sheets(i).Range(addr).Value
Next i
Sheet1.Range(addr) = x
End Function
Variation on the already given answer.
Functions return something. You are using a return value so make it a sub.
No need for a loop in this case. You can just sum direct.
Declare the appropriate type for x. Option Explicit has already been mentioned.
Use the worksheets collection to avoid trying to work with a chart sheet.
Drop the call keyword as is obsolete.
Code:
Option Explicit
Public Sub MySums()
SumSameCells "B8"
SumSameCells "B9"
SumSameCells "B10"
End Sub
Public Sub SumSameCells(ByVal addr As String)
Dim x As Double '<== Use whatever appropriate type is
x = Application.WorksheetFunction.Sum(Worksheets(2).Range(addr), Worksheets(3).Range(addr))
Worksheets("Sheet1").Range(addr) = x
End Sub

Declare multiple variables with zero in one line

In an old macro I declare many variables in one line like
Dim Jan_Bnm, Feb_Bnm, Mar_Bnm, Apr_Bnm, Mai_Bnm, Jun_Bnm, Jul_Bnm, Aug_Bnm, Sep_Bnm, Okt_Bnm, Nov_Bnm, Dez_Bnm
With this variables I make some calculations like
Jan_Bnm = Jan_Bnm + 1
'e.g. empty = empty + 1 -> 1
Now I have the problem if the macro runs twice the old value is still stored
Jan_Bnm = Jan_Bnm + 1
'1 = 1 + 1 -> 2
So all my values are doubled.
Is it possible to set all variables by declaration to zero so that I don't have to set every (some hundreds) variable manualy?
Your current situation is the following:
Dim a As Long, b As Long, c As Long
Sub proc1()
End Sub
Sub proc2()
End Sub
The first way to avoid a, b and c still have a value when running proc1() the second time is to re-initialize them on proc1():
Sub proc1()
a = 0
b = 0
c = 0
'rest of the code
End Sub
Another way, you could pass the variables as parameters and declare them only on proc1():
Sub proc1()
Dim a As Long, b As Long, c As Long
'rest of the code
proc2 a,b,c
End Sub
Sub proc2(ByVal a As Long, ByVal b As Long, ByVal c As Long)
End Sub
Or, finally, you might think about working with a collection rather than with N variables. Example:
Dim myVars As New Collection
myVars.Add a
myVars.Add b
myVars.Add c
So now you will be able to reinitialize the variables as follows:
For j = 1 To myVars.Count
myVars(j) = 0
Next j
And what I said for the N variables (public declaration or private declaration + re-initialization) is applicable to the collection as well, but only once instead of N times (that's why I think it would simplify).

Multiple Objects In With Statement

I'm wondering why this simple code throws a "Object Required" error when I attempt to run it. I can't really find any reason why VBA would have trouble andling this. It compiles OK, but fails to run.
Sub Test()
Dim X, Y, Z As Range
Set X = Sheets(1).Range("A1")
Set Y = Sheets(2).Range("A1")
Set Z = Sheets(3).Range("A1")
With X And Y And Z
.Value = "Test" 'FAILS HERE
End With
End Sub
Im sure its something small, or maybe VBA just can't handle this?
If you do this a lot, create a helper routine:
Sub setValueOf(value As String, ParamArray ranges())
Dim i As Long
For i = 0 To UBound(ranges)
ranges(i).value = value
Next
End Sub
You can then pass 1 or more ranges;
setValueOf "Test", Sheets(1).Range("A1"), Sheets(2).Range("A1"), Sheets(3).Range("A1"), [B5], ...
VBA is trying to use the result of logical 'X AND Y AND Z' as the object in your with statement, which is probably not what you want
You need:
X.Value = "Test"
Y.Value = "Test"
Z.Value = "Test"
rather than
(X AND Y AND Z).Value = "Test"
You could set your range values using a loop instead:-
Sub Test()
Dim i
For i = 1 to 3
sheets(i).range("A1").value = "TEST"
Next
End Sub