Below is my XML code
<toggleButton id="CloseBtn" label = "Close"
size="large"
imageMso="FrameDelete"
onAction= "=InvoiceRibbon_Close()"
getPressed="MyToggle"
keytip="C"
supertip= "Close current window."/>
By Function is Form code:
Public Function InvoiceRibbon_Close() As Boolean
It works on three computers. Two have Office 2016 Access and one is Access 2016 run time only. It does not work on the other two computers. Both are Access 2016 run time only. All three 2016 Run time computers are new computers which is Windows 10. Error message is attached.
The onAction function is inside Form VBA code. Below are some testing I did.
If I move InvoiceRibbon_Close to Module, it works.
On module OnAction function, I still cannot call function which is inside Form by Call Forms("FormName").InvoiceRibbonTesting_Close. Error message is still the same.
The function in Form works. I used it for a while.
I want to keep the function in Form VBA. I have hundreds Functions which is form related. It will be a huge tasks to move it to Module
Well, on the computers that fail, does ANY VBA code work? So, button code and what not - check if they work. If they don't work, then of course the Ribbon code will not work.
The other issue:
Check if you have a timer form running. Remember, the FANTASTIC idea you are using is to call functions in the form, and NOT USE horrible call backs which MUST be placed in standard code modules and thus are not attached to the given form in which 99% of the time we want code in that form to run and be used (say like any standard button code, but now you are using the ribbon. So, your setup is good and a high recommend approach.
Some things to check for this failure:
Does any VBA run at all? Check the trusted location settings.
Do you have a timer form running in the background. This is VERY but VERY VERY VERY important to check. What occurs with a timer form is that the form focus actually CHANGES to the the timer form while the timer code runs, and then returns back to whatever form currently has the focus. This is HUGE HUGE HUGE important since when you click on a ribbon button, it will FIRST TRY to run code in the current focused form's code module. This is good and great, since as you note that's were you have (and should) have that code that belongs to that form.
However, IF DURING THE TIME you click on the ribbon and the current forms focus changes (such as timer code, or other forms code running that MIGHT/MAYBE/COULD/PERHAPS/POSSBILE changes the forms focus to another?
Well, the Ribbon will look for and try to find that routine in the form with the CURRENT focus. A timer form running thus will change the form's focus, and if you click that button while the timer form code is running, then THAT FORM at THAT POINT in time actually has the focus, and thus the Ribbon will actually be attempting to find and run the function name in your ribbon in that timer form!!
You can quite quick test the above by removing for a test any timer forms you have running.
The other thing to look for is any kind of accidentally forms focus change. So, say a you recent added a sub form, or another navigation form or what not? Well, now the form you think that has the focus does not in fact have the focus, and thus the ribbon can't find the routine to run. This often happens when you say switch to a nice new computer, are using say the runtime. With a newer machine, often everything is running so much better and faster, that the FOCUS CHANGE you did not see much now occurs in a far more aggressive fashion.
The bottom line and thing you are looking for here is:
Does a un-expected form focus change occur. Say to some sub form that specifies a different ribbon, or some other small message or dialog or popup form that appeared un-expected. With any of these objects getting focus, then your main form with the code that the ribbon buttons call will not be found.
So, this is not a trusted location (ie: other VBA code works just fine), then next to check and test with is if any timer form is running (since as noted such forms VERY quick do get and rob the current forms focus away - and if you hit the ribbon at the same time while the timer code runs, then the focus change has also occurred, and thus the ribbon button will fail.
The above as a result ALSO means:
Don't have a timer form(s) if you can avoid as such.
The timer code if you have has to be VERY good and efficient code - it better get in, run VERY fast, and get out.
Don't have a aggressive timer interval. So, say some timer is to check and shut down access? Well, checking 10 times a second, or even once a second is OVER kill. Have it check say every 3 seconds.
Note that the above timer issue also often causes report print buttons to fail - you find that some blank form gets printed (and that blank form is in fact the timer form that temp had the focus when you hit your report print button.)
Related
I'm trying to setup a form in MS Access 2016 Pro Plus. Genuine copy in use on a govenment PC (in case that matters).
So I have two problems. The first and main one is that I can't manage to connect a button to an OnClick handler on one of the existing forms. It just stopped working.
I've created a new form and attached an event to a new button there and it's working there (it does detect the code connected).
I'm not sure what's wrong because when I click on the button in the faulty form and on the ... to edit the code it does bring me to the correct function (including moving the cursor). So it's not a Sub mispelling.
Anyone has any idea of why a form (only one in my project) would stopped triggering its handler/s?
I have taken 2 sample databases from online - one for a calendar and one for drag and drop functions - and pulled some code together for a result that is ALMOST functioning as I had hoped.
There is a function to build/refresh the calendar, which works perfectly.
The drag and drop functions work perfectly. (The item is updated in the table to reflect the new date.)
When I drag and drop, the calendar doesn't automatically refresh. If I click next month then last month (which call the refresh function with a new date), the changes are reflected as expected.
The problem is when I try to automatically call the refresh function after a drag/drop event. Access crashes every time I call for a refresh in the code after drag/drop, regardless of where I put the call.
The error says:
Microsoft visual C++ Runtime Library
Runtime Error!
Program: C:...
This application has requested the Runtime to terminate it in an
unusual way. Please contact the application's support team for more
information.
I have tried:
I thought it might be trying to refresh too fast, so I added a pause
function and had the program wait 10 seconds after dropping before
refreshing. Still crashed.
I did a compact and repair on the database.
I ran /decompile from the command-line on my accdb file.
I exported the relevant form, tables, query and module to a new accdb
file.
I have tried to re-register the libraries checked under references.
(RegSvr32 "Path to library file") The only one that succeeded was
vbe7.dll. The "MS access 14.0 object library", "OLE automation", and
"MS Office 14.0 Access Database Engine Object" don't contain a
DllRegisterServer method, so regsvr32 did not succeed with those. There are no other
references checked. Still crashes.
I have tried countless places to insert the call to refreshcalendar()
I have stepped through the code and verified the exact place that the
crash happens. It is commented in the code.
Here is a link to the database.
To reproduce the problem:
Open frmsubCalendar.
There are 2 entries in May 2014 that can be dropped to other days on the calendar. I can then click the prev/next month buttons on the form, and when May reloads, the change has been made. But if I go into mod_drag_drop under the sub dropdetect() and uncomment the lines noted in the comments, the refresh will crash access at the end of the dropdetect() sub.
I cannot figure out how to make the calendar refresh automatically after a drag/drop event without access crapping the bed.
I realize this is a bit outdated, but I had a similar issue and didn't see this one being answered, I figured I'd add this answer for posterity. :) I discovered it was caused by a reference to a function by the form name. I had the following call in a module:
lContractCt = Form_Census.lContractCt_f(bIsMembers)
Where lContract is a Long, there is a form named Census and a public function in that form called lContractCt_f.
I moved the function to a module (so the Form_Census reference wasn't necessary any more). And changed the call to:
lContractCt = lContractCt_f(bIsMembers)
This fixed the error. So, I would check if you have any public function references going from a module to a form and move those public functions into a module. I also saw a similar thread with a different form reference, via Forms![Census], for example.
I am working on a modal popup form in access and I have the following problem:
When I incidentally open my form in "form view" instead of "design view" It causes a VB script error (which is normal, because it tries to get information from another form which is not open).
So VB tells me there's an error, I tell the VB debugger to stop the execution of the code, and thus the form does not open, but then access is not re-enabled.
I can't regain any form of control, and it's not an endless loop or something like that, because Access is still running correctly according to my task manager.
So far the only solution I found was to close access through the task manager, but it doesn't seem normal to me.
Here are a few suggestions:
http://www.pcreview.co.uk/forums/control-location-screen-form-opens-t4041436.html
You can also try to modify a bit of your form, move it to a new/good position, and saving it. I have had this happen to me in the past.
We have an MS Access 2007 database with a simple form displaying table data. We use the Find dialog (click the binoculars on the Home ribbon) to locate records we want. This can cause an error under specific circumstances.
Steps to reproduce the problem:
Open the form.
Open the find dialog.
Edit some field within the record.
The record is now in update mode
(you'll see the pencil in row's
"gutter" area).
Without saving the record, click on
the ALREADY open Find dialog.
Search for a record that can't be
found.
Click on the form again. The record
is still in edit mode (i.e. the
pencil still shows). Attempt a save
or edit some other field.
This message box will display
"Update or CancelUpdate without
AddNew or Edit." You can click OK or
Help buttons.
Clicking the Help button shows:
You tried to call Update or CancelUpdate or attempted to update a Field
in a recordset without first calling AddNew or Edit. (Error 3020)
On a Microsoft Access database engine database, you called the Update or
CancelUpdate method but did not use the AddNew or Edit method before writing
data to a record.
On an ODBCDirect database, this error occurs when you attempt to write data
to a record without first calling AddNew or Edit.
We’ve reproduced this in a new database where there is no VBA code. So the problem is solely within MS Access, and you should be able to reproduce it easily.
If you save the record before doing the find, the problem doesn’t happen. Unfortunately, we have users doing a find while the record is still in edit mode.
We’ve tried setting up form-level, data-field-level, and Access application level events and error handling. Nothing can detect or catch this situation. There is no way within VBA to detect if the Find dialog is active.
Does anyone have any ideas for preventing the error or a way to save the record before the find occurs? Our best thought right now is to create an AutoHotkey or AutoIt script that waits for the Find dialog to have focus. We’ll then send a Ctrl+S to save the current record to force a save.
#CodeSlave's answer suggests a possibility to me:
Instead of simply removing the binoculars from the toolbar/ribbon, instead change what the binoculars do. That is, have it call code that saves the current record if it's dirty and then launches the FIND dialog.
Now, there'd need to be some code to check that a form was open, and that it had a recordsource (testing the .Dirty property errors if there's no recordsource), and that a field has the focus, but all of those things are doable. Likely many of them (except the last) would be taken care of by showing the toolbar/ribbon only when the form is loaded, or by editing the default toolbar/ribbon when the form opens.
But this would be much less crazy than using an out-of-process solution, and your users wouldn't know any difference.
I'd suggest that you've found a bug that was introduced in MS-Access 2007. However, I have not been able to duplicate it on my copy. I presume we're both up to date on our patches, so perhaps there is something more subtle happening.
If you're wanting to force the record to be saved, use one of the the following - not a CTRL-S
if me.dirty then Me.Dirty = false ''(n.b. often the preferred method)
Docmd.RunCommand acCmdSaveRecord
DoCmd.DoMenuItem acFormBar, acRecordsMenu, acSaveRecord, , acMenuVer70 ''(n.b. deprecated)
The problem as I understand it, is that if they edit the form after the "find" is already open and then do the "find" the get the error.
I'd try one of two things:
Find a way to close the built in find form, and do so whenever you make the current record dirty (On Dirty)
Add your own "find" button to the form (not opening the built in find form), and hide the one on the ribbon.
The hack, work-around we came up with was to write an AutoIt script which can watch for when the Find dialog gains focus and save the record if it has changed.
We didn't want to distribute the script separately from the database, so the the script was added to a database table as a Blob. The database's AutoExec macro runs some VBA code that pulls the script out of the Blob table and starts the script.
When the script detects that the Find dialog has focus, the script runs a VBA macro in the database. The macro checks to see if the current record is dirty. If dirty, the macro forces a save. Also, the AutoIt script is stopped when the database is closed.
This is all pretty awkward, but it works.
I have a form with two subforms (on separate tab pages). It's an MDB project in Access
2003.
When it initially opens, Form_Current on the active subform fires once, as
it should.
But when you move to another record (ie. from the main form), it fires
Form_Current on the active subform 4 times. Then subsequent record-moves
result in Form_Current firing 2 times. This is a pain, because the subforms
have a lot of fields that get moved and/or hidden and so it jumps around for
every Form_Current, not to mention being slow.
I am opening the form with a filter via DoCmd.OpenForm (actually it sends
the filter in via OpenArgs). FilterOn is only set once, in Form_Open on the
main form, never in the subforms. Form_Current is not called explicitly
anywhere else in the code.
When I look at the call stack when Form_Current fires moving the first time,
it looks like:
my_subform.Form_Current
[<Debug Window>]
my_subform.Form_Current
So it seems like something in Form_Current is triggering another
Form_Current event. But only on the first record move.
The code in Form_Current is somewhat complex, involving custom classes and
event callbacks, but generally does not touch the table data. The only thing I
can think might be triggering a Form_Current is that it checks OldValue on
form controls - could this be causing it?
Or anything else come to mind?
Thanks.
Eric
As TheAceMan1 once noted, "The only thing you have to watch out for with the On Current event is recursion! That is ... code in the event that causes the event to retrigger. Like moving to another record within the code. Other than that ... the event can be as hefty as required." I have found Current to be horribly twitchy. That said, it is sometimes the only place to put your code.
You may be aware that events for sub-forms trigger before those for the parent form. This is certainly true for Load, and maybe for Current as well.
I can only suggest step-by-step trouble-shooting; comment out parts, check functioning, and work it out. Of course you can always post a heap more code for us to see.