Solved VBA - Inconsistent compile error - Type declaration (1 Viewer)

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
Hello,

This is getting frustrating at the cost of many hours of production.

A project i am working on is throwing a compile error on the line:

Code:
baK(lIdx) = asc(Mid$(sKey, 1 + (lIdx Mod Len(sKey)), 1))

This is true for a few "MID" functions in this project that are entirely unrelated to one another and some instances where the parent function is completely unused. This started randomly last night. The function that contains the line above was introduced to the project (its an RC4 Encryption Alg) AFTER i had to ditch a previous encryption function that was completely different but still used a "MID$" function within. I ditched the first function because rather than scratch my head at it, i would just try a new function i had. Please note this function (as well as the previous i used) has compiled and executed fine several hundred times before.

The compiler raises "Type declaration character does not match declared data type".

I have tried running the VBA decompiler tool on the project multiple times.

CODE :
Code:
Public Function EncryptRC4(sText As String, sKey As String) As String
    Dim baS(0 To 255) As Byte
    Dim baK(0 To 255) As Byte
    Dim bytSwap     As Byte
    Dim lI          As Long
    Dim lJ          As Long
    Dim lIdx        As Long

    For lIdx = 0 To 255
        baS(lIdx) = lIdx
        baK(lIdx) = asc(Mid$(sKey, 1 + (lIdx Mod Len(sKey)), 1))
    Next
    For lI = 0 To 255
        lJ = (lJ + baS(lI) + baK(lI)) Mod 256
        bytSwap = baS(lI)
        baS(lI) = baS(lJ)
        baS(lJ) = bytSwap
    Next
    lI = 0
    lJ = 0
    For lIdx = 1 To Len(sText)
        lI = (lI + 1) Mod 256
        lJ = (lJ + baS(lI)) Mod 256
        bytSwap = baS(lI)
        baS(lI) = baS(lJ)
        baS(lJ) = bytSwap
        EncryptRC4 = EncryptRC4 & Chr$((pvCryptXor(baS((CLng(baS(lI)) + baS(lJ)) Mod 256), asc(Mid$(sText, lIdx, 1)))))
    Next
End Function
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Tomorrow, 02:28
Joined
May 7, 2009
Messages
19,169
Mid$() as the function suggests, will return a String type.
while Mid() will return a variant type.
 

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
Mid$() as the function suggests, will return a String type.
while Mid() will return a variant type.


I attempted remove the declaration '$'. Then the compiler complains "Expected array".
 

Isaac

Lifelong Learner
Local time
Today, 11:28
Joined
Mar 14, 2017
Messages
8,738
Is the byte array correct? I think bite only goes to 254
 

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
Yes byte array, never considered there's actually 256 values being stored...

Regardless, like i said, this function executed several hundred times and the fact that I had other MID functions in this project flag randomly at the exact time this started (functions i never touched), this is obvious VBA compiler corruption - whether that is due to a confusion in this function or not, its not being consistent and the compiler is failing to be logically consistent.

Read here:
 

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
My next step is to copy the Module to plain text and re-import manually in a fresh module.
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Tomorrow, 02:28
Joined
May 7, 2009
Messages
19,169
add Option Explicit on each of your module, forms, report etc.
compile and you will see exactly where is the error.
 

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
add Option Explicit on each of your module, forms, report etc.
compile and you will see exactly where is the error.
This isn't my first day writing VBA...

I just exported every single forms, module, and table in this DB to a fresh DB. I then used a third encryption algorithm and the MID function still flags as a compile error in a completely different function that is entirely unrelated to the one in question. This is obvious corruption. I demonstrated where the error is in the function above.

I welcome you to try and compile this code in a fresh db. You will find it works flawlessly. There is apparently another piece of code in the project that VBA is not happy with. Yet it fails to show me where that is because its hung up on a WORKING piece of code. (how reliable).

Code:
Option Explicit
Const MyKey As String = "blah"

Enum VBAHashTypes
SHA512_ = 512
SHA384_ = 384
SHA256_ = 256
MD5_ = 5
End Enum

Public Function HASH(val As String, Optional HashType As VBAHashTypes = SHA512_, Optional Base64 As Boolean = True) As String
Dim HType               As Integer
Dim Encoder             As Object
Dim Provider            As Object
Dim Text2Hash()         As Byte
Dim Bytes()             As Byte

'On Error GoTo Handler
Set Encoder = CreateObject("System.Text.UTF8Encoding")
HType = HashType

Select Case HType
    Case 512:
        Set Provider = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
    Case 384:
        Set Provider = CreateObject("System.Security.Cryptography.SHA384Managed")
    Case 256:
        Set Provider = CreateObject("System.Security.Cryptography.SHA256Managed")
    Case 5:
        Set Provider = CreateObject("System.Security.Cryptography.MD5CryptoServiceProvider")
End Select

Text2Hash = Encoder.Getbytes_4(val)
Bytes = Provider.ComputeHash_2((Text2Hash))

If Base64 = True Then
   HASH = ConvToBase64String(Bytes)
Else
   HASH = ConvToHexString(Bytes)
End If
Set Provider = Nothing
Set Encoder = Nothing
Exit Function

'Handler:
    'MsgBox "*CRITICAL* :  Error in hash function. Contact system administrator."
End Function


Public Function RC4(val As String) As String
RC4 = EncryptRC4(val, MyKey)
End Function


Private Function EncryptRC4(sText As String, sKey As String) As String
    Dim baS(0 To 255) As Byte
    Dim baK(0 To 255) As Byte
    Dim bytSwap     As Byte
    Dim lI          As Long
    Dim lJ          As Long
    Dim lIdx        As Long

    For lIdx = 0 To 255
        baS(lIdx) = lIdx
        baK(lIdx) = asc(Mid(sKey, 1 + (lIdx Mod Len(sKey)), 1))
    Next
    For lI = 0 To 255
        lJ = (lJ + baS(lI) + baK(lI)) Mod 256
        bytSwap = baS(lI)
        baS(lI) = baS(lJ)
        baS(lJ) = bytSwap
    Next
    lI = 0
    lJ = 0
    For lIdx = 1 To Len(sText)
        lI = (lI + 1) Mod 256
        lJ = (lJ + baS(lI)) Mod 256
        bytSwap = baS(lI)
        baS(lI) = baS(lJ)
        baS(lJ) = bytSwap
        EncryptRC4 = EncryptRC4 & Chr$((pvCryptXor(baS((CLng(baS(lI)) + baS(lJ)) Mod 256), asc(Mid$(sText, lIdx, 1)))))
    Next
End Function

Private Function pvCryptXor(ByVal lI As Long, ByVal lJ As Long) As Long
    If lI = lJ Then
        pvCryptXor = lJ
    Else
        pvCryptXor = lI Xor lJ
    End If
End Function

Public Function ToHexDump(sText As String) As String
    Dim lIdx            As Long

    For lIdx = 1 To Len(sText)
        ToHexDump = ToHexDump & Right$("0" & Hex(asc(Mid(sText, lIdx, 1))), 2)
    Next
End Function

Public Function FromHexDump(sText As String) As String
    Dim lIdx            As Long

    For lIdx = 1 To Len(sText) Step 2
        FromHexDump = FromHexDump & Chr$(CLng("&H" & Mid(sText, lIdx, 2)))
    Next
End Function


Private Function ConvToBase64String(vIn As Variant) As Variant

    Dim oD As Object
      
    Set oD = CreateObject("MSXML2.DOMDocument")
      With oD
        .LoadXML "<root />"
        .DocumentElement.DataType = "bin.base64"
        .DocumentElement.nodeTypedValue = vIn
      End With
    ConvToBase64String = Replace(oD.DocumentElement.Text, vbLf, "")
    
    Set oD = Nothing

End Function

Private Function ConvToHexString(vIn As Variant) As Variant

    Dim oD As Object
      
    Set oD = CreateObject("MSXML2.DOMDocument")
      
      With oD
        .LoadXML "<root />"
        .DocumentElement.DataType = "bin.Hex"
        .DocumentElement.nodeTypedValue = vIn
      End With
    ConvToHexString = Replace(oD.DocumentElement.Text, vbLf, "")
    
    Set oD = Nothing

End Function
 

Isaac

Lifelong Learner
Local time
Today, 11:28
Joined
Mar 14, 2017
Messages
8,738
it works flawlessly. There is apparently another piece of code in the project that VBA is not happy with. Yet it fails to show me where that is because its hung up on a WORKING piece of code
this is exactly how a generalized database corruption has almost always presented itself to me. it will fail to compile, stopping on some ridiculously simple (and usually a native) VBA function, like Left() or Mid().
 

arnelgp

..forever waiting... waiting for jellybean!
Local time
Tomorrow, 02:28
Joined
May 7, 2009
Messages
19,169
search all your Project for "MID(", check if there is one that is UDF.
i remember having an issue that the project will not compile because it is pointing
on a built-in access function.
turns out when i search there is same function which i copied from a forum that
is embedded on code on the button click event.

This isn't my first day writing VBA...
coding and debugging goes together.
 
Last edited:

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
coding and debugging goes together.
Except its hard to debug when your debugger needs debugged.


Turns out my speculations became conclusive. This project has something going on where the MID function is not cooperating. Furthermore, intellisense doesn't even recognize MID, but it will recognize Left, Right, and every other function in the VBA library as it should.

I solved this by setting a direct reference to VBA.mid
What do you know, the code compiles.

I will search for "MID" keyword and see if there is something ambiguous.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 14:28
Joined
May 21, 2018
Messages
8,463
If you have a bad or broken reference it often manifests in simple vba string functions failing (left, right, mid, instr, ...). The reason is when you call a function the compiler starts to look through the loaded libraries in alphabetical order. That puts VBA at the end. So as it searches it hits a broken reference and never even gets to the VBA reference. So it looks like a VBA issue but in fact it is a non related reference.
 

MajP

You've got your good things, and you've got mine.
Local time
Today, 14:28
Joined
May 21, 2018
Messages
8,463
This is why vba.mid will work. It goes directly to the vba library skipping the loop through all the references. You have a bad reference.
 

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
Update:

2 seconds of searching, I had an Enum value as "Mid" (Google Maps APIs, one of the marker size arguments is "MID" - what a dumb way to describe size, am i right) . Problem solved.
Silly me!

What a waste
 

ironfelix717

Registered User.
Local time
Today, 14:28
Joined
Sep 20, 2019
Messages
193
If you have a bad or broken reference it often manifests in simple vba string functions failing (left, right, mid, instr, ...). The reason is when you call a function the compiler starts to look through the loaded libraries in alphabetical order. That puts VBA at the end. So as it searches it hits a broken reference and never even gets to the VBA reference. So it looks like a VBA issue but in fact it is a non related reference.

Great info. Lessons learned.
 

Users who are viewing this thread

Top Bottom