Why does my Excel VBA code still run after closing my form? - vba

I'm creating a fairly extensive Excel user form making use of several custom classes I've written. Things currently seem to work as expected, but sometimes when I close the form a process appears to still be running in the background.
I know this because after closing said form, sometimes a CPU core keeps running at full capacity, and when I click on a cell in my spreadsheet the value shown in the formula bar blinks rapidly, as if the spreadsheet were being repeatedly refreshed.
I've tried inserting breaks and debug statements in the Class_Terminate functions of each class (or at least all the big ones), and they all seem to deconstruct neatly. Furthermore, when I rest at a code break, everything halts as expected.
So, what gives? Is there a better way to isolate the problem? How can I find out what's still running after I close my userform?

Well, after some aggressive commenting and uncommenting, it seems like my error has to do with VBA's destructor functions, Class_Terminate().
I have a "WellReader" class within a "WellCollection" class, so when I terminate my WellCollection class, it destructs WellReader along with it. However, if I have Class_Terminate() defined for both classes, it throws my program into a loop (literally). Simply defining the functions causes the error, even if there's no code within them.
(Here's a related StackOverflow post that sheds some amount of light on this issue.)
So, while I'm not sure why both destructor functions won't work, for now I'll do without one. Thanks for everyone's help!

Related

VBA code example on Microsoft's website destroyed the clipboard for the rest of the computer. Why did this happen and how can I prevent it?

This is something I didn't think was even possible, but here goes. I was trying to learn how to use the Windows API in Visual Basic to use system calls, and this tutorial (yes, I had to type out the link manually to ask this question, more on that later) showed me how to use the clipboard to retrieve text that the user copied with Ctrl+C. Out of curiosity, and under the assumption that all user input is bad input, I tried pressing Print Screen and then running the code just to see what would happen. I got some error message (can't remember what) but what's very strange is, now the clipboard no longer works! Any attempt I make to paste after a cut or copy, no matter what program I'm using, either does nothing or returns an error message in the program I'm using it in. Yes, it's my fault for intentionally trying to break the code example, but let's be honest - there's no excuse for the OS to fall apart so easily. If it matters, I'm using a PC running Windows 10.
EDIT: Settings won't let me clear the clipboard, and when I try to view the clipboard history, it shows nothing is there. Unfortunately I wasn't able to screenshot the clipboard history because it closes by itself when I try to open Snipping Tool.
Sounds like you've missed a CloseClipboard(), keeping the clipboard locked since Windows thinks a program is reading to it or writing from it. This will prevent other programs from working with the clipboard, since only one program can access it at a time. If Access is still open, you can try running CloseClipboard in the immediate window, else, I recommend a reboot.
On code like this, always add an error handler that calls CloseClipboard() to prevent leaving the clipboard open if something unexpected happens. Note that when working with WinAPI, you might encounter hard crashes that may not call the error handler, so always triple-check your pointers and expect crashes and reboots.
The code you've found is also not adjusted for 64-bit use, so beware. If you've got it to work by just slapping PtrSafe on the functions, you may end up with invalid pointers which can crash Access, leaving the clipboard open and unusable.
The code you've found, while written by Microsoft, is not of particularly good quality. I recommend first checking if there's text on the clipboard using EnumClipboardFormats, then only requesting text if there actually is text on the clipboard.
Beware that using WinAPI through VBA is tough, it's not beginner stuff, especially regarding the clipboard.
Note that there's no excuse for the OS to fall apart so easily is not the attitude to have when working with WinAPI. You're directly interfacing with the OS without any of the securities that managed languages offer, and manually working with pointers. It can and will break if you do something invalid. There's a reason most people use libraries that abstract the dangerous stuff away, if you don't, all bets are off.
similar problem for me. I did not have a CloseClipboard() but when I looked in another module there was already a EmptyClipboard() so used that before the DupRec() call at each instance and no more problems with clipboard. just FYI

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.

MS Access closing on command button click

I have been writing VBA code for a split database, and as of late, some of the command buttons will close the instance of access on the end users machine. No warnings, no ability to stop it from happening. If I add a breakpoint, the code doesnt even hit the click event, it just closes out entirely. This however, is briefly solved by adding a NEW command button and then transferring the code over. What gives?
Repairing and compacting a database rarely seems to solve database corruption problems, and neither does decompiling it (although these can work).
I'd follow these steps (as per Dan's suggestion):
create a new database
import all objects (tables, queries, forms, reports, macros and modules) from old database
At this point it may hang on one particular form or report. If this happens, just omit this form/report from the import (although you may well be unable ever to get at it again!).
Finally, compile any VBA code, repair any references to other VBA object libraries, redraw your relationships window so it looks as pretty as it did before (the relationships themselves aren't lost; just the way they're arranged) - and curse Access!

Excel freezes during execution

When I execute my code (which takes 3-4min. to execute) in Excel, and I click on something in excel or in my userform, it freezes, gets white, almost crashes... When the execution is ready everything is fine again.
Of course it is normal that I can't work in excel during execution, but how can I avoid the "crashing" of excel?
Do you have a Loop in the code?
If so, add the following line just after you initialize the loop and it should help with your problem!
DoEvents
The best way to prevent these kinds of issues is to benchmark your code to determine what is taking so long. If your code is taking over 3 minutes to run, you almost certainly have room for optimization.
Here are the steps you need to take:
Set multiple breakpoints within the code that is executing.
Time how long it takes to get from one breakpoint to the next.
Once you've identified the culprit(s), refactor.
If you aren't able to improve performance, post the inefficient code and ask for help.
A notorious slow-performing anti-pattern to look out for is selecting things during a loop.
What you need to do is create a custom UserForm that will overlay the Excel UI, like a Progress Bar. You'll also want to look into ways to force your form to stay ontop, much like a modal form. You can't use modal form's because they cease execution.
After you make sure there are no infinite loops making excel unresponsive try optimizing your code.
I found this a very interesting read on vba-excel code optimization and some of the practices actually had an impact on a big and time consuming module I wrote. Hope it helps.

Why does this program need MsgBox?

Long story short: I'm trying to write an app that'll dump IE's history to a text file. Because I am lazy, I went searching for a preexisting library and found this beautiful project to build from: http://www.freevbcode.com/ShowCode.asp?ID=6702. Only, I'm stuck...
I finally got the program to dump the history, but it only works if I put a MsgBox() on line 169 of Module1.vb. I've tried putting a Thread.Sleep() there, but that doesn't work. There has to be a message box there, or only today's history gets listed.
My guess, since this is talking to wininet.dll, is this is a concurrency thing. Thread.Sleep() (for a For...Next loop) stops the program from listening; nothing there makes it exit the loop before values are assigned, but a MsgBox() is just right. Is there something besides MsgBox() that will have the same effect? I'd like to not have to hit OK thirty times to make the program work.
Here's my branch/version/derived work: http://profnano.org/andy/misc/img/HistList.zip; it's a VS.NET2003 project.
MsgBox() pumps a message loop. That can get all kind of code unstuck. Windows get a chance to paint themselves. COM deadlocks due the main thread getting stuck in a loop are solved, always an issue when IE is involved. Calling DoEvents() is the very imperfect alternative to MsgBox().