9

The colon operator : is a statement delimiter in VBA.

However, does anyone has a clue why the first three examples work and the fourth (when uncommented) produces an error?

Option Explicit

Public Sub TestMe()

    If 1 = 1 Then: Debug.Print 1

    If 2 = 2 Then Debug.Print 2

    If 3 = 3 Then:
        Debug.Print 3

'   Gives error:
'    If 4 = 4 Then
'        Debug.Print 4

'Other Examples, from the comments and the answers:

::::::::::::::::::::::::::::         '<-- This seems to be ok

    If 5 = 5 Then Debug.Print "5a"::: Debug.Print "5b"
    If 6 = 0 Then Debug.Print "6a"::: Debug.Print "6b"

    If 7 = 0 Then:
        Debug.Print 7 ' Does not have anything to do with the condition...

    If 8 = 0 Then Debug.Print "8a"::: Debug.Print "8b" Else Debug.Print "8c"

End Sub
Community
  • 1
  • 1
Vityata
  • 42,633
  • 8
  • 55
  • 100
  • 1
    You have no "End If" after the last line. Else put ":" after "Then" on your last code If 4 = 4 Then: – pokemon_Man Feb 01 '17 at 15:07
  • @pokemon_Man, yeah, but number 3 works pretty good without any `End If` – Vityata Feb 01 '17 at 15:09
  • number 3 has a colon and number 4 do not. Put a colon after "Then" on number 4 – pokemon_Man Feb 01 '17 at 15:09
  • Then it should be exactly like number 3. And I want to write it on 2 lines. – Vityata Feb 01 '17 at 15:10
  • 2
    then you'll need to add an End If – RyanL Feb 01 '17 at 15:12
  • In my humble knowledge, `:` is used to put multiple commands on the same line as the VBA compiler will be a bit more performant having less lines to read. So it don't see the point of 3 and 4... Then you could use `_` to change line, but it's the same issue... – R3uK Feb 01 '17 at 15:13
  • 3
    The `:` straight after the `Then` is basically ignored, other to force it into being a single line `If`. `Debug.Print 3` is executed whether the previous statement is `If 3 = 3 Then` or `If 3 = 15 Then`. – YowE3K Feb 01 '17 at 15:22
  • 1
    When `python` programmer does `vba` you get the last (commented) statement – John Alexiou Feb 01 '17 at 15:38
  • @ja72 - I knew it reminds me something :) – Vityata Feb 01 '17 at 23:26

2 Answers2

13

I think the confusion comes from 3. We'd think that 3 and 4 should behave the same. In fact, 3 is equivalent to this:

If 3 = 3 Then: (do nothing) 'an empty statement
   Debug.Print 3 ' <-- This will be executed regardless of the previous If condition

To see it, change 3 into this:

If 3 = 0 Then:
    Debug.Print 3 '<-- 3 will be printed! ;)

In conclusion, yes, the : is indeed to merge many statements on a single line

Good job @Vityata !!! :)

A.S.H
  • 29,101
  • 5
  • 23
  • 50
3

If Then Blocks require a matching End If when they are multi-line.

The first case is fine because the command after Then is on the same line.

The second case is fine for the same reason, the : makes no difference in this situation.

The third case works because when the IF statement evaluates to True, there is no command following the ':'. The : signals to compiler that the next command should be seen as being on the same line. There is nothing following, so processing moves to the next line which is seen as outside the If Then Block.

The fourth case has no notation to tell the compiler that the If Then command is single line, and therefore it is looking for the End IF to the block.

Option Explicit

Public Sub TestMe()

  If 1 = 1 Then: Debug.Print 1 '<-- All on a single line - OK

  If 2 = 2 Then Debug.Print 2  '<-- All on a single line - OK

  If 3 = 3 Then:               '<-- No command following :
    Debug.Print 3              '<-- Seen as outside the If Then Block

'   Gives error:
'    If 4 = 4 Then
'        Debug.Print 4
'    End IF                   '<-- Required to show the end of the If Then block
End Sub
Rdster
  • 1,846
  • 1
  • 16
  • 30
  • `The first one is fine because the command after Then is on the same line.` - but we have a statement deliminator, it should be treated as if it goes on another line. – Vityata Feb 01 '17 at 15:13
  • 3
    @Vityata - No, with the `:` and then the command it is still a single line `If`, just like `If 5 = 5 Then Debug.Print 5: Debug.Print 5: Debug.Print 5` – YowE3K Feb 01 '17 at 15:15
  • @YowE3K - I would have expected an error in case 1 and 3. – Vityata Feb 01 '17 at 15:20
  • 3
    Case 3 works because when the `If` is evaluated to `True` there are no statements to execute (other than the dummy statements preceding / following the `:`). – YowE3K Feb 01 '17 at 15:21
  • @YowE3K Really? That's kinda cool actually. I'll update to reflect that. – Rdster Feb 01 '17 at 15:30
  • 3
    @Vityata - I'd suggest you use an example of `If 5 = 5 Then Debug.Print 5::: Debug.Print 5` except that it would make it too obvious what the answer is - that a `:` just separates statements even if one of those statements is a dummy non-statement. P.S. If you single-step through your code it becomes more apparent what is happening. – YowE3K Feb 01 '17 at 15:34
  • Agree with @YowE3K, I tried it as well, all statements following the `If` and separated with `:` will be merged in one. Following it step by step with the debugger is just amazing! – A.S.H Feb 01 '17 at 15:35
  • @YowE3K, yup, just added it. Looks interesting, did not know it. – Vityata Feb 01 '17 at 15:40
  • 1
    @Vityata - or of course the example `If 5 = 6 Then Debug.Print 5::: Debug.Print 5 Else Debug.Print 6: Debug.Print 6` – YowE3K Feb 01 '17 at 15:42
  • @YowE3K - it is added. – Vityata Feb 01 '17 at 15:45