I'm trying to build an ATL COM with a c++ class and add it to excel by automation. I found some guides but I have many problems, one is that my dll donesn't compare in automation and if I try to add it excel says there's a problem about not contain a server or there aren't permissions. Could someone give me a guide? I'm using Visual Studio 2012. Thanks.
ATL COM to add a function to excel
2.4k Views Asked by The Newbie Toad At
2
There are 2 best solutions below
2
Govert
On
Making a COM Automation Add-In is not the best way to add user-defined functions to Excel - it is slow and has various limitations. Better is to make an .xll add-in based on the native C API (http://msdn.microsoft.com/en-us/library/office/bb687883.aspx). If you are using C++ there are a number of toolkits that help a lot (using only the SDK is not so easy). You might like to have a look at:
- XLW - an open source wrapper for the API that's the standard starting point
- Keith Lewis's xll library - uses modern C++ paradigms, with a nice variety of example projects.
- XLL+ - a highly regarded commercial toolkit, with various advanced features like async functions and ribbon integration.
If you prefer to use a managed language, like VB.NET, C# or F#, you should use the open--source Excel-DNA library which allows the integration of .NET with Excel using the C API, and also has various advanced features.
Related Questions in C++
- How to immediately apply DISPLAYCONFIG_SCALING display scaling mode with SetDisplayConfig and DISPLAYCONFIG_PATH_TARGET_INFO
- Why can't I use templates members in its specialization?
- How to fix "Access violation executing location" when using GLFW and GLAD
- Dynamic array of structures in C++/ cannot fill a dynamic array of doubles in structure from dynamic array of structures
- How do I apply the interface concept with the base-class in design?
- File refuses to compile std::erase() even if using -std=g++23
- How can I do a successful map when the number of elements to be mapped is not consistent in Thrust C++
- Can std::bit_cast be applied to an empty object?
- Unexpected inter-thread happens-before relationships from relaxed memory ordering
- How i can move element of dynamic vector in argument of function push_back for dynamic vector
- Brick Breaker Ball Bounce
- Thread-safe lock-free min where both operands can change c++
- Watchdog Timer Reset on ESP32 using Webservers
- How to solve compiler error: no matching function for call to 'dmhFS::dmhFS()' in my case?
- Conda CMAKE CXX Compiler error while compiling Pytorch
Related Questions in EXCEL
- Power Query / M Code, extract a list of tables into one main table, some column headers same but some different and in different order (and in row 2)
- Is there a way to validate the cell format (from excel) to fetch the symbol from it (in Java)?
- Excel - Visual Basic, macro with autofill "1"
- Getting Run-time error '13': Type Mismatch using .Find
- Getting website metadata (Excel VBA/Python)
- Excel Code Editor doesn't work (blank window)
- How to find out how many of each 2, 3 and 4 required to fit in 100 using excel?
- How would I apply a rather complex summation formula like this in Excel?
- Removing a Button from Customized Excel Ribbon
- Excel - Update Item Description Based on Accessories Ordered with It
- select duplicates from data based on another column
- How to use VBA to bold just some text
- VBA Code to filter and get values from csv to excel worksheet
- Look up max alpha numeric value
- Azure Batch for Excel VBA
Related Questions in COM
- How to program a COM object with an IEnumerator, IEnumerable interface inside
- WinAPI - right mouse drag & drop and IContextMenu
- Function Returning Excel COM Objects Unexpectedly
- Windows ContextMenuHandler names - Document conflict?
- How to publish a console application with COM interop and trim unused code
- IContextMenu Handler - Should ShellExecute or CreateProcess be used to InvokeCommand?
- Windows Explorer Conditional Context Menu Item for Drive?
- How do I fix an error while trying to send email using Outlook with COM?
- ITypeLib2.GetLibStatistics() always throws AccessViolationException in C#
- Directwrite is not always able to query font
- How can I pass a C++ struct to a C# DLL method using COM interop
- VBA PowerPoint Run-time error '-2147467259' (80004005): Presentation.Close: Failed
- PHP using a dll with COM + dotnet
- d3d11 triangle rendering failure despite everything being properly initialized
- COM context menu InvokeCommand not being called
Related Questions in ATL
- Reading / Enumerating registry path fails "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Country/region List"
- cmake set UseOfAtl for visual studio generated files
- VS2022 - Enabling C++ Language Standard 20 and using CComPtr gives Cannot Convert error?
- How to implement using COM interface in Communication between NET and C++
- Missing base class in ATL COM+ Component class declaration generated by Visual Studio
- Which code page is used for the implicit conversion of CStringA to CStringW?
- Consume C++ COM class from Python
- Does ID2D1DeviceContext::GetTarget() create a new pointer via AddRef()
- Getting compile error in atlbase 'GetThreadLocale': identifier not found
- CSimpleString::SetLength() Exception in Visual C++ Windows Service
- Figuring out %VCToolsVersion% without VsDevCmd.bat in new(ish) Visual Studios
- Access violation in CoCreateInstance creating a COM Object
- ATL project not compiling in C++ 20 standard in VS2019
- ATL project pushbutton color change
- nvwgf2umx.dll CComPtr Crash Sometimes
Related Questions in ATLCOM
- Converting CString to UTF-8 with CT2CA is corrupting some characters
- images not working properly if I open it from my shell namespace extension folder
- in my shell namespace extension context menu differs from the default one("new" and "properties" items are missed)
- How to fix "The Project needs to include ATL support" in Visual Studio 2019 C++?
- Duplicate entries of ENUM in two COM components
- C++ dynamic_cast with a C# com visible object
- Debugging a debug C++ COM dll with pdb but without source code
- ATL COM to add a function to excel
- Closing timers handle from the working thread
- How to use ATl COM from a windows service
- Regarding SafeArrayPutElement
- VS 2008 atlcom.h ClassesAllowedInStream not defined (cannot convert parameter)
- ATL: Can't remove a method from a COM interface - ALWAYS reappears like magic
- How to create anonymous IDispatch functions with ATL?
- How to generate a 64 bit COM Proxy
Trending Questions
- UIImageView Frame Doesn't Reflect Constraints
- Is it possible to use adb commands to click on a view by finding its ID?
- How to create a new web character symbol recognizable by html/javascript?
- Why isn't my CSS3 animation smooth in Google Chrome (but very smooth on other browsers)?
- Heap Gives Page Fault
- Connect ffmpeg to Visual Studio 2008
- Both Object- and ValueAnimator jumps when Duration is set above API LvL 24
- How to avoid default initialization of objects in std::vector?
- second argument of the command line arguments in a format other than char** argv or char* argv[]
- How to improve efficiency of algorithm which generates next lexicographic permutation?
- Navigating to the another actvity app getting crash in android
- How to read the particular message format in android and store in sqlite database?
- Resetting inventory status after order is cancelled
- Efficiently compute powers of X in SSE/AVX
- Insert into an external database using ajax and php : POST 500 (Internal Server Error)
Popular # Hahtags
Popular Questions
- How do I undo the most recent local commits in Git?
- How can I remove a specific item from an array in JavaScript?
- How do I delete a Git branch locally and remotely?
- Find all files containing a specific text (string) on Linux?
- How do I revert a Git repository to a previous commit?
- How do I create an HTML button that acts like a link?
- How do I check out a remote Git branch?
- How do I force "git pull" to overwrite local files?
- How do I list all files of a directory?
- How to check whether a string contains a substring in JavaScript?
- How do I redirect to another webpage?
- How can I iterate over rows in a Pandas DataFrame?
- How do I convert a String to an int in Java?
- Does Python have a string 'contains' substring method?
- How do I check if a string contains a specific word?
I will give a simple example of how to create a c++ ATL/COM dll that will be referenceable in Excel's vba. The dll will expose to the VBA a ATL/COM object and this object will have a method that will be able to take a double from excel/vba, multiply it by 2.0 and output it to the VBA. The VBA code will be usable to define a excel function. Of course, no need to resort to a c++ dll for having an excel function mutiplying the content of a cell by two, but it is just for the demonstration.
Last remark before start : better run visual studio (called mvs for short throughout this answer) as admin for all of this. All versions of mvs from 2005 included work for this.
Let us start. open your favourite mvs, create a new project : choose the template "ATL project" in the Visual c++ template project types list. Name it "MyATLProject", and choose to save it in "C:\Users...\Desktop" for instance. Click ok. This will open a new window. Do not click there on finish, but on next : now check that only "dll" is checked, and if so, click on finish. (Of course for our basic need we need nothing more here.
All we have done has created a solution (in "C:\Users...\Desktop\MyATLProject", I call $(SOL) this path.) with two projects in it : MyATLProject & MyATLProjectPS. The PS ended project (PS stands for proxy/stub) is useless for what we want to do, but anyway. We will do everything here in debug. Do a rebuild solution. (You'll note that MyATLProjectPS has been skipped from rebuid : this is normal.) Now you could see that a folder $(SOL)\MyATLProject\debug has been created, with various files in it, the one of interest to us being MyATLProject.dll --> this file is the one we will have to reference in the VBA and that we expose us objects and methods. For now, it would expose nothing to us in the VBA, for we haven't yet implemented any ATL/COM object, a fortiori nor any method.
Now, let us create an ATL/COM object. There is a hard way for this and a soft way, I will only show the soft way. Right click on the "MyATLProject" project in the solution explorer, then "add", then "class", and in categories choose "ATL" and then "ATL simple object". Then click on "add". In simple name put "MyATLObject" and click finish. (Here again we could do more, but for such an intro, we don't need more.) This will create and open a "MyATLObject.h" file. MyATLObject.cpp has also been created, and MyATLProject.idl (present at the project generation) has been modified. This three files are the holy trinity for what we intend to do. Do a rebuild all for sake's sake. ;-) An ATL/COM object MyATLObject, without any methods for now, has been created. You could see it the VBA if you would reference the dll there, but be patient, we will do it later.
Now, let us give a method to this object. There is a hard way for this and a soft way, I will show you both, starting with the hard one first. First modification. Go in MyATLProject.idl and replace
by
What have we done ? The idl file "references our
MyATLObject" (I am voluntarily vague) (as well as other objects/interfaces if needed), and we specify in it that ourMyATLObjectwill have a method calledMULT, method that will take a reference (pointer to) a double. As you may guess,MULTwill multiply by 2.0 the double pointed to. Now, we have to modify accordingly MyATLObject.h and MyATLObject.cpp. Second modification : go to MyATLObject.h and replaceat the end of it by
What have we done ? We have declared the method
MULTin the class, as we would have done it for a class in "vanilla" c++. Third and last modification : go to MyATLObject.cpp and afteradd
S_OKis of typeHRESULTand tells by return if ourMULTmethod finished well or not. (No need to be more verbose here for what we plan here.) Now we have to implement theMULTmethod really, like this for instance (I am voluntarily ugly and unsafe here, you'll fashion the stuff yourself later) :Rebuild solution. The ATL/COM object
MyATLObjecthas been now updated to have a methodMULTnow. This was for the (not very in fact) hard way of adding a method. The soft way is by using the wizard : undo all three modifications we did and rebuild, so that we are now at the same stage as the one we were in when we were about adding the MULT method. Go to class view, expand MyATLProject, right click on the interfaceIMyATLObject(the one with the handle icon, the icon looking like a little key), click on "add", and then "add method". This opens the add method wizard. PutMULTin method name, chooseDOUBLE *in parameter type, and "theDouble" in the parameter name. The fact the our parameter is a pointerDOUBLE *will give us access to the out and retval parameter attributes. Click "in" and "out". Then click on add, and then on finish. This will recreate all what we did by hand (forMULTonly, and without its implementation of course) before. Add theline in the implementation of the MULT method in the MyATLObject.cpp file.
Warning : depending on the mvs version, by experience, it may happen that everything is recreated well except the idl file part, check it, and if this is the case, do it by hand as we did it in the first place, during the hard way.
Now, it is time to use our ATL/COM c++ dll in the VBA of excel. Pick your favourite excel version, and create a spreadsheet (in xlsm format for earlier excel versions and in xls for late version, because we will need macros) called MyATLProjectTEST.xls. Make sure to enable the use of all macros. (How to do it varies with excel's version, but you'll find how to do it with your friend google.) Alt+F11 to open VBA. Click on tool, references, browse to your MyATLProject.dll and click to add a reference to it. (To be safe, maybe regsvr32 the dll before --> this is explained everywhere on the internet, google is your friend again on this.) Insert a module, it will be automaticaly called Module1. In it, code :
Now go in a sheet of the spreadsheet, put
3.14159in cell B2 let's say, and put formulain cell B3, and enjoy the result.
Remark : try to build to solution in mvs while the spreadsheet is open : you'll have a
Make sure that the file is not open by another process and is not write-protected. MyATLProject
error. This is because the dll is referenced (used) in the VBA, who "owns" it somehow, empeaching mvs to modify (recompile) it. At each code modification, you'll have to close your spreadsheet for building/rebuilding. The demo is over.
Now, the "fun" part, the debug session. Rebuild the solution, reopen the spreadsheet and rereference the dll in it if needed. Put a breakpoint on the line
Do a ctrl+alt+p (or "debug" and then "attach to process") in mvs, choose the excel spreadsheet in the list and wait a bit to have access to your spreadsheet again (let the symbols load, in fact). Now open the VBA and put a breakpoint at the line
Now go to cell B3, and recalculate it. You will break in the VBA at the specified line, and if you step into (F8) you will break at the
line in MyATLObject.cpp.
Some last remarks.
1)
DOUBLE *even if it works is not the right way to pass info from vba to c++ and from c++ to vba, for the following simple reason : you sell your dll and vba code to someone, and he puts a string LUDWIGVONMISES in B2 instead of putting a number. What would happen ? An error : constated in a "not-debug" mode that you'll have to track in debug to see where it happens. Why ? Because you do not handle error at all. For handling them, you should passVARIANT *between c++ and VBA, and operate in c++, at the beginning of your MULT method for instance, to check that theVARIANT *pointer passed toMULTpoints to aVARIANT"wrapping" adoubleand not astring.2)
Being extremely focused on execution time for the code I am working on and delivering, and having developped a lot of ATL/COM dll's for excel/VBA, as well as xla/xll using the excel sdk, I do not agree at all with this statement from Govert. What could we say about the small demo above ? We have entered in the c++ when we enter in the MULT method, and our calculation (multiplication by two) was done inside the method. This was quick, but imagine that the calculation that was done was something extremely intensive numerically, or in memory terms. We could be stupid and doing it in our ATL/COM method, but we could deport the calculation outside our method, in plain c++. This would be the quickest thing to do, and afaik, it is the only reasonable way to do it. Same thing if you want to use the excel sdk, for producing excel functions directly, without wrapping ATL/COM methods in VBA code to produce these excel functions yes. Here you could say : hey, the xll option using the excel sdk is then better, because I do not loose wrapping time. Maybe, but wrapping time is really not that big, and with ATL/COM, you have VBA with you, where you could use ATL/COM object in quite an elegant fashion, and you can use it to generate com object etc etc. You can even access excel memory to instantiate object there through excel functions coded by wrapping ATL/COM method in VBA ! Moreover, any such ATL/COM dll is referenceable in c# project, and usable there in the same way that you use it in VBA. Even in java. ;-) This is not the case of any xla/xll coded with excel's sdk, like the solutions Govert is advertising for. Serious lack of reusability concern.
3) The OP wants to use ATL COM to do something which is perfectly doable with it, and Govert tells him that ATL/COM is too slow - which is false - and to use something else. For this I should downvote Govert's answer. ;-)