diff --git a/skills/vba-best-practices/SKILL.md b/skills/vba-best-practices/SKILL.md index e191558..43468e2 100644 --- a/skills/vba-best-practices/SKILL.md +++ b/skills/vba-best-practices/SKILL.md @@ -29,6 +29,62 @@ description: VBA (Visual Basic for Applications) coding standards for Excel, Wo - **Use `vbNullString` instead of `""`** for empty string assignment; use `Len(s) = 0` to check emptiness — both are faster than comparing against `""`. - **Use `vb` string constants** instead of `Chr()` calls: `vbTab`, `vbLf`, `vbCr`, `vbNewLine` (fastest), `vbNullChar`. +### No Duplicate `Dim` Declarations Within a Procedure + +VBA uses **procedure-level scope** — a variable declared anywhere inside a Sub/Function is scoped to the entire procedure. Declaring the same variable name more than once (even in separate `If/Else` branches or nested loops) causes a **compile error**. + +**Rule: declare every variable exactly once, at the top of the procedure.** + +```vb +' ❌ Compile error — same name declared twice in different branches +Sub BadExample() + If condition Then + Dim x As Integer ' first declaration + x = 1 + Else + Dim x As Integer ' DUPLICATE — compiler rejects this + x = 2 + End If +End Sub + +' ✅ Correct — declared once at the top, assigned freely in any branch +Sub GoodExample() + Dim x As Integer ' single declaration + + If condition Then + x = 1 + Else + x = 2 + End If +End Sub +``` + +The same rule applies to loop variables reused across multiple `For Each` loops: + +```vb +' ❌ Compile error — rawMat declared inside two separate loops +For Each rawMat In rawMaterials ' implicit Dim inside loop + allRawMaterials.Add rawMat +Next rawMat + +For Each rawMat In allRawMaterials ' duplicate Dim — compile error + ' ... +Next rawMat + +' ✅ Correct — declare once at the top, reuse freely +Dim rawMat As Variant + +For Each rawMat In rawMaterials + allRawMaterials.Add rawMat +Next rawMat + +For Each rawMat In allRawMaterials + ' ... +Next rawMat +``` + +**Tip:** A quick way to catch duplicates is to search for `Dim ` within the same procedure. With `Option Explicit` enabled, the compiler will also surface this error on the first compile attempt. + --- ## Parameters & Scope @@ -104,6 +160,7 @@ Sheet1.Range("A1:D500").Value = arData ' one write |---|---| | `Option Explicit` in every module | Prevents undeclared-variable bugs | | Descriptive names + Hungarian prefixes | Readability & self-documentation | +| Each variable declared **once**, at procedure top | Duplicate `Dim` = compile error | | `ByVal`/`ByRef` always explicit | No silent side effects | | Custom `GoTo ErrorHandler`, not `Resume Next` | Errors surface instead of hiding | | `With…End With` for repeated object refs | Speed + clarity | @@ -111,4 +168,4 @@ Sheet1.Range("A1:D500").Value = arData ' one write | `vbNullString` / `Len()` for strings | Faster than `""` comparison | | Arrays for bulk range I/O | Orders-of-magnitude speed gain | | No `Option Base 1` or `Option Compare Text` | Predictable defaults | -| No `GoTo` except for error handler label | Structured, readable flow | +| No `GoTo` except for error handler label | Structured, readable flow | \ No newline at end of file