简体   繁体   中英

Excel VBA C++ .dll

First post here. I'm trying to follow the numerous tutorials out there for compiling a C++ dll as an Excel function and running it as an Excel function, but can't seem to get it to work. I'm running Windows 10 64-bit, Visual Studio Community 2017, and Excel 2016 64-bit.

I've followed the tutorials out there. I started a new project as a "Windows Desktop Wizard", and created an empty project as a DLL. This is my code below. There are only these two files, in the "Source Files" folder under my project.

funct.cpp:

double __stdcall squareFxn(double x) {
    return x * x;
}

This is my Def file, defFile.def:

LIBRARY "square"
EXPORTS
squareFxn

In the project properties, I made sure to set the Platform to x64 in the configuration manager, and added "defFile.def" without quotes to Linker/Input/Module Definition File.

It compiled fine. I put the following into VBA:

Declare PtrSafe Function squareFxn Lib "C:\MyPath\square.dll" (ByVal x As Double) As Double

When I debugged in Visual Studio, and ran in an Excel cell:

=squareFxn(5)

Visual studio is saying that x is an extremely small number (6.234E-310) and the function is returning zero.

The other problem I'm having is when I try to do this as a reference, with the appropriate changes (squareFxn(double &x) in funct.cpp and ByRef instead of ByVal in the VBA function declaration), I'm getting a read access error. I tried running Excel as an administrator, to no avail.

Does anybody know what's going on here? Any help would be greatly appreciated!!

You might need a wrapper function in VBA in order to cast the Variant (14 bytes) representing a cell to a Double (8 bytes). At least, this works in my situation: VSE2017, x64 DLL-build together with XL2016x64. For example:

in CPP:

extern "C" __declspec(dllexport) double __cdecl myCPPfunc(double x)
{
    return some_double_expression;
}

in VBA:

Public Declare PtrSafe Function myVBAfunc Lib "complete_path_to_my.DLL" Alias "myCPPfunc" (ByVal x As Double) As Double

Function WS_myVBAfunc(ByVal x#)
Dim result#
result = myVBAfunc(x)
WS_myVBAfunc = result
End Function

You would also want to modify WS_myVBAfunc so that it accepts and returns an entire range of cells. This speeds up the whole process considerably.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM