sancarn / stdVBA

VBA Standard Library - A Collection of libraries to form a common standard layer for modern VBA applications.
MIT License
288 stars 60 forks source link

Compatible Long And Longptr #81

Closed SanbiVN closed 10 months ago

SanbiVN commented 10 months ago

hi Pro!

This declaration code is not compatible with Win64 OS and Office 32bit, causing code compilation error: "Compile error: Expected: identifier"

1680054150970

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

This code works on Win64 and Office 32bit, I have verified

#If VBA7 = 0 Then
   'Private Enum LongLong:[_]:End Enum ' This declaration is required
   #If VBA6 = 0 OR Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
   #End If
#End If

Thanks for your Project!

sancarn commented 10 months ago

Hello,

Which file/module did you find this declaration in? I don't actually see it anywhere...

Also VBA6 didn't have LongPtr I believe, so the VBA6 statement shouldn't be there. Though I was fairly sure Win64 declarations weren't required either... So I'm not sure why this would be throwing a compile error... 😕

sancarn commented 10 months ago

So I'm not sure why this would be throwing a compile error

It could be a corrupt VBA module. I'd suggest commenting out the module, saving it, and uncommenting the module again. This will reset the structure of the pcode and ensure it isn't a corruption issue.

SanbiVN commented 10 months ago

Hi @sancarn!

Please read the conversation between me and @cristianbuse, maybe you will understand more about the issue.

https://github.com/cristianbuse/VBA-UserForm-MouseScroll/issues/30

sancarn commented 10 months ago

As discussed in https://github.com/cristianbuse/VBA-UserForm-MouseScroll/issues/30 won't fix this as it's unexpected and will affect compatibility with VB6

SanbiVN commented 10 months ago

Hi @sancarn!

will affect compatibility with VB6

The declaration I have proposed is compatible both in VB6 and VBA environments. If you look back at the condition in the code, the Win64 compiler argument does not exist in the VBA6 (VBA) and VB6 environments, so the Win64 value is always 0. In the VB6 environment, the VBA7, VBA6, and Win64 compiler arguments are also does not exist. So declaring LongPtr will be enough to compile, if suitable for the environment.

cristianbuse commented 10 months ago

Hi @SanbiVN ,

The declaration you proposed is not compatible as you might think. I understand that some of your users already have LongPtr for VBA6 but when I test on my computers, I do not have LongPtr in VBA6. So, I still need the enum declaration. In other words, the declaration used in this repo and in mine work but yours does not work.

To clarify, this:

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

throws a compiler error (User-defined type not defined)

But this:

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

works fine

SanbiVN commented 10 months ago

@cristianbuse, Thank you! I will ask for help from users, check a few more cases about this declaration!

sancarn commented 10 months ago

You are unlikely to be able to get around it, unless you can determine at compile time whether LongPtr is defined or not. One option would be:

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

Then you can apply a patch to the compiler args of customer's projects, perhaps.

SanbiVN commented 10 months ago

Hi @sancarn!

It's still best practice to use VBA's default compiler arguments. I'll let users test a few declarative cases as @cristianbuse suggested, and wait for their responses.

sancarn commented 10 months ago

I think it's the only solution for you that will work. Generally LongPtr is not defined in VBA6. I.E. this error should not occur, unless perhaps you've got some addin installed/referenced or perhaps an incorrect version of Excel(?)

SanbiVN commented 10 months ago

Hi @sancarn and @cristianbuse!

I want to verify the declaration again on your computer, please let me know your test results. Sorry you two for this suggestion, in fact I have received feedback from users, and I need your opinions.

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

#If VBA7 Then
        Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#Else
        Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As LongPtr)
#End If

Thank you both for your support.

At the same time, please take a look at my VB Tools project with compatible declaration code as in the first article, I use Win32 API functions, all of which are declared compatible, please try to take a look once.

https://github.com/SanbiVN/VBA_FastCode

cristianbuse commented 10 months ago
#If VBA7 = 0 And Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If

is exactly the same as:

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

because Win64 is always 0 for anything else than VBA7. It works fine for me since it's the exact thing that I'm having right now.

sancarn commented 10 months ago

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

Does this resolution work for your users? Seems surprising to me that Win64 is true for them.

SanbiVN commented 10 months ago

Hi @sancarn I give the declarations to the user, the above result is the feedback from the user.

SanbiVN commented 10 months ago

Hi @cristianbuse!

I had users test the two types of declarations you're mentioning, they told me the first one worked fine, the other one didn't.

(System: Windows 11 64bit, Office 2019 32bit)

Is there any difference between the two declarations?

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

(There are bug reports)

And:

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

(Works fine)

sancarn commented 10 months ago
#If Win64 = 0 Then

is different to

#If VBA7 = 0 Then

If that's what you are asking.


I think @cristianbuse is saying is that adding the Win64 declaration to this:

#If VBA7 = 0  And Win64 = 0 Then

Should cause no difference, because you only have Win64 under VBA7. Thus all non-VBA7 will always be non-Win64. This was my expectation also. But if you are claiming that someone has VBA6 AND Win64 (which appears what you are suggesting, this might be different).


It would be really useful if your users could actually run the code previously suggested by @cristianbuse :

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

And report back on what the msgbox says. I did see your thread but can't read vietnamese so am only getting what google gives me 😂 But I can see that your users haven't ran this specific code snippet. It would be very helpful if they did, as then we really can see if we can build anything robust or not.

SanbiVN commented 10 months ago

Hi @sancarn

My topic is quite funny, I titled it "Advanced VBA", while my interlocutor did not know about VBA preprocessing. I have to follow their direction. Makes the problem worse.

I suggest declaring it to them, they don't know how to Debug Compile, they only see the line of code highlighted in red. And then, They gave me feedback that it was an error.


Users told me that when testing VBA, the results printed were "VBA7 and x32" on System: Windows 11 64bit, Excel 2019 32bit.

To get the results as @cristianbuse suggested, I asked them to test and the results are:

1698719522007

The results remain the same.


@sancarn and @cristianbuse I let them test four cases, the results were, 1 and 2 did not report errors, 3 and 4 reported errors. (I advised them to go to Debug Compile, after copying the code into VBE)

Case 1:

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

Case 2:

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

Case 3:

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

Case 4:

#If Win64 = 0 Then
   Private Enum LongPtr:[_]:End Enum
#End If
sancarn commented 10 months ago

How bizarre that case2 where Win64 is included has any effect when supposedly the msgbox claimed that they were on VBA7 and 32 bit O_o Thanks for the info, I'll change the declares in stdVBA, it can't hurt at least...

SanbiVN commented 10 months ago

I was previously skeptical about the statement Enum LongPtr #If VBA7 = 0 , but it turns out my doubts were a good thing. It was a pleasure talking to you both. If possible, next time I will try to bother you guys more.

cristianbuse commented 10 months ago

Hi @SanbiVN ,

Thanks. Out of curiosity, does this work for your users?

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

Or this?

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

There is this compiler bug that I know. Since that post the bug was only partially fixed.

SanbiVN commented 10 months ago

Hi @cristianbuse

The And operator is a Bitwise operator so: When VBA7 = 1, the value of the operation VBA7 = 0 And True will always be 0 When VBA7 = 0, the value of the operation VBA7 = 0 And True will always be -1

When VBA7 = 1 and Win64 = 1, VBA7 = 1 and Win64 = 0: the value of the operation VBA7 = 0 And Win64 = 0 will always be 0


The error is in the topic at the link, not related to this topic, because that error is a rare case, only occurs when calling the New operator directly as a function argument, and at the same time declaring it in a class with the command end Class_Terminate.

cristianbuse commented 10 months ago

@SanbiVN ,

I know, but so Win64 = 0 is always True when VBA7 = 0 and yet you are saying that some users experience compiler errors. So, I was just curious if repalcing with True directly still works. Please indulge me 😄

SanbiVN commented 10 months ago

@cristianbuse

We should stop talking about this issue. Take some quiet time to enjoy a country song by Taylor Swift. Forget about lines of code, close your eyes and imagine, dream more, love life more. Open your lips and smile brightly.

cristianbuse commented 10 months ago

@SanbiVN ,

So, can your users test the two cases using True?

SanbiVN commented 10 months ago

Hi @cristianbuse!

Yesterday's comment was just a fun comment, to let me finish my working day, because in my country it's almost 10pm.


Two cases had no errors.

I have added a declaration with the function CBool and the operator NOT so that users can test again from the beginning. The response was quite shocking. No errors occurred.

#If VBA7 Then
#Else
   Public Enum LongPtr:[_]:End Enum
#End If
#If VBA7 = 0 Then
   Public Enum LongPtr:[_]:End Enum
#End If
#If Not -VBA7 Then
   Public Enum LongPtr:[_]:End Enum
#End If
#If CBool(VBA7 = 0) Then 
   Public Enum LongPtr:[_]:End Enum
#End If
#If VBA7= 0 And Win64 = 0 Then
   Public Enum LongPtr:[_]:End Enum
#End If
#If Not (-VBA7 OR -Win64) Then 
   Public Enum LongPtr:[_]:End Enum
#End If

The VBA compiler has no problem. The problem lies with my users. Apparently, they are learning more about VBA by interacting with my articles.

How to explain this photo that users responded to in my thread?

sancarn commented 10 months ago

So let me get this straight... There isn't actually a problem with

#If VBA7 Then
#Else
   Public Enum LongPtr:[_]:End Enum
#End If

? 😂😂

SanbiVN commented 10 months ago

@sancarn

Exactly like that

KallunWillock commented 10 months ago

Is it possible that OP has added a 32bit type library reference to the project that is conflicting with this enum declaration? Eg: https://www.vbforums.com/showthread.php?898078-Typelib-to-add-LongPtr-type-to-VB6-for-universal-codebases