Reputation:
My main problem is assigning a variable an manipulating it in VBA.
I know that this code works, but I'm not sure if it this is a proper way to assign a variable in VBA like I have with currentcell = Cells(i, 1).Value
Sub C()
Dim i As Integer
For i = 1 To 4
currentcell = Cells(i, 1).Value
MsgBox currentcell
Next i
End Sub
Upvotes: 1
Views: 390
Reputation: 71157
What the macro recorder and a lot of tutorials won't tell you, is that these calls are implicitly referring to the ActiveSheet
, which is obviously implicitly in the ActiveWorkbook
. When all you ever have to deal with is a single worksheet, it's probably fine, but reality is that it's never the case, and code written with implicit references to the ActiveSheet
is incredibly frail, bug-prone, and the underlying cause behind way too many Stack Overflow questions tagged with vba:
Cells
Range
Name
Rows
Columns
Whenever you use any of those, you're making calls against some global-scope Property Get
accessor that "conveniently" fetches the ActiveSheet
reference for you:
Screenshot of Rubberduck's toolbar, showing the declaration site of the selected code. Disclaimer: I manage that open-source VBIDE add-in project.
So yes, this "works", but what you'll want is to work off an explicit Worksheet
object reference instead. There are many ways to get a Worksheet
object reference, but the best one is to not care about where the worksheet is coming from, and take it as a parameter:
Sub DoSomething(ByVal ws As Worksheet)
Dim currentCell As Variant
Dim i As Integer
For i = 1 To 4
currentcell = ws.Cells(i, 1).Value
'in-cell error values can't be converted to a string:
If Not IsError(currentCell) Then MsgBox currentcell
Next i
End Sub
This takes the responsibility of knowing exactly what worksheet to work with away from the procedure, and gives it to the calling code, which can look like this:
DoSomething Sheet1 'uses the sheet's CodeName property
Or this:
DoSomething ThisWorkbook.Worksheets("Period" & n)
Or whatever. There are plenty of ways, each with their own gotchas - often you'll see something like this:
DoSomething Sheets("Sheet1") 'where "Sheet1" is in ThisWorkbook
Except Sheets
implicitly refers to the ActiveWorkbook
which may or may not be ThisWorkbook
, and the Sheets
collection could return a Chart
object, which isn't a Worksheet
. Also if "Sheet1"
is in ThisWorkbook
(the workbook with the code that's running), then referring to a worksheet by name means your code breaks as soon as the user renames the tab for that sheet.
The most robust way to refer to a worksheet that exists at compile/design-time, is by its CodeName
. Select the sheet in the Project Explorer (Ctrl+R), then bring up the Properties toolwindow (F4), and set its CodeName
by changing the (Name)
property to whatever you need: VBA defines a global-scope global object variable by that name, so you can call it MyAwesomeReport
and then refer to it as such in code:
DoSomething MyAwesomeReport
And that code will not break if the user changes the worksheet's "name".
Your code (however small that snippet might be) has other issues, notably it's using undeclared variables, which means you're not using Option Explicit
, which is another thing that will end up biting you in the rear end and come to Stack Overflow with an embarrassing question that boils down to a typo - because without Option Explicit
specified at the top of every module, VBA will happily compile a typo, making your code behave strangely instead of simply not compiling. These bugs can be excruciatingly hard to find, and they're ridiculously easy to prevent:
Use. Option. Explicit. Always.
Upvotes: 1