1. Excel
- Posted by Mike777 <anon4321 at gm?il.c?m> Jan 07, 2008
- 1713 views
- Last edited Jan 08, 2008
I figured this time I would ask first! Has anybody a good link/reference for building a DLL that can function as an Excel Add-in? Not critical. Not rush. Just something I have my sights set on. Thanks Mike
2. Re: Excel
- Posted by Michael J. Sabal <m_sabal at ??hoo.com> Jan 07, 2008
- 1685 views
- Last edited Jan 08, 2008
How much functionality are you looking for? I have a lib that can read documents saved in 97/2K/XP format, and one that can save sequences into HTML tables with an xls extension (hey, it works for the most part). I only needed the most minimal feature set, so I haven't gotten around to completing it. If you're interested, I can email you off list. Michael Sabal
3. Re: Excel
- Posted by Matt Lewis <matthewwalkerlewis at ?ma?l.com> Jan 07, 2008
- 1735 views
- Last edited Jan 08, 2008
Mike777 wrote: > > I figured this time I would ask first! Has anybody a good link/reference for > building a DLL that can function as an Excel Add-in? Not critical. Not rush. > Just something I have my sights set on. I suspect that your dll needs to be an ActiveX object, which implies a lot of overhead. There are probably templates that can be used from C++ or maybe some .NET language, but I'm not aware of anyone building an ActiveX object in euphoria. I think it's possible, but would be very difficult, at least the first time. Matt
4. Re: Excel
- Posted by Mike777 <anon4321 at gm?il.com> Jan 08, 2008
- 1700 views
Appreciate the offer, but I was thinking more along the lines of a classic excel add-in. Something that would allow my to type something like: =myfunction(cell1, cell2, cell3) and then have it do its magic. Magic in this case is something that is not written in VBA (although it certainly could be) but instead is compiled into an excel add-in and exposes the functions therein to the excel cells. Mike
5. Re: Excel
- Posted by Mike777 <anon4321 at g?ail.co?> Jan 08, 2008
- 1710 views
Matt Lewis wrote: > > Mike777 wrote: > > > > I figured this time I would ask first! Has anybody a good link/reference for > > building a DLL that can function as an Excel Add-in? Not critical. Not > > rush. > > Just something I have my sights set on. > > I suspect that your dll needs to be an ActiveX object, which implies a lot > of overhead. There are probably templates that can be used from C++ or > maybe some .NET language, but I'm not aware of anyone building an ActiveX > object in euphoria. I think it's possible, but would be very difficult, > at least the first time. I'm not sure I need to go the ActiveX route. My understanding is that you only need/want ActiveX is you want to go outside of the Excel framework. For example, if you want to write to or read directly from the file system. If all you want to do is memory bound, I think an Add-in can be compiled as a special form of DLL. I remember some KB articles on it the last time I looked, which was quite a while ago (I told you it wasn't a rush!). Now that I've at least posted here, I'll see if I can't find something that lays out the requirements as far as how the DLL has to be built. Mike
6. Re: Excel
- Posted by Greg Haberek <ghaberek at ??ail.com> Jan 08, 2008
- 1689 views
Mike777 wrote: > > I'm not sure I need to go the ActiveX route. My understanding is that you > only > need/want ActiveX is you want to go outside of the Excel framework. For > example, > if you want to write to or read directly from the file system. If all you > want > to do is memory bound, I think an Add-in can be compiled as a special form of > DLL. I remember some KB articles on it the last time I looked, which was > quite > a while ago (I told you it wasn't a rush!). Now that I've at least posted > here, > I'll see if I can't find something that lays out the requirements as far as > how the DLL has to be built. Writing an Office Add-in is tough at best. I wrote one for Outlook in VB 2005 Express (.NET) and it was rather hairy. Lots of .NET and/or COM code is required. I think it may be possible with EuCOM, but Microsoft abstracts so many things, I wouldn't know where to begin. -Greg
7. Re: Excel
- Posted by Juergen Luethje <j.lue at ??x.de> Jan 08, 2008
- 1714 views
Greg Haberek wrote: > Mike777 wrote: > > > > I'm not sure I need to go the ActiveX route. My understanding is that you > > only > > need/want ActiveX is you want to go outside of the Excel framework. For > > example, > > if you want to write to or read directly from the file system. If all you > > want > > to do is memory bound, I think an Add-in can be compiled as a special form > > of > > DLL. I remember some KB articles on it the last time I looked, which was > > quite > > a while ago (I told you it wasn't a rush!). Now that I've at least posted > > here, > > I'll see if I can't find something that lays out the requirements as far as > > how the DLL has to be built. > > Writing an Office Add-in is tough at best. I wrote one for Outlook in VB 2005 > Express (.NET) and it was rather hairy. Lots of .NET and/or COM code is > required. > I think it may be possible with EuCOM, but Microsoft abstracts so many things, > I wouldn't know where to begin. Maybe writing a Eu wrapper for DispHelper <http://disphelper.sourceforge.net/> would be a good starting point. Just an idea ... Regards, Juergen -- There are two ways of constructing a software design: One way is to make it so simple that there are /obviously/ no deficiencies and the other is to make it so complicated that there are no /obvious/ deficiencies. [C.A.R. Hoare (1987), The Emperor's Old Clothes]
8. Re: Excel
- Posted by Matt Lewis <matthewwalkerlewis at gmail.c?m> Jan 08, 2008
- 1746 views
- Last edited Jan 09, 2008
Juergen Luethje wrote: > > Maybe writing a Eu wrapper for DispHelper > http://disphelper.sourceforge.net/ > would be a good starting point. Just an idea ... I don't think so. It looks like a C/C++ analog to EuCOM, but wouldn't help you to make COM objects from euphoria code. I think that the simplest way to do that might be to write a regular euphoria dll, and then wrap it with the ActiveX object written in C++ or something. Matt
9. Re: Excel
- Posted by Alan Oxley <alan.oxley at ??indigo.com> Jan 09, 2008
- 1687 views
Possibly there is no need for complex .NET etc. If the XLS files that you wish to write to using Euphoria, are used only by yourself, you can ensure that the XLS type is known and unchanging. And therefore no problem. There are examples in the archive for Eu writing XLS, I have used successfully myself. HTH! Regards Alan
10. Re: Excel
- Posted by Mike777 Feb 04, 2009
- 1755 views
I figured this time I would ask first! Has anybody a good link/reference for building a DLL that can function as an Excel Add-in? Not critical. Not rush. Just something I have my sights set on. Thanks Mike
It has been a while since I asked the above question, so I figured I would ask again. Still have my sights set on doing this someday. Maybe somebody who wasn't around a year ago has something they can add to this discussion.
I'm not looking for anything other than a simple template, but I do need to develop something that would be compatible with old versions of Excel , like Excel 97.
So that new readers don't need to read the entire thread, I'll summarize:
I'm not looking for an activex object, just a "simple" add-in. .net shouldn't enter the discussion, as it doesn't apply to an add-in of this kind. What I'm looking for is the ability to put a simple call in an excel cell like =myfunction(a1,a2,a3) such that myfunction runs some euphoria compiled code using the values found in a1, a2 and a3.
Always optimistic,
Mike
11. Re: Excel
- Posted by Mike777 Feb 04, 2009
- 1787 views
- Last edited Feb 05, 2009
I figured this time I would ask first! Has anybody a good link/reference for building a DLL that can function as an Excel Add-in? Not critical. Not rush. Just something I have my sights set on. Thanks Mike
It has been a while since I asked the above question, so I figured I would ask again. Still have my sights set on doing this someday. Maybe somebody who wasn't around a year ago has something they can add to this discussion.
I'm not looking for anything other than a simple template, but I do need to develop something that would be compatible with old versions of Excel , like Excel 97.
So that new readers don't need to read the entire thread, I'll summarize:
I'm not looking for an activex object, just a "simple" add-in. .net shouldn't enter the discussion, as it doesn't apply to an add-in of this kind. What I'm looking for is the ability to put a simple call in an excel cell like =myfunction(a1,a2,a3) such that myfunction runs some euphoria compiled code using the values found in a1, a2 and a3.
Always optimistic,
Mike
I should point out that the xlw project at http://xlw.sourceforge.net/refman does almost exactly what I want, except for the not insignificant issue of it using C rather than Euphoria. I wish I understood enough about wrapping C to sub Euphoria routines for the C routines of xlw.
Mike
12. Re: Excel
- Posted by Mike777b Oct 10, 2010
- 1581 views
Well, it has been another year or so, so I thought I'd try again. I really, really have my sights set on using Euphoria rather than another language (like the C (or C# or C++?) based xlw project, which does what I want but now I find out doesn't support anything other than 32 bit architecture).
To remind folks what this thread is about, without them having to read the whole thing:
I'm not looking for an activex object, just a "simple" add-in. .net shouldn't enter the discussion, as it doesn't apply to an add-in of this kind. What I'm looking for is the ability to put a simple call in an excel cell like =MyFunction(a1,a2) such that MyFunction runs some euphoria compiled code using the values found in cells a1 and a2.
I mentioned the xlw project last year. That subsystem is intended to build an xll which can be used by Excel directly as I described. Since then, I've found another mechanism which might make what I want to implement in Euphoria easier to emulate. The Visual C++ 2008 Express Edition (freely downloadable) has a template for creating DLL's that "almost" works the way I want. Since it creates a DLL (rather than an XLL) it can't be directly called by a worksheet function, but VBA can be used to create a wrapper that will make it work the same way.
From what I've gathered (and I *have* tested it, and it works on my machine), the following code/changes are all that are necessary to create a DLL which works as described further below:
Run VC++2008EE and create a Win32 Project (which is one of the pre-installed templates).
While creating the Win32 Project, check the "DLL" box.
Add a main.cpp file and an export.def file, which contain something like the following:
main.cpp ======== //____________________________________________ __declspec( dllexport ) double MyFunction(double a, double b) { return a + b; } //____________________________________________ export.def ========== LIBRARY MyDLL EXPORTS MyFunction @1
Then change the following properties in the IDE before compiling:
1) Change the "Calling Convention" for MyDLL to "__stdcall (/Gz)" (found by highlighting MyDLL in the Solution Explorer, then selecting View|Property Pages|Configuration Properties|C/C++|Advanced - it is the first item)
2)Change the "Module Definition File" for MyDLL to ".\export.def" (found by highlighting MyDLL in the Solution Explorer, then selecting View|Property Pages|Configuration Properties|Linker|Input - it is the fourth item)
Then compile (Build|Build MyDLL).
You can move the resultant MyDLL.dll to anywhere.
In Excel, insert a Module through the VBA window (alt-F11 from the worksheet will open the VBA window) and in the Module include the following:
Option Explicit Public Declare Function MyFunction Lib "c:\MyDLLs\MyDLL.dll" _ (ByVal a As Double, ByVal b As Double) As Double Function aMyFunction(a As Double, b As Double) As Double aMyFunction = MyFunction(a, b) End Function
Then you can insert in any cell the following and excel will process it:
=aMyFunction(a1, a2)
I still think that an xll would be preferable (probably a lot faster, because I'm sure the VBA interface slows things down dramatically), but at the least I would be able to do a majority of the heavy lifting in Euphoria which has to be a lot faster than C++.
Staying optimistic.
Mike
13. Re: Excel
- Posted by ne1uno Oct 11, 2010
- 1529 views
Well, it has been another year or so, so I thought I'd try again.
it's been said the quickest way to get an answer from a forum is to first post an incorrect answer.
could try to translate with -dll option then call myfunction.dll with the VB wrapper.
public function MyFunction(atom a, atom b) atom c = a * b return c end function
I wasn't able to get VB script to link to the dll created this way, but I'm sure it can be done. the translator or eu.cfg doesn't have the ability yet to pass any/all options to the compiler so you may have to edit the default created emake.bat if required.
14. Re: Excel
- Posted by mattlewis (admin) Oct 11, 2010
- 1575 views
Well, it has been another year or so, so I thought I'd try again.
it's been said the quickest way to get an answer from a forum is to first post an incorrect answer.
Must....resist.....
could try to translate with -dll option then call myfunction.dll with the VB wrapper.
public function MyFunction(atom a, atom b) atom c = a * b return c end function
I wasn't able to get VB script to link to the dll created this way, but I'm sure it can be done. the translator or eu.cfg doesn't have the ability yet to pass any/all options to the compiler so you may have to edit the default created emake.bat if required.
One issue with this is that he wants to pass a double. Euphoria callbacks can't handle doubles being natively passed. They can only take 31-bit integers (or Euphoria Atoms or Sequences).
The desired signature is:
Public Declare Function MyFunction Lib "c:\MyDLLs\MyDLL.dll" _ (ByVal a As Double, ByVal b As Double) As Double
If you translate (I did this on Linux, but should be similar), you should get some thing like :
$ euc -makefile-full -dll vb.e // inside vb.c: int _1MyFunction(int _a_144, int _b_145) { int _c_146 = 0; int _0, _1, _2; /** atom c = a * b*/ if (IS_ATOM_INT(_a_144) && IS_ATOM_INT(_b_145)) { if (_a_144 == (short)_a_144 && _b_145 <= INT15 && _b_145 >= -INT15) _c_146 = _a_144 * _b_145; else _c_146 = NewDouble(_a_144 * (double)_b_145); } else { if (IS_ATOM_INT(_a_144)) { _c_146 = NewDouble((double)_a_144 * DBL_PTR(_b_145)->dbl); } else { if (IS_ATOM_INT(_b_145)) { _c_146 = NewDouble(DBL_PTR(_a_144)->dbl * (double)_b_145); } else _c_146 = NewDouble(DBL_PTR(_a_144)->dbl * DBL_PTR(_b_145)->dbl); } } /** return c*/ DeRef(_a_144); DeRef(_b_145); return _c_146; ; }
The easiest thing to do here is probably to write a wrapper function right below the above code:
double MyFunctionDbl( double ad, double bd ){ object a, b, c; double cd; a = NewDouble( ad ); b = NewDouble( bd ); c = _1MyFunction( a, b ); cd = DBL_PTR( c )->dbl; DeRefDS( a ); DeRefDS( b ); DeRefDS( c ); printf("MyFunctionDbl ad %f bd %f cd %f\n", ad, bd, cd ); return cd; }
And then call that. I wrote this test program to use it:
include std/dll.e constant VB = open_dll( "/home/matt/eu/test/vb.so" ), MYFUNC = define_c_func( VB, "MyFunctionDbl", {C_DOUBLE, C_DOUBLE}, C_DOUBLE ) ? c_func( MYFUNC, { 0.5, 0.25 }) ? c_func( MYFUNC, {1, 1 })
Matt
15. Re: Excel
- Posted by Mike777b Oct 11, 2010
- 1555 views
One issue with this is that he wants to pass a double. Euphoria callbacks can't handle doubles being natively passed. They can only take 31-bit integers (or Euphoria Atoms or Sequences).
The desired signature is:
Public Declare Function MyFunction Lib "c:\MyDLLs\MyDLL.dll" _ (ByVal a As Double, ByVal b As Double) As Double
It was just an example. I can live with 31 bit values if I have to (I can get a date or a value up to 21,474,836.48, right?).
If you translate (I did this on Linux, but should be similar), you should get some thing like :
$ euc -makefile-full -dll vb.e // inside vb.c: int _1MyFunction(int _a_144, int _b_145) { int _c_146 = 0; int _0, _1, _2; /** atom c = a * b*/ if (IS_ATOM_INT(_a_144) && IS_ATOM_INT(_b_145)) { if (_a_144 == (short)_a_144 && _b_145 <= INT15 && _b_145 >= -INT15) _c_146 = _a_144 * _b_145; else _c_146 = NewDouble(_a_144 * (double)_b_145); } else { if (IS_ATOM_INT(_a_144)) { _c_146 = NewDouble((double)_a_144 * DBL_PTR(_b_145)->dbl); } else { if (IS_ATOM_INT(_b_145)) { _c_146 = NewDouble(DBL_PTR(_a_144)->dbl * (double)_b_145); } else _c_146 = NewDouble(DBL_PTR(_a_144)->dbl * DBL_PTR(_b_145)->dbl); } } /** return c*/ DeRef(_a_144); DeRef(_b_145); return _c_146; ; }
The easiest thing to do here is probably to write a wrapper function right below the above code:
When you say the "above code", what do you mean? In what language is the wrapper function (I only do EU, so if it is C, I'll be stuck).
double MyFunctionDbl( double ad, double bd ){ object a, b, c; double cd; a = NewDouble( ad ); b = NewDouble( bd ); c = _1MyFunction( a, b ); cd = DBL_PTR( c )->dbl; DeRefDS( a ); DeRefDS( b ); DeRefDS( c ); printf("MyFunctionDbl ad %f bd %f cd %f\n", ad, bd, cd ); return cd; }
And then call that. I wrote this test program to use it:
include std/dll.e constant VB = open_dll( "/home/matt/eu/test/vb.so" ), MYFUNC = define_c_func( VB, "MyFunctionDbl", {C_DOUBLE, C_DOUBLE}, C_DOUBLE ) ? c_func( MYFUNC, { 0.5, 0.25 }) ? c_func( MYFUNC, {1, 1 })
This is testing whether the DLL works from EU, right? Does that necessarily translate into success if the DLL is being called from VBA within Excel?
Thanks
mike
16. Re: Excel
- Posted by mattlewis (admin) Oct 11, 2010
- 1576 views
One issue with this is that he wants to pass a double. Euphoria callbacks can't handle doubles being natively passed. They can only take 31-bit integers (or Euphoria Atoms or Sequences).
The desired signature is:
Public Declare Function MyFunction Lib "c:\MyDLLs\MyDLL.dll" _ (ByVal a As Double, ByVal b As Double) As Double
It was just an example. I can live with 31 bit values if I have to (I can get a date or a value up to 21,474,836.48, right?).
Yes, if you're certain you'll only pass integers like that, you should be fine. Bigger integers, or floats or doubles, however, and you'll need to do something like what I showed.
If you translate (I did this on Linux, but should be similar), you should get some thing like :
$ euc -makefile-full -dll vb.e // inside vb.c: int _1MyFunction(int _a_144, int _b_145) { ... snipped ... }
The easiest thing to do here is probably to write a wrapper function right below the above code:
When you say the "above code", what do you mean? In what language is the wrapper function (I only do EU, so if it is C, I'll be stuck).
Yes, that was C. It was from translated euphoria code. You can adapt the wrapper code easily to call a different function. This basic code will work for anything that takes two doubles and returns a double. Other signatures are pretty easy, too.
And then call that. I wrote this test program to use it:
... snipped...
This is testing whether the DLL works from EU, right? Does that necessarily translate into success if the DLL is being called from VBA within Excel?
It was meant just to show that it was working in general, and calling it from euphoria was the easiest way to do it. You'll have to try it yourself in VBA.
Matt
17. Re: Excel
- Posted by Mike777b Oct 11, 2010
- 1568 views
Thanks.
I know Jeremy uses Excel, he can probably run a test in much less time than it would take me. {hint, hint} Just to see whether VBA can successfully utilize a dll created in this manner.
I know this is going to sound dumb, but, in looking back on what you wrote, I don't see where the Euphoria logic that I want to apply (within MyFunction) goes.
I see that you ran a translation. But it appears the translation was just of the signature. Was it also of the simplistic code that I included? If so, does that imply that the course of action I would need to follow would be to develop the logic of the dll in Euphoria, then translate that into C, so that I could append the appropriate signature wrapper at the end, and then compile at that point?
Sorry for sounding so out of it, but I'm out of my depth here.
Thanks again.
Mike
18. Re: Excel
- Posted by mattlewis (admin) Oct 11, 2010
- 1533 views
Thanks.
I know Jeremy uses Excel, he can probably run a test in much less time than it would take me. {hint, hint} Just to see whether VBA can successfully utilize a dll created in this manner.
I've done something like this in the past, so I know that it's possible.
I know this is going to sound dumb, but, in looking back on what you wrote, I don't see where the Euphoria logic that I want to apply (within MyFunction) goes. I see that you ran a translation. But it appears the translation was just of the signature. Was it also of the simplistic code that I included? If so, does that imply that the course of action I would need to follow would be to develop the logic of the dll in Euphoria, then translate that into C, so that I could append the appropriate signature wrapper at the end, and then compile at that point?
Sorry for sounding so out of it, but I'm out of my depth here.
This message contains the translated version of the simple example (multiplying two atoms and returning the result). The first block (in the post) contains the translated version, which looks like this:
int _1MyFunction(int _a_144, int _b_145) { ...
That was simply what the translator created based on the euphoria code. My little wrapper function that I hand wrote in C is what's meant to be called by your Excel VBA code. It takes the 'native' double values, and turns them into Euphoria atoms, uses those to call your code, then releases the memory it reserved, and returns the value.
So, the basic idea here is to write your euphoria code, then translate, add the additional wrappers, and finally compile the dll so you can use it. By default, when you run the translator, it translates, compiles and cleans up after itself (deleting the c and obj files).
For this task, however, we need to edit the C files before we build it. I like to use the -makefile-full option. It translates your code, and writes out a makefile that your compiler / build system can use. When using Watcom (as I presume you are), it might look like this:
> euc -makefile-full -dll mikes_excel_code.e Translating code, pass: 1 2 3 4 5 6 7 8 9 10 11 generating 19.c files were created. To build your project, type wmake -f mikes_excel_code.mak -- do your editing here... > wmake -f mikes_excel_code.mak
And it will build your dll for you. I haven't tried this with Watcom lately, but you might need to specify this file for export by adding it to another generated file that defines all of the exported functions.
Matt
19. Re: Excel
- Posted by Mike777b Oct 11, 2010
- 1440 views
[snip..]
My little wrapper function that I hand wrote in C is what's meant to be called by your Excel VBA code. It takes the 'native' double values, and turns them into Euphoria atoms, uses those to call your code, then releases the memory it reserved, and returns the value.
I'm a little confused, but that's ok. Things are looking like it will work, so I will plow forward. One thing I'll need at some point, if you get a chance, is the C variations for different types of information which will be sent from Excel. I can see only three things: integers, strings and real numbers. I'll presume the real numbers were what your wrapper addressed and that I could probably make do with the same for integers. I have no clue on how to deal with text, though.
My confusion (one of many, of course) is based on the language of your wrapper. Where you use the lines:
a = NewDouble( ad ); b = NewDouble( bd ); c = _1MyFunction( a, b );
it doesn't seem to be consistent with: "It takes the 'native' double values, and turns them into Euphoria atoms, uses those to call your code, then releases the memory it reserved, and returns the value."
Unless, of course, NewDouble is the function for converting a double into a Euphoria atom.
Thanks again.
20. Re: Excel
- Posted by mattlewis (admin) Oct 11, 2010
- 1558 views
I'm a little confused, but that's ok. Things are looking like it will work, so I will plow forward. One thing I'll need at some point, if you get a chance, is the C variations for different types of information which will be sent from Excel. I can see only three things: integers, strings and real numbers. I'll presume the real numbers were what your wrapper addressed and that I could probably make do with the same for integers. I have no clue on how to deal with text, though.
Strings coming from VB are a little weird. They're BSTRINGs. Basically, you receive them as a pointer. The length of the string is stored in the 4 bytes previous to the value of the pointer. The data itself is stored as wide characters. Take a look at EuCOM, which has some code for dealing with these, along with arrays, which you should try to avoid (because they're a PITA). I've actually used the code in EuCOM (about 9 or 10 years ago) to write a DLL that was called by Excel. The EuCOM code was mainly used for dealing with Strings and Arrays coming from VBA.
I don't know what Excel thinks "real numbers" are, but they're probably native doubles.
My confusion (one of many, of course) is based on the language of your wrapper. Where you use the lines:
a = NewDouble( ad ); b = NewDouble( bd ); c = _1MyFunction( a, b );
it doesn't seem to be consistent with: "It takes the 'native' double values, and turns them into Euphoria atoms, uses those to call your code, then releases the memory it reserved, and returns the value."
Unless, of course, NewDouble is the function for converting a double into a Euphoria atom.
Yes, NewDouble() is the back end euphoria function that allocates a Euphoria atom that is stored as a double. In addition to the actual double, it also stores reference counting and cleanup information. The calls to DeRefDS() de-reference the objects, making sure that the memory they use is freed.
Matt