Access .dll library MODULE function in Excel (VBA) - vba

I have a library called PIT_math_tools (written in vb.net) containing math functions which is split up into different modules.
In this case, the function I want to access is located in a Module called geometry_ellipsen_module:
Namespace geometry_ellipsen
Public Module geometry_ellipsen_module
...
Public Function calc_distanz_ellipse_kreis(...) As Double
Now I want to access the Function calc_distanz_ellipse_kreis() in VBA.
I used the following declare statement to accomplish this:
Private Declare PtrSafe Function calc_distanz_ellipse_kreis Lib "C:\Users\path...\PIT_math_tools.dll" (...) As Double
So far, everything looks fine.
When trying to call that function, however, I get runtime error '453'
"DLL-Entry Point calc_distanz_ellipse_kreis in 'PathToLibrary' not found."
When using the function in other .Net code, it could be found either by using the prefix
PIT_math_tools.geometry_ellipsen.geometry_ellipsen_module.calc_distanz_ellipse_kreis()
or an import statement identical to the prefix above.
Based on that, I tried extending the Function name in the Declare Statement by the same prefix:
Private Declare PtrSafe Function geometry_ellipsen.geometry_ellipsen_module.calc_distanz_ellipse_kreis Lib ...
However, this results in a compiler error "Expected: Lib".
How do I get the vba code to find the function inside the library module?
Thanks in advance.

The VBA syntax...
Private Declare Function SomeMethod() Lib "Some.dll"
... is used to prototype standard Win32 DLLs, e.g. Win32 API. Which .NET DLLs (aka "Assemblies") are not.
What you need to do in VB.NET is to make that assembly COM-visible. VB.NET creates a typelib (*.tlb) for the assembly.
In VBA you then add a COM reference (point to that typelib) to your project like you would do with other COM DLLs (ADODB, MSXML etc.). And then you do your standard
Dim myObject As Namespace.ClassName
Set myObject = New Namespace.ClassName
With myObject
.ThisProperty = 123
Dim lRet As Long
lRet = .ThisMethod("abc")
End With

Related

vba Run-time error '429': ActiveX can't create object, with user defined vb.net dll (VB.NET 2017, Excel 2016)

I have written a simple dll in VB.NET 2017, and I am trying to call it from VBA (Excel 2016). I have searched through Stack Overflow and MSDN, but despite many hits for this VBA error, I cannot find information related to a user defined dll that solves this particular problem.
I checked the box for the Register for COM Interop option when compiling the dll. I also verified that the Make assembly COM-Visible box was also checked.
Compilation was successful, and I was able to find my library (called TestLibrary2) in References inside the VBA editor. The class I created in it is called TestVBNET. I checked TestLibrary2 to include it in VBA, and then attempted to run the following code in VBA:
Public Sub mySub()
Dim myTest2 As TestLibrary2.TestVBNet
Set myTest2 = New TestLibrary2.TestVBNet
End Sub
When I ran the sub, I got the pop-up dialog with message: Run-time error '429': ActiveX can't create object
Based on what I have read on MSDN and other sites, the expected result is that the TestLibrary2.TestVBNet object should be instantiated successfully.
The code below is the VB.NET code that I compiled to the dll. The GUID's were generated using guidgen at the Windows 10 command prompt.
Imports System.Runtime.InteropServices
<Guid("2CEBF80D-D5FC-4C52-BCF1-E2F076318240")>
Public Interface ITestVBNet
Function addTrig(x As Double, y As Double) As Double
End Interface
<Guid("60983277-A724-4CDD-8ACE-B94CF9546F43")>
<ClassInterface(ClassInterfaceType.None)>
Public Class TestVBNet
Function addTrig(x As Double, y As Double) As Double
Return Math.Sin(x) + Math.Cos(x)
End Function
End Class
Any help and or references would be greatly appreciated. Thanks in advance.
EDIT (per comments below): I compiled the dll as admin, which in fact was required for the Register for COM Interop option to run. I also tried using regasm -- also as admin -- as follows, in the same directory as the compiled dll:
regasm /codebase /tlb TestLibrary2.dll
The following was returned:
RegAsm : warning RA0000 : Registering an unsigned assembly with /codebase can cause your assembly to interfere with other applications that may be installed on the same computer. The /codebase switch is intended to be used only with signed assemblies. Please give your assembly a strong name and re-register it.
Types registered successfully
RegAsm : error RA0000 : An error occurred while saving the exported type library: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
I apologize for being a newb here with respect to registering COM libraries, but what this seemed to indicate was the dll was registered successfully, but could not be transferred to the GAC. It was my intention not to transfer it. When I tried loading it in VBA, the same error as above occurred.
It turns out that the above code compiled to a dll that was indeed callable from a C# client. The problem with VBA, however, was that I neglected to put Implements ITestVBNet following the derived class declaration. In VB.NET, though, in addition to this, one must also explicitly indicate function overriding in the derived function declaration as well; viz (scroll all the way to the right to see the entire line),
Public Function addTrig(x As Double, y As Double) As Double Implements ITestVBNet.addTrig
By replacing the derived class above with the following, I was able to create an instance of the TestVBNet object in VBA and call the addTrig(.) method successfully:
<Guid("60983277-A724-4CDD-8ACE-B94CF9546F43")>
<ClassInterface(ClassInterfaceType.None)>
Public Class TestVBNet
Implements ITestVBNet
Public Function addTrig(x As Double, y As Double) As Double Implements ITestVBNet.addTrig
Return Math.Sin(x) + Math.Cos(x)
End Function
End Class

Import Delphi dll in vba

For a project, I need to import a DLL made in Delphi and call some functions.
However, nobody in the projectteam knows how to get this done. Our company supervisor made a program in C++ to open the DLL and call the functions, but he has not the experience in VBA.
Our project is to call the functions and pass some parameters from an excel worksheet to a program (Gas turbine Simulation Project). Our first question is: How do we load a Delphi dll in VBA? I read about the function dllimport, but still i don't know how to use this function.
For example, within the dll there is a function: d4868activateLog
The code in Delphi is as followed:
function activateLog (const filename: PAnsiChar):Integer;
How do we call this function?
You cannot call that function from VBA since it uses the register calling convention. VBA can only import stdcall functions.
You could change the Delphi code to:
function d4868activateLog(const filename: PAnsiChar): Integer; stdcall;
And then in the VBA you would write:
Private Declare Function d4868activateLog Lib "mydll.dll" (ByVal filename As String) As Long

Difficulty Registering/using VB .Net DLL for use in VBA/Com Interop

I have created a library I want to be able to share with colleagues, containing functions they can access from the VBIDE within MSOffice applications. I am using Visual Studio Express 2010, so I haven't been able to get the IDE to automatically register the DLL - instead, I have used RegAsm.exe. After several hours of desperate Googling, I finally managed to get the DLL (TLB) to appear in the VBIDE references menu. Whilst I have lots of classes in the DLL, I only exposed one as a ComClass:
<ComClass(RandomDemographicData.ClassId, RandomDemographicData.InterfaceId, RandomDemographicData.EventsId)> Public Class RandomDemographicData
Public Const ClassId As String = "05DC232D-D584-4739-8DDE-6FCA997EDC0C"
Public Const InterfaceId As String = "8FBD540B-3884-4585-9C90-47E42666FB63"
Public Const EventsId As String = "736CDFDC-D240-4DC7-9BE6-9167054221ED"
Public Function aName() As String
Return "Hello World"
End Function
End Class
Then I called it in VBA with:
Sub fgjhfh()
Dim f As New RandomDemographicData
Debug.Print f.aName
End Sub
But I get error "'-2147024894 (80070002)': Automation Error: system cannot find the file specified". I seem tantalizingly close to my goal, but can't quite make it - is anyone able to help?
EDIT:
The RegAsm command I used was "RegAsm.exe MyVBALib.dll /tlb:MyVBALib.tlb /codebase following advice found in the last post here. I have also made a copy of RegAsm.exe in the folder containing the DLL

What is a public object module in VBA?

I'm trying to get as close to function pointers / abstract classes as I can in VBA.
I have a class called VerificationManager and verifies a bunch of cells in a couple of spreadsheets match up. This will be done in different ways depending on the information and spreadsheets being used with it.
I'd like to be able to make the code reusable by specifying a method to be called in a string using the Application.Run function. So I can rewrite the function that changes.
Now if I was using Java or C# I would be able to extend an abstract class and rewrite the internals to the function. If I was using JavaScript I could store a function in a variable and pass the variable to the class and call it from there.
Inside my class I have a public property called "verificationModule" which I set to the name of the function I want it to call.
Sub VerifyWorkLocations(empLoc As EmployerLocation)
...
For i = 0 To empLoc.numOfEmp
Application.Run verificationModule, empLoc.taxdescmatch, empLoc.employees(i)
Next i
...
End Sub
However, when I try to call Application.Run I receive the following error:
Compile Error:
"Only user-defined types defined in public object modules can be
coerced to or from a variant or passed to late-bound functions"
I already tried placing my User Defined Types in a Class Module but it basically said that a class module was the wrong place for a type.
The error comes from full-fledged VB, where you can create an ActiveX dll project, create a public class there and put a UDT into that class.
In VBA, you use classes instead of UDTs when you need to coerce to or from a variant.
So just declare a class with all the fields you have in your UDT, and delete the UDT.
Alternatively, create a DLL in VB6 that would only contain the declaration of the type, and reference that dll from VBA. Or, if you're comfortable with IDL, just create a TLB file directly.
To add a module to a VBA application, try the following steps (assuming you've already entered the VBA IDE):
From the Project Explorer, right-click on your project.
Click on "Insert..."
Select "Module."
If no modules exist, a new folder within the VBA/Excel project will be created, named "Modules," and a module with a default name of "Module1" will be created.
Double-click the module to open it in the source editor.
This is where you have to place UDT's. I believe this is because of the difference in the way such types are stored internally by VBA relative to the COM-style structure of elements/objects declared/manipulated as Classes...

Calling Unmanaged DLL from VB

I'm having some trouble finding the syntax for making function calls to unmanaged DLLs in VB.NET. Is anyone familiar with this?
Let's just assume there's a function "Connected" in unmanaged DLL "Connector.DLL". I want to call this function by creating an abstract function call to it.
I've seen some code out there that looks something like
[DllImport("Connector.DLL")]
Public Shared Function Connect(ByVal intPort)
But that syntax doesn't work for me.
Try the following code.
Public Declare Function Connect Lib "Connector.DLL" (<MarshalAs(UnmanagedType.I4)> ByVal intPort As Integer) As Integer
In Visual Studio, add a reference to this Dll.
In Code:
Dim vr as new COMDllClass()
vr.FunctionInDll()
EDIT per comment:
Try this code:
<DllImport("Connector.DLL")> _
Public Shared Function Connect(ByVal intPort)