Disclaimer: I am actively involved in the development of Rubberduck.
Consider this common error:
lastRow = Worksheets("Sheet12").Cells(1, Rows.Count).End(xlUp).Row
Rows
is unqualified and therefore implicitly refers to the active sheet, and therefore Rows.Count
not necessarily the number of rows on "Sheet12". The code may work, but it can also lead to a subtle error, where lastRow
does not have the correct value because of this, depending on the contents of the active sheet.
Or this one:
ActiveWorkbook.Worksheets("SummarySheet") _ .ListObjects("Table1").Sort.SortFields.Add _ Key:=Range("Table1[[#All],["Date]]"), _ SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortTextAsNumbers
You see? Since the Key
parameter is not qualified, the call will fail at runtime with error 1004 - Method "Range" of object "_Global" failed. These are 169 questions . "Error 1004" gives 1465 stack overflow questions .
Implicit links to an active worksheet are a very common cause of errors.
Rubberduck VBA code checks, like ReSharper C # static code analysis, tips / suggestions. The tool tells you that there might be something here that might cause problems, or that makes the code less explicit than it could be.
Need to fully qualify every Range
challenge? Of course not - Rubberduck just lets you know that in these cases, ActiveSheet
implicitly refers to everything there is.
You can always tell Rubberduck “look, I know what I'm doing” using the “Ignore once” quick-fix:
This “fix” inserts a special comment (internally Rubberduck calls them “annotations”) that instructs the inspection to ignore specific results, leaving the check turned on:
With ActiveWorkbook Set wsMacro = .Worksheets("Macro") Set wsORatio = .Worksheets("ORatio" & TabNum) With wsORatio sMap = "oratio" & TabNum & "map" '@Ignore ImplicitActiveSheetReference For CurrentRow = 1 To Range(sMap).Rows.Count '@Ignore ImplicitActiveSheetReference Test = Range(sMap).Cells(CurrentRow, 1) Set wsData = ActiveWorkbook.Worksheets(Test) '@Ignore ImplicitActiveSheetReference Start = Range(Range(sMap).Cells(CurrentRow, 2)).Row Report = wsMacro.Range(sMap).Cells(CurrentRow, 3) For Cat = 0 To 12 For iMth = 1 To 12 wsORatio.Cells(Report + Cat, 7 + iMth) = wsData.Cells(Start + Cat, 37 + iMth) Next iMth Next Cat Next CurrentRow End With End With
These annotations have the advantage of telling the reader (the future or anyone who takes your code) that something is happening here.
Future versions will ultimately support specifying @Ignore
annotations once at the module level to ignore all the results of a particular check throughout the module.
Please note that the verification is carried out in the section "Suitability and readability". Range("DefinedName")
not half as explicit and fault tolerant as:
ActiveWorkbook.Names("DefinedName").RefersToRange
Which gives you the same range and reads how it actually pulls the named range, limited by the level of the workbook.