Multiple Objects In With Statement - vba

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

Related

Factorial function returning squared number and not factorial

Where is my code wrong? It is returning the square of any number:
Sub factorial()
Dim x As Long, i As Integer, fact As Long
x = InputBox("enter the integer")
For i = 1 To x
fact = i * x
Next i
MsgBox fact
End Sub
Practicing Loops and If Statements!?
Option Explicit
' If you are practicing (loops) then:
Sub factorial()
Dim x As Long, i As Long, fct As Double
x = InputBox("enter the integer")
If x >= 0 And x <= 170 Then
fct = 1
If x > 1 Then
For i = 2 To x
fct = fct * i
Next i
End If
MsgBox fct
Else
MsgBox "Next time enter a number between 0 and 170."
Exit Sub
End If
End Sub
' ...if not, just use Fact
Sub factorialExcel()
Dim x As Long
x = InputBox("enter the integer")
If x >= 0 And x <= 170 Then
MsgBox Application.WorksheetFunction.Fact(x)
Else
MsgBox "Next time enter a number between 0 and 170."
Exit Sub
End If
End Sub
One mistake is that fact needs to be initialized with fact=1 before it is used in the loop. Then inside the loop the result is should be multiplied by the iteration number, as in fact = fact * i. Lastly to make sure you get the highest possible range use the LongLong type (available in VB7 and above) which is a 64-bit integer. Oh, and don't forget to convert the text returned by InputBox to a number type.
Sub factorial()
Dim x As Long, i As Long, fact As LongLong
x = CLng(InputBox("enter the integer"))
fact = 1
For i = 1 To x
fact = fact * i
Next i
MsgBox fact
End Sub
PS. Never use Integer in VBA, but rather opt for the native 32-bit integer Long.
In your code the value of fact is recalculated on any iteration and it is not kept. So at the end, just the last value is shown, which is x*i where i=x, e.g. a square of the input. Something like this, using 90% of your code works:
Sub Factorial()
Dim x As Long, i As Long, fact As Long
x = 5
fact = 1
For i = 1 To x
fact = fact * i
Next i
Debug.Print fact
End Sub

How can I force the Integer type to be used as a Reference type without wrapping?

I am trying to assign a variable to another variable by reference, so that changing the value of one would change the value of both, as in this pseudo-code example:
Dim x as Integer = 0
Dim y as Integer = x [byRef]
x = 1
Debug.print("x = " & x)
Debug.print("y = " & y)
'should print x = 1, y = 1
But of course, it prints x = 1, y = 0, because Integer is a Value type by default. So the question is, how can I force the y to be assigned to x by reference? I know an Object is a reference type, so I tried y = Cobj(x), but it didn't work. I want to do this without wrapping (long to explain why, but I just can't use wrapping here). Can anyone give any suggestions, please?
EDIT: I forgot to mention that I'm coding in VB.NET.
You can't make an integer type hold a reference in vb. It will always hold a value, not a reference to another object. You can, however, pass an integer variable by reference to a function or subroutine so that the function or subroutine can modify the value. Here's an example:
Sub Main()
Dim x As Integer = 0
PassByValue(x)
Debug.Print("x = " & x) 'Prints x = 0
PassByReference(x)
Debug.Print("x = " & x) 'Prints x = 2
End Sub
Sub PassByValue(x As Integer)
x = 2
End Sub
Sub PassByReference(ByRef x As Integer)
x = 2
End Sub

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

Object required error when looping through cells in selection

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