cristianbuse / VBA-UserForm-MouseScroll

Use the Mouse Scroll Wheel to scroll VBA UserForms and Controls
MIT License
70 stars 12 forks source link

Declare compatible preprocessors #30

Closed SanbiVN closed 11 months ago

SanbiVN commented 11 months ago

Hi cristianbuse!

You declare compatibility as follows, so as not to encounter errors in Windows 64bit and Office Win32.

In your code:

#If VBA7 = 0 Then
    Private Enum LongPtr
        [_]
    End Enum
#End If

Better compatible code:

#If VBA7 = 0 Then
   Private Enum LongLong:[_]:End Enum
   #If VBA6 = 0 OR Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
   #End If
#End If

Have a nice day!

cristianbuse commented 11 months ago

Hi @SanbiVN ,

As you probably already know, Microsoft introduced VBA on 64-bit in 2010 along with VBA7. This introduced a new data type called LongLong and an abstract type LongPtr.

The LongPtr abstract type:

However, LongPtr and LongLong are not declared in VBA6 and prior.

While we do want LongPtr to transform into Long for VBA6 and prior, there is absolutely no need for LongLong because x64 only got introduced in VBA7. Since this repo does not use LongLong as a data type for anything else than x64 (which is implicitly VBA7) then there is absolutely no need to declare Private Enum LongLong:[_]:End Enum. Moreover, this wouldn't even make sense because an Enum is always a Long data type in VBA regardless if x32 or x64.

SanbiVN commented 10 months ago

No @cristianbuse! I actually understand what Microsoft means by that, you don't need to repeat it to me.

What I mean is that your declaration will get a compilation error "Compile error: Expected: identifier" with Win64 OS and Office 32bit.

1680054150970

In your code:

#If VBA7 Then
#Else
Private Enum LongPtr
       [_]
End Enum
#EndIf

Because LongPtr is still available in Win64 OS and Office 32bit. This code works on multiple platforms, including Win64 and Office 32bit, I have verified

#If VBA7 = 0 Then
    #If VBA6 = 0 OR Win64 = 0 Then
    Private Enum LongPtr:[_]:End Enum
    #EndIf
#EndIf

Line of code:

    Private Enum LongLong:[_]:End Enum

Just a redundant line of code, but I'd prefer a full declaration.

Thanks, for your previous answer!

cristianbuse commented 10 months ago

Hi @SanbiVN ,

I actually understand what Microsoft means by that, you don't need to repeat it to me.

Hence my introduction with "As you probably already know,". I was only trying to make sure we are on the same page.

What I mean is that your declaration will get a compilation error "Compile error: Expected: identifier" with Win64 OS and Office 32bit.

I tested this before and re-tested today and I do NOT get that compile error. I tested on x64 OS with x32 Office and x32 OS with x32 Office. I don't see why you would get that error - it must be a bug.

The bitness of the operationg system does not matter. The only impact the bitness of the OS has is that you cannot install a x64 Office on a x32 OS but that's pretty much it. As you already know, the Win64 precompiler constant is tied to the bitness of Office itself and doesn't care about the OS. In other words, OS bitness doesn't matter.

Because LongPtr is still available in Win64 OS and Office 32bit.

That's only true for VBA7 and again regardless of the OS bitness. There is no LongPtr for VBA6 and prior regardless of bitness.


#If VBA7 = 0 Then
    #If VBA6 = 0 OR Win64 = 0 Then
    Private Enum LongPtr:[_]:End Enum
    #EndIf
#EndIf

If VBA7 is 0 then there is no need to check Win64. Win64 can only be true on VBA7. So, #If Win64 = 0 is the equivalent of #If False for VBA6 and prior.

Just to clarify:

Option Explicit

#If VBA7 Then
    'We can have either x32 or x64 Office
    'We have LongPtr
    '
    #If Win64 Then
        'We have a x64 Office on a x64 OS
        'We have LongLong
        'LongPtr defaults to LongLong
        '
        #If Mac Then
            'We are on x64 Office on x64 Mac
        #Else
            'We are on x64 Office on x64 Windows
        #End If
    #Else
        'We have a x32 Office on x32 OS or x64 OS
        'We do not have LongLong
        'LongPtr defaults to Long
        '
        #If Mac Then
            'We are on x32 Office on either x32 or x64 Mac
        #Else
            'We are on x32 Office on either x32 or x64 Windows
        #End If
    #End If
#Else
    'We have VBA6 or prior
    'We are on x32 Office for sure - we cannot have x64 Office
    'OS bitness does not matter. Could be x32 or x64
    'Win64 precompiler does not exist so it is evaluated  to 0/False
    'There is no LongPtr so we add it via Enum
    '
    Private Enum LongPtr
        [_] 'This is a Long which all we need on x32 Office
    End Enum
    '
    #If Mac Then
        'We are on x32 Office on either x32 or x64 Mac
    #Else
        'We are on x32 Office on either x32 or x64 Windows
    #End If
#End If

The fact that your screenshot shows Private Enum LongPtr in Red colour shows that you are on VBA7. You should not get the compiler error. Try updating your Office to a newer version - this seems to be a bug, which would explain both my and your confusion.

To be 100% sure, run this code and let me know the results:

Sub TestPreCompilerConstants()
    Dim m As String
    Dim b As String
    Dim v As String
    '
    #If Mac Then
        m = "Mac"
    #Else
        m = "Windows"
    #End If
    '
    #If Win64 Then
        b = "x64"
    #Else
        b = "x32"
    #End If
    '
    #If VBA7 Then
        v = "VBA7"
    #Else
        v = "VBA6 (or prior)"
    #End If
    '
    MsgBox "You are on " & m & " OS, on " & b & " Office, on " & v
End Sub
SanbiVN commented 10 months ago

Hi @cristianbuse! In the image there is an actual error warning due to VBA's code interpreter. (Win11 64 bit and Office 2019 32bit) This was reported by end users of the application I developed. I also gave them all the typical Debug examples like you, but errors like yours still occur.

You see user reports:

#If VBA7 Then
     ' --> This is platform user
#Else VBA6 Then
     Private Enum LongPtr:[_]:End Enum  ' <--  LongPtr is still interpreted, causing an error -> identifier
#Else
     Private Enum LongPtr:[_]:End Enum
#End If

Some users are also on the same platform, but do not encounter the error.

I then fixed the compatibility declaration my way and all got good results. The API Functions in my code are all declared cross-platform compatible.

I'm sure, one day, an end user will report this error to you! It's also possible that they don't care, and don't report the problem to you.

cristianbuse commented 10 months ago

Thanks @SanbiVN ,

Understood. This is definitely some unexpected behaviour.

sancarn commented 10 months ago

@SanbiVN thanks for directing me here...

I'm not sure if #If VBA6 = 0 OR Win64 = 0 Then is correct? If we want to support VB6 at least, this seems like it would be a problem? Instead shouldn't it be:

#If VBA7 = 0 and Win64 = 0 Then ...

cristianbuse commented 10 months ago

Hi @sancarn ,

I think he was doing #If VBA6 = 0 OR Win64 = 0 Then under the #If VBA7 = 0 branch. I already pointed out that Win64 is False (doesn't exist) under VBA6 and prior.

What he is saying is that for some people, LongPtr appears under VBA6 which is totally unexpected. I cannot replicate this BTW. Like you mentioned under the issue in your repo, it does look like a compiler bug. I also suggested this in this thread as I found similar issues in Mac a while ago (which got fixed after upgrading Office).

sancarn commented 10 months ago

What he is saying is that for some people, LongPtr appears under VBA6

Hmm... Could it be the fault of an addin or referenced type library? I avoid referencing addins/type libraries in all my projects so am a bit inexperienced there 😅

cristianbuse commented 10 months ago

@sancarn

Hmm... Could it be the fault of an addin or referenced type library? I avoid referencing addins/type libraries in all my projects so am a bit inexperienced there 😅

That's a good guess. Even if there is a Public Enum LongPtr in another module within the same project could possibly cause the issue.

cristianbuse commented 10 months ago

@sancarn

Very interestingly, having Public Enum LongPtr: [_]: End Enum in 2 different modules does not throw a compiler error - just tested on VBA6 (Office 2007). However, when I tested this in March 2022 (see here) I was definitely getting a compiler error.

I suspect that Microsoft keeps pushing updates even to older Office version, so I guess it would be plausible that there is a version of VBA6 out there that actually has LongPtr 😆

SanbiVN commented 10 months ago

hi @sancarn and @cristianbuse!

It wasn't just one person who reported the problem. That's why I searched for those who reported like you.

I understand VBA will interpret the preprocessor with the correct value and ignore the rest, but I can't believe that the [#If VBA7] block is already interpreted, but the [#If VBA6] block is not ignored. I also think it's a source code error from the VB interpreter in some version.

I am suffering from brain disorder due to this problem! For now, forget it!