VBA Range Function/Variable Object error - vba

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

Related

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!

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

Every 5 seconds record the value in 2 cells in another worksheet VBA

Problem:
I have searched extensively for this and cannot seem to get it to work. I have a timer running when the "StartBtn" is pressed:
Dim StopTimer As Boolean
Dim SchdTime As Date
Dim Etime As Date
Dim currentcost As Integer
Const OneSec As Date = 1 / 86400#
Private Sub ResetBtn_Click()
StopTimer = True
Etime = 0
[TextBox21].Value = "00:00:00"
End Sub
Private Sub StartBtn_Click()
StopTimer = False
SchdTime = Now()
[TextBox21].Value = Format(Etime, "hh:mm:ss")
Application.OnTime SchdTime + OneSec, "Sheet1.NextTick"
End Sub
Private Sub StopBtn_Click()
StopTimer = True
Beep
End Sub
Sub NextTick()
If StopTimer Then
'Don't reschedule update
Else
[TextBox21].Value = Format(Etime, "hh:mm:ss")
SchdTime = SchdTime + OneSec
Application.OnTime SchdTime, "Sheet1.NextTick"
Etime = Etime + OneSec
End If
End Sub
Then in another cell (say, C16) I have a manually entered value which is the hourly cost rate. I have a third cell that is calculating total cost by C16*current timer value.
What I want to do is record every 5 seconds after the "StartBtn" is clicked the current time and current calculated cost in another sheet. This is what I have started:
Sub increment()
Dim x As String
Dim n As Integer
Dim Recordnext As Date
n = 0
Record = [TextBox21].Value
Recordnext = [TextBox21].Value + OneSec
Range("B13").Value = Recordnext
Do Until IsEmpty(B4)
If [TextBox21].Value = Recordnext Then ActiveCell.Copy
Application.Goto(ActiveWorkbook.Sheets("Sheet2").Range("A1").Offset(1, 0))
ActiveSheet.Paste
Application.CutCopyMode = False
n = n + 1
Recordnext = [TextBox21].Value + 5 * (OneSec)
Exit Do
End If
ActiveCell.Offset(1, 0).Select
Loop
End Sub
But it doesnt work. Any help would be appreciated.
I have tried to simplify your timer method down to what is actually needed.
Sheet1 code sheet
Option Explicit
Private Sub ResetBtn_Click()
bRun_Timer = False
'use the following if you want to remove the last time cycle
TextBox21.Value = Format(0, "hh:mm:ss")
End Sub
Private Sub StartBtn_Click()
bRun_Timer = True
dTime_Start = Now
TextBox21.Value = Format(Now - dTime_Start, "hh:mm:ss")
Range("D16").ClearContents
Call next_Increment
End Sub
Module1 code sheet
Option Explicit
Public bRun_Timer As Boolean
Public Const iSecs As Integer = 3 'three seconds
Public dTime_Start As Date
Sub next_Increment()
With Worksheets("Sheet1")
.TextBox21.Value = Format(Now - dTime_Start, "hh:mm:ss")
.Range("D16") = Sheet1.Range("C16") / 3600 * _
Second(TimeValue(Sheet1.TextBox21.Value)) '# of secs × rate/sec
Worksheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Resize(1, 2).Offset(1, 0) = _
Array(.TextBox21.Value, .Range("D16").Value)
End With
If bRun_Timer Then _
Application.OnTime Now + TimeSerial(0, 0, iSecs), "next_Increment"
End Sub
Note that the operation of transferring the data to Sheet2 is a direct value transfer¹ with no .GoTo, ActiveCell or Select.
It was not entirely clear to me what you were trying to do with the value transfer. I have stacked them one after another on Sheet1.
        
You would benefit by adding Option Explicit² to the top of all your code sheets. This requires variable declaration and if you misplace a public variable, you will quickly know.
¹ See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals.
² Setting Require Variable Declaration within the VBE's Tools ► Options ► Editor property page will put the Option Explicit statement at the top of each newly created code sheet. This will avoid silly coding mistakes like misspellings as well as influencing you to use the correct variable type in the variable declaration. Variables created on-the-fly without declaration are all of the variant/object type. Using Option Explicit is widely considered 'best practice'.

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

How do you count the list of strings VBA Excel?

I'm still new to VBA Excel coding. Do tell me if there's anything that needs improvement.
In the example below I'm trying to get the list of even values from the generate class and insert into the excel vba sheet. But how do I count the number of list returned?
Private Function Generate()
Dim red(1 To 20) As String
For i = 1 To 20
red(i) = i * 2
Next i
Generate = red()
End Function
Sub Format()
Dim str() As String
str() = Generate
Range("A1").Select
With Selection
For i = 1 To str().Count 'what do I do with this? Obviously str().Count is not working.
.Offset(1, i).Value = str(i)
Next
End With
End Sub
Thank you.
Managed to solve on my own and here is the answer:
Private Function Generate()
Dim red(1 To 20) As String
For i = 1 To 20
red(i) = i * 2
Next i
Generate = red()
End Function
Sub Format()
Dim str() As String
str() = Generate
Range("A1").Select
With Selection
For i = LBound(str) To UBound(str)
.Offset(i - 1, 0).Value = str(i)
Next
End With
End Sub