Blue Fin
asked on
Getting Runtime Error 91: Object variable or With block variable not set in Access
Hi,
I am getting "Runtime Error 91: Object variable or With block variable not set. In my opinion the issue is due to the Object: CreateObjectNet is set to nothing. I have attached a .pdf file which has the code shown.
Help and guidance will be appreciated.
CreateObjectNet Set to Nothing.pdf
I am getting "Runtime Error 91: Object variable or With block variable not set. In my opinion the issue is due to the Object: CreateObjectNet is set to nothing. I have attached a .pdf file which has the code shown.
Help and guidance will be appreciated.
CreateObjectNet Set to Nothing.pdf
I don't even know how to spell .Net but what is MyCreateObject? Shouldn't it just be CreateObject?
ASKER
Thanks Martin for your reply.
No it not a workbook the code is part of vba Access 2019 (part of Office 365 Suite).
And to your earlier question MyCreateObject is optional keyword that can be used during declaration to implicitly enable object creation. Here I am trying to assign a object reference.
No it not a workbook the code is part of vba Access 2019 (part of Office 365 Suite).
And to your earlier question MyCreateObject is optional keyword that can be used during declaration to implicitly enable object creation. Here I am trying to assign a object reference.
The error message says, that there is no defined Object.
The reason is, that - Martin Liss already said this - that you create an external object, and the command to do this is CreateObject.
https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/createobject-function
A DLL in VBA is usually called by its classname, how it is registered in the registry as CLSID.
The reason is, that - Martin Liss already said this - that you create an external object, and the command to do this is CreateObject.
https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/createobject-function
A DLL in VBA is usually called by its classname, how it is registered in the registry as CLSID.
ASKER
@Bambi,@Martin
The fact that the same code works perfectly on two different machines perplexed me...I have attached a .pdf document with code snippets from both machines so that the difference can be observed. Code.pdf
The fact that the same code works perfectly on two different machines perplexed me...I have attached a .pdf document with code snippets from both machines so that the difference can be observed. Code.pdf
Does the problem machine(s) run 64bit and the good machine(s) 32bit or vice versa?
ASKER
Martin,
Machine A on which the code is failing have Access 2016 - 32 Bit
Machine B on which the code is working have Access 2010 - 32 Bit.
I have also attached a screenshot for the two.Access Ver Info.pdf
Machine A on which the code is failing have Access 2016 - 32 Bit
Machine B on which the code is working have Access 2010 - 32 Bit.
I have also attached a screenshot for the two.Access Ver Info.pdf
Based on that I'm tempted to say that something was lost between Access 2010 and Access 2016, but that's probably not the case and so the only thing I can suggest is that if the problem is limited to just one machine then try things on that machine like rebooting or reinstalling Access.
ASKER
Martin,
I have another Machine with Access 2016 MSO (32 bit) and NOT Microsoft Access 365 MSO (32 Bit) as on Machine A the code is also working fine on that machine since the Microsoft Access version number is the same i.e. 16.
Just thinking out loud should I repair the Office installation?
I have another Machine with Access 2016 MSO (32 bit) and NOT Microsoft Access 365 MSO (32 Bit) as on Machine A the code is also working fine on that machine since the Microsoft Access version number is the same i.e. 16.
Just thinking out loud should I repair the Office installation?
If you back it up first it can't hurt.
ASKER
Just did a re-install but still the same issue...one thing I want to mention is that this code is referencing a .dll file.
I have read that sometime difference in .NET framwork installed on a machine also matters and I checked that the versions are same on both machine.
I have read that sometime difference in .NET framwork installed on a machine also matters and I checked that the versions are same on both machine.
Okay, sorry but I can't think of anything else.
@Martin..., stay here :-)
@Blue Fin
I would say that this is either just a function or it comes from any other reference.
But it is definitely not part of any Office VBA. At least all my Office versions doesn't show any valid reference.
2.) You use conditional compilation and reference the WIN64 to point to nloader64.dll or nloader.dll and you reflect to CurrentProject.Path. That means, the nloader.dll (32 Bit Office) or nloader64.dll (64 Bit Office) has to reside in the same folder than the database.
As we can not see what is behind "MyCreateObject", we can not really tell you what is happening in this procedure, but you may step with F8 through your code and see, what is going on, especially where CurrentProject.Path points to and if the DLLs reside there.
@Blue Fin
MyCreateObject is optional keyword that can be used during declaration ...1.) OK, can you show me please the reference? In Object Browser or what ever you can find?
I would say that this is either just a function or it comes from any other reference.
But it is definitely not part of any Office VBA. At least all my Office versions doesn't show any valid reference.
2.) You use conditional compilation and reference the WIN64 to point to nloader64.dll or nloader.dll and you reflect to CurrentProject.Path. That means, the nloader.dll (32 Bit Office) or nloader64.dll (64 Bit Office) has to reside in the same folder than the database.
As we can not see what is behind "MyCreateObject", we can not really tell you what is happening in this procedure, but you may step with F8 through your code and see, what is going on, especially where CurrentProject.Path points to and if the DLLs reside there.
stay here :-)Okay.
If you Google MyCreateObject you'll get a bunch of hits so it is a real thing. One of the hits is this one which may not apply in your case but the last post says that that person's problem was fixed by reinstalling the .NET Framework.
ASKER
@bambi
Please see attached .pdf MyCreateObject.pdf
You are right is a member (function)
On your point # 2, yes both the .dll (32 Bit and 64 Bit) are in the same folder (that is a requirement). I did step into the code please see .pdf Code1.pdf
As you can see in the Code1.pdf file CurrentProject.Path points to location where the referenced .DLLs are stored.
@Martin,
Your recommendation is to re-install .NET Framework...
Please see attached .pdf MyCreateObject.pdf
You are right is a member (function)
On your point # 2, yes both the .dll (32 Bit and 64 Bit) are in the same folder (that is a requirement). I did step into the code please see .pdf Code1.pdf
As you can see in the Code1.pdf file CurrentProject.Path points to location where the referenced .DLLs are stored.
@Martin,
Your recommendation is to re-install .NET Framework...
Your recommendation is to re-install .NET Framework...Yes, and as long as you make a backup first it can't hurt to try it.
ASKER
@Martin
This is very strange issue, I just tested the code on a new machine which also has Office 365 i.e. same version as in the Machine (laptop) with issues and the codes runs fine...!!!
OK I will re-install the .NET Framework to the latest version available and post back.
This is very strange issue, I just tested the code on a new machine which also has Office 365 i.e. same version as in the Machine (laptop) with issues and the codes runs fine...!!!
OK I will re-install the .NET Framework to the latest version available and post back.
OK, we narrow down the issue...
Please post pictures and codeblocks, and not just PDF, it makes the thread unreadable.
You can just copy and paste it into here.
So if I interpret your pictures in the right way, you have a module called NetLoader, where you declare the 4 methods including MyCreateObject and LoadLib...., they point to nloader.dll (following your Object Broser)
Inside your code, you use the LoadLib to check if either nloader.dll or nloader64.dll is loaded?
Doesn't make sense to me to check a static declare against a version dependend DLL...
Either you have declared the correct DLL or it will fail anyway. You just hit the error with the hammer and set the object to nothing.
But nevertheless interesting what LoadLib delivers back as well as the values of loaderDLL and bsIsLoaded
An then you call the MyCreateObject inside that static declared DLL to load a class Pmerge.Pmerge inside the Pmerge.dll library.
So far for clarification.
So lets assume the nloader.dll is loaded and declared with the correct version, you use a 32 Bit Office and your code reaches the part of the MyCreateObject....
My next question would be, where these DLLs coming from, like Martin I found a few rare links but nothing really usefull.
A DLL can be, but need not to be connected with NET Framework, and because I can not sort them into any direction, I can not tell you if reinstalling NET Framework may help or not. Even it is not clear which version of NET Framework, maybe 3.x or 4.x. They arenot compatible to each other, so if you need one of them, you have tofind out which one your need. If the DLL reflects to NET 3.x, what is noit installed by default on newer systems, it will fail, even 4.x is installed.
You may search the registry, if you can find Pmerge.Pmerge or only Pmerge, if there are differences between working and non working clients. If you call a Class inside a library, it should be registered with a CLSID, nevertheless it is possible to hook blind into a DLL without any registration.
The other option is also possible, that the DLL is registered, but with a different path.
At the end, you have to follow the instructions of the source of this DLLs as nobody else can tell you, what the libraries are doing and how they work and what they need.
Please post pictures and codeblocks, and not just PDF, it makes the thread unreadable.
You can just copy and paste it into here.
So if I interpret your pictures in the right way, you have a module called NetLoader, where you declare the 4 methods including MyCreateObject and LoadLib...., they point to nloader.dll (following your Object Broser)
Inside your code, you use the LoadLib to check if either nloader.dll or nloader64.dll is loaded?
Doesn't make sense to me to check a static declare against a version dependend DLL...
Either you have declared the correct DLL or it will fail anyway. You just hit the error with the hammer and set the object to nothing.
But nevertheless interesting what LoadLib delivers back as well as the values of loaderDLL and bsIsLoaded
An then you call the MyCreateObject inside that static declared DLL to load a class Pmerge.Pmerge inside the Pmerge.dll library.
So far for clarification.
So lets assume the nloader.dll is loaded and declared with the correct version, you use a 32 Bit Office and your code reaches the part of the MyCreateObject....
My next question would be, where these DLLs coming from, like Martin I found a few rare links but nothing really usefull.
A DLL can be, but need not to be connected with NET Framework, and because I can not sort them into any direction, I can not tell you if reinstalling NET Framework may help or not. Even it is not clear which version of NET Framework, maybe 3.x or 4.x. They arenot compatible to each other, so if you need one of them, you have tofind out which one your need. If the DLL reflects to NET 3.x, what is noit installed by default on newer systems, it will fail, even 4.x is installed.
You may search the registry, if you can find Pmerge.Pmerge or only Pmerge, if there are differences between working and non working clients. If you call a Class inside a library, it should be registered with a CLSID, nevertheless it is possible to hook blind into a DLL without any registration.
The other option is also possible, that the DLL is registered, but with a different path.
At the end, you have to follow the instructions of the source of this DLLs as nobody else can tell you, what the libraries are doing and how they work and what they need.
ASKER
@bembi
I appreciate your response.
I am working on that machine remotely so as soon as I get access to it I will definitely post the code blocks as you mentioned.
I think it is better to give a little back ground of the DLLs and why they are being used in Access database:
I needed a way to merge more then one pdf file in a folder without using a "third party software" so on another forum a very helpful gentleman provided his tested (and tweaked) .NET Library for processing PDF files taken from PDFSharp and NetLoader module.
The instructions/information to implement these .DLLs was as follows:
1. Download and save them in the same folder where your Front End (FE) Database file is stored.
2. Import the NetLoader into your FE DB
3. Import Module1 (also provided) which I need to call within my vba code when a user click a button to combine the pdf file into one file. Need to make few changes such as updating with the paths of the PDF files located in my system
So the program flow is follows:
1. User Click a button to combine the pdf file into one:
2. It takes the program to execute code in Module1 below:
3. The following line of code takes the program control to NetLoader Module
6. Netloader loads the required .dll files which uses PDFSharp class libraries.
7. The PDFSharp .NET Library for processing PDFs provide a Pmerge Class which can be used to merge PDF files in a specific folders. The .DLL were already tweaked and ready to use. The ONLY modification required was as I mentioned above to recompile the NetLoader module on your machine and place the .DLLs in the same folder of your FE database.
The .dlls provided was compiled in 4.0 with a note that they will work seamlessly with PCs with .NET Framework Versions 4.0 and upward installed. That was indeed the case until I tested this code on a Machine A where the code failed and was giving me Runtime Error 91.
Again thanks for looking into the issue.
I appreciate your response.
I am working on that machine remotely so as soon as I get access to it I will definitely post the code blocks as you mentioned.
I think it is better to give a little back ground of the DLLs and why they are being used in Access database:
I needed a way to merge more then one pdf file in a folder without using a "third party software" so on another forum a very helpful gentleman provided his tested (and tweaked) .NET Library for processing PDF files taken from PDFSharp and NetLoader module.
The instructions/information to implement these .DLLs was as follows:
1. Download and save them in the same folder where your Front End (FE) Database file is stored.
2. Import the NetLoader into your FE DB
3. Import Module1 (also provided) which I need to call within my vba code when a user click a button to combine the pdf file into one file. Need to make few changes such as updating with the paths of the PDF files located in my system
So the program flow is follows:
1. User Click a button to combine the pdf file into one:
2. It takes the program to execute code in Module1 below:
Sub TestMerge2()
Dim MyPdf As Object
Set MyPdf = CreateObjectNET("Pmerge.dll", "Pmerge.Pmerge")
MyPdf.Add CurrentProject.Path & "\a.pdf"
MyPdf.Add CurrentProject.Path & "\b.pdf"
' set output file to merge above list to
MyPdf.OutPutDoc = CurrentProject.Path & "\ab.pdf"
'MyPdf.CreatePageNumbers = True
MyPdf.Merge ' merge the files
End Sub
3. The following line of code takes the program control to NetLoader Module
Set MyPdf = CreateObjectNET("Pmerge.dll", "Pmerge.Pmerge")
4. The NetLoader Module code is below:Private Declare PtrSafe Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
#If Win64 Then
Private Declare PtrSafe Function MyCreateObject Lib "nloader64.dll" (ByVal strDll As String, ByVal strClass As String) As Object
#Else
Private Declare PtrSafe Function MyCreateObject Lib "nloader.dll" (ByVal strDll As String, ByVal strClass As String) As Object
#End If
'Private Function LoadLib(strDll As String) As Boolean
Dim s As String
Dim blRet As Boolean
Dim hLibDynaPDF As LongPtr
On Error Resume Next
LoadLib = False
hLibDynaPDF = LoadLibrary(CurrentProject.Path & "\" & strDll)
If hLibDynaPDF = 0 Then
' Our error string
s = "Sorry...cannot find the " & strDll & " file" & vbCrLf & _
"Please ensure that the " & strDll & " file is placed in the same folder as " & CurrentProject.Path
MsgBox s, vbOKOnly, "MISSING " & strDll & " FILE"
LoadLib = False
Exit Function
End If
' RETURN SUCCESS
LoadLib = True
End Function
Public Function CreateObjectNET(strDll As String, strClass As String) As Object
Static bIsLoaded As Boolean ' local static - for one time load
Dim loaderDLL As String ' use x64 or x32 .net loader
#If Win64 Then
loaderDLL = "nloader64.dll"
#Else
loaderDLL = "nloader.dll"
#End If
If bIsLoaded = False Then
If LoadLib(loaderDLL) = False Then
Set CreateObjectNET = Nothing
Exit Function
Else
bIsLoaded = True
End If
End If
Set CreateObjectNET = MyCreateObject(CurrentProject.Path & "\" & strDll, strClass)
End Function
5. The following line of code takes back the program control to Module1 Set CreateObjectNET = MyCreateObject(CurrentProject.Path & "\" & strDll, strClass)
Module1 codes starts to execute from: MyPdf.Add CurrentProject.Path & "\a.pdf"
MyPdf.Add CurrentProject.Path & "\b.pdf"
' set output file to merge above list to
MyPdf.OutPutDoc = CurrentProject.Path & "\ab.pdf"
'MyPdf.CreatePageNumbers = True
MyPdf.Merge ' merge the files
End Sub
I am getting Runtime Error 91 at the bolded line in Module1 code above. 6. Netloader loads the required .dll files which uses PDFSharp class libraries.
7. The PDFSharp .NET Library for processing PDFs provide a Pmerge Class which can be used to merge PDF files in a specific folders. The .DLL were already tweaked and ready to use. The ONLY modification required was as I mentioned above to recompile the NetLoader module on your machine and place the .DLLs in the same folder of your FE database.
The .dlls provided was compiled in 4.0 with a note that they will work seamlessly with PCs with .NET Framework Versions 4.0 and upward installed. That was indeed the case until I tested this code on a Machine A where the code failed and was giving me Runtime Error 91.
Again thanks for looking into the issue.
OK, now I understand a bit more...
What I can see here is...(nevertheless is seems to work on some clients...)
PtrSafe is / has to only used in 64 Bit environments.
So the correct (or more save) declaration would be
https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/ptrsafe-keyword
The point is, that you can use wrong declarations with the windows API as long as the values are not overwriting memory. If you overwrite a declared value in memory, the result will be an memory exception, the application will crash.
The second point is, that a wrong declaration my force windows to use address space what is not addressable by 32 Bit applications. In that case you doesn't get a valid value back.
To avoid both options, you have to take care about the correct declarations, otherwise you do not have any control, what windows is doing, it may work or even not.
If the libraries are compiled for Net 4.x Framework, it may be an option to reinstall / repair the Net Framework, but seldom seen issues with the 4.x version.
What I can see here is...(nevertheless is seems to work on some clients...)
Private Declare PtrSafe Function LoadLibrary Lib "kernel32" _
Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
#If Win64 Then
Private Declare PtrSafe Function MyCreateObject Lib "nloader64.dll" (ByVal strDll As String, ByVal strClass As String) As Object
#Else
Private Declare PtrSafe Function MyCreateObject Lib "nloader.dll" (ByVal strDll As String, ByVal strClass As String) As Object
#End If
...
Dim hLibDynaPDF As LongPtr
LongPtr on Win32 is a long value while on 64 Bit a LongLong. It is not an own datatype than rather a Pointer, which can be converted by vba. LoadLibrary delivers a handle, but they are long values in 32 Bit environments.PtrSafe is / has to only used in 64 Bit environments.
So the correct (or more save) declaration would be
#If Win64 Then
Private Declare PtrSafe Function MyCreateObject Lib "nloader64.dll" (ByVal strDll As String, ByVal strClass As String) As Object
Private Declare PtrSafe Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As LongPtr
Dim hLibDynaPDF As LongPtr
#Else
Private Declare Function MyCreateObject Lib "nloader.dll" (ByVal strDll As String, ByVal strClass As String) As Object
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Dim hLibDynaPDF As Long
#End If
Seehttps://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/ptrsafe-keyword
The point is, that you can use wrong declarations with the windows API as long as the values are not overwriting memory. If you overwrite a declared value in memory, the result will be an memory exception, the application will crash.
The second point is, that a wrong declaration my force windows to use address space what is not addressable by 32 Bit applications. In that case you doesn't get a valid value back.
To avoid both options, you have to take care about the correct declarations, otherwise you do not have any control, what windows is doing, it may work or even not.
If the libraries are compiled for Net 4.x Framework, it may be an option to reinstall / repair the Net Framework, but seldom seen issues with the 4.x version.
I am getting Runtime Error 91 at the bolded line in Module1 code above.I would assume, also the PDF files are existing in the Project Path, right?
ASKER
Thanks Bembi for such a detailed response, I tested the updated declaration code given by you but I am getting a Compile error: Ambiguous name detected LoadLibrary on the following line of code:
Note: I have tested the code on good machine.
Since I still have to get access to the machine remotely to debug further.
As I mentioned it to @Martin Liss earlier that I tested this code on a new machine with Office 365 (Access 32 Bit) and same .Net Framework as the machine with error and the code runs without any issue...this is what making me confuse...apart from obvious my lack of knowledge on the inner workings of windows APIs...
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Note: I have tested the code on good machine.
Since I still have to get access to the machine remotely to debug further.
As I mentioned it to @Martin Liss earlier that I tested this code on a new machine with Office 365 (Access 32 Bit) and same .Net Framework as the machine with error and the code runs without any issue...this is what making me confuse...apart from obvious my lack of knowledge on the inner workings of windows APIs...
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
ASKER
Thanks @Bembi, appreciated your feedback...I will follow your suggestions and post back my findings.