COM Automation / Running Excel Macros - automation

Possibly, my questions do not presume a simple answer as I'm asking to share a specific experience.
What kind of issues you experienced trying to execute Excel macros through COM Automation?
Are there any specific requirements for creation of macros to be run through Automation?
Can you share your experience with data (scalar and vector parameters) pass-in / pass-back for macros run through Automation?
I have tried some ideas already and it worked; but I'd like to find out if someone had gone through that way and what issues to expect - before I invest time and resources in building the framework.
Finally, I will share here results of my investigation and decision made at the end.
Thank you,
Albert Gareev

OK, this is what I have so far.
1) Issues.
Every single exit point on COM Client should have proper disconnection routine so that Excel.Application is properly shut down and released. If COM Client was executed in debugging mode, and execution was manually stopped, then shut down Excel.Application manually too (from Task Manager).
2) I currently use worksheet to pass in parameters and retrieve the results.
Additionally, for a data parsing task executed within macro I pass-in text files names. The contents is read and normalized from the Excel macro side.
Thanks.

Related

MS Access VBA editor activity affects running program variables

MS Access 2016 running on Windows 10.
I am debugging VBA changes to a MS Access application and am seeing some unexpected interactions between the VBA editor and running code. The steps are basically:
Open the application, which opens startup form.
The startup form_load instantiates an object used by other forms the user may subsequently open.
Open the VBA editor
Using the VBA editor, select a line in any code module and the instantiated objects are set to nothing.
An error is thrown when the other forms using the object are opened.
So basically, the VBA editor action has set the objects to nothing. I have added instrumenting code to confirm this.
Has anyone seen the behavior? Does anyone have thoughts about what may be happening and causing this?
Thanks in advance...
Additional information:
The code instantiating the object in the Form_Load method is:
Set musrInfo = New usrInfo
Where usrInfo is a class module containing user information.
Also, there is no problem with earlier versions of this - I have never experienced the described problem with any other MSA VBA application. The compiled version of this particular MSA file is a bit bigger than 20MB, with little in the way of data tables - only a few parameters, etc. - and more than 13MB in forms, reports, etc.
I hope this helps... Lindsay
And there's more...
- I tried this .accdb file on another PC with Win7/MSA2010 and this
behavior did not occur.
- I then tried it in a different folder on the original PC and it
did not occur.
Maybe these findings will allow a path forward, but I still wonder why this would ever happen - why would the folder choice make any difference?
This is usual behavior.
When making changes using the VBA editor, it may recompile the VB project behind your database. This can be the whole project, or parts of it, depending on the exact change.
Recompiles will clear any variables.
You can change this behaviour, by going to Tools -> Options, under the General tab. See the following screenshot.
However, even with Compile On Demand off, you will have to trigger a recompile for most changes, clearing any set variables.
For classes that need a single instance to be publicly available as long as the database is open, I recommend setting the VB_PredeclaredID to true. That will instantiate the object as soon as the database opens, or the code recompiles. See here how.

Causes for random break points unknown

This has been a long and unresolved problem with Excel VBA code that runs a repeated loop via the Application.OnTime Now + TimeSerial(x,x,x). Users will find that their code is running fine for a few days and may, or may not, mysteriously stop.
I'm facing such a situation and hoping to resolve it. I've read over 30 forum answers, some written by experienced developers, and came to this understanding. My conclusion and question follow.
The conclusion is that Excel randomly goes into a break mode but no one knows the reason why this occurs, more so, why it randomly occurs.
Shall we then conclude that in fact this randomly occurs? And that Excel VBA isn't as robust as other languages.
Some notes:
I know this can be resolved by pressing Ctrl+Break twice. It doesn't explain why we have to do it in the first place.
I realize that this error is code independent. It'll occur with both simple and involved programs.
After trying multiple ways to simulate this error, and I mean a lot - long and multiple ADODB SQL connections and queries, cell editing while macro is running, using multiple and 1 second Application.OnTime recursive calling, I can't replicate the error. It is truly random.
I'm running only one workbook and one Excel instance.
Some say, for each break point we did in the debugging, that break point remains in memory. And then when we run a macro in the future, a write to that part of memory triggers this random break. This is a plausible explanation and does conclude that this error is random. No way can we inspect memory in VBA.
I need something to go by, even if it isn't to solve this problem, to act as proof for my boss.
I've solved the bug! I've not read this answer to this problem before so it is pivotal that the Excel community receives this.
Excel fails to call its sub routines in the Application OnTime queue whenever this happens. You have started to edit a cell, stayed in edit mode, and then switched away from Excel either by minimizing the window or by clicking onto another window.
All the sub routines in the Application OnTime queue will wait until the cell is finished editing. So once you switch back to Excel, the cell switches edit mode off, and then all the sub routines will run.
I'm actually quite impressed I solved this myself.

Loading (and executing) a lisp-file in autocad using .NET

I'm currently in the process of rewriting some old AutoCAD plugins from VBA to VB.NET. As it turns out, a (rather large) part of said plugin is implemented in LISP, and I've been told to leave that be. So the problem became running LISP-code in AutoCAD from .NET. Now, there are a few resources online who explain the process necessary to do so (like this one), but all of them takes for granted that the lisp-files/functions are already loaded. The VBA-function I'm currently scratching my head trying to figure out how to convert does a "(LOAD ""<file>"")", and the script is built in such a way that it auto-executes on load (it's a simple script, doesn't register functions, just runs from start to end and does it's thing).
So my question is. How can I load (and thus execute) a lisp-file in autocad from a .NET plugin?
Ok, there are two ways to sendcommand via .NET.
The first thing you need to understand is that ThisDocument doesn't exist in .NET.
ThisDocument is the document where the VBA code is written, but since your addin is document undependant, it stands alone and you must take the documents from the Application object.
You access the application with:
Autodesk.AutoCAD.ApplicationServices.Application
If you want to transform it to the same Application object as in VBA, with same methods and functions
using Autodesk.Autocad.Interop;
using Autodesk.Autocad.Interop.Common;
AcadApplication App = (AcadApplication)Autodesk.AutoCAD.ApplicationServices.Application.AcadApplication;
The first application has MdiActiveDocument, from where you can call the Editor and send written commands, or call the SendStringToExecute as said in other answer.
The AcadApplication has ActiveDocument (an AcadDocument object that behaves exactly as in VBA).
This document will have the same SendCommand your VBA has, use it the same way it's done in VBA.
If you can explain better the autoexecute part, I can help with that too.

Is there a standard process to save Excel File Formatting/Settings into an Object?

It could be cumbersome at times to maitain Excel Workbook's formatting/settings when heavy backend, front end work loads are done. At times (even frequently) workbooks were crashed. But I can't recall what the code or process was to avoid this happening due to the formatting. What I am clear is that before any data retrieval, processing took place in the workbook, I saved the Workbook's formatting/settings into an object. Once everything was completed, that object was called to restore. It was most probably one of the custom/user written classes.
That code was very handy when working with Workbooks to manage certain company standards/Logos/Colour Pallete/formatting/protection settings/code settings and so on.
So I just want to ask if anyone in the community have come across such process? I searched online and disappointing enough I am unable to find anything near - else I have really lost my wits on key-word search ;)
PS: This is not my home work or work. So please throw some light.
If you are talking about creating spreadsheets that conform to your branding standards, why don't you just create a template file:
http://office.microsoft.com/en-us/excel-help/save-a-workbook-or-worksheet-as-a-template-HA010218874.aspx

Avoiding cross process calls when doing Word automation via VB.net

The short version
I've got a Word Addin in VB.net and VSTO that exposes a COM compatible object via Word.COMAddins.Object, so that the addin functionality can be called External to Word, without accesses to Word itself being cross-process.
The technique worked in VB6, but with VB.net, it still works, but it's much slower than the same code running directly from the addin via a task pane, as if the calls are all cross process when they shouldn't be.
x
The Long version
This addin essentially does tons of processing on Word Documents.
The addin can be run in two ways.
from within Word, using a taskpane
externally, via a set of classes
exposed to COM (because I have to
provide access to the functionality
to VB6 client apps.
BUT, here's the rub. Anyone who's ever done Word automation knows that code that runs perfectly acceptably INPROC with Word (in this case the instance of the ADDIN that Word itself loads), will generally run unacceptably slowly out of process (or cross process).
This app is no different.
Ages ago, I made use of a handy trick to circumvent this issue.
Create a Word Addin as usual
Expose an object via the
Word.COMAddin.Object property that
will let external code access your
addin.
In your external project, instead of
manipulating Word directly, Use the
Application.COMAddins collection,
find your addin, retrieve the
exposed COMAddin.Object property
from it and then call a method on
that object that does the work.
Of course, the call to your COMAddin.Object object will still be cross process, BUT, once execution is in the addin that is IN PROCESS with Word, your addin can now perform all the Word object manipulations it wants and it's fast because they're all in-process calls at that point.
That worked in the VB6 COM days.
But, I put together this VB.net vsto addin, and expose my addin object via the RequestComAddInAutomationService function of VSTO's Connect object
I can make calls into my addin externally and they all work exactly as I would expect them to, except they're all +slow+, very much like the calls into Word are still being performed cross process even though the code making those calls to Word is part of the addin dll that was loaded in-process by Word!
And slow as in a factor of about 10 to 1; what takes 3 seconds to run when run directly from the ADDIN via the task pane, takes ~30seconds to run when called from external code through the COMADDIN.object object.
I'm guessing that I'm running into some sort of issue with .net APPDOMAINS or something and what +really+ constitutes cross proc calls in .net, but I've found nothing so far that would even hint about this sort of thing.
My next step, barring some mystical insight, will be to code up a repro, which could get tricky because of the shear number of elements in play.
Any thoughts?
I've made the same observations with my VSTO Word add in. What I'd like to add here: When you add your procedure as a click handler to a button:
`this.testButton.Click += new Office._CommandBarButtonEvents_ClickEventHandler(YourProcedure);ยด
and implement your expensive procedure in "YourProcedure", you can call into Word's UI thread using
this.testButton.Execute();
This is not an elegant solution either, but maybe useful if you happen to have buttons ready in a CommandBar.
Unfortunately, the Event hook technique Thorben mentions wouldn't work for my particular situation.
So I'm closing this question out with the workaround that I mentioned in comments and I'll repeat here...
Well, not a perfect solution, but I have found +a+ solution. It involved a timer, so it's definitely suboptimal Essentially, when the addin is loaded by Word, (ie during the STARTUP event), initialize a timer (a WINFORMS timer, not a threading timer), and set it's interval to 500. When External code connects to the addin via the COMADDIN.OBject property, and makes a call into the addin, set a variable flag, which is being polled by the timer. When the timer sees it set, it resets the flag and performs the action.
It's not the clean solution I'd have preferred, but it's fairly easy to implement, moderately easy to understand after the fact, and it definitely avoids the slowdown of xprocess COM calls into Word.