MS Access 2010 VBA: mysterious compile error on custom LostFocus sub - ms-access

In a data validation form, I have a subroutine checking previously-entered data on a LostFocus event by ensuring that the release time (TimeReleased in table; Me.txtTimeReleased on form) is after the capture time (ObservationTime in table; Me.txtObservationTime on form). I'm using LostFocus rather than BeforeUpdate because the data were bulk-imported into the db and are now being error-checked.
My users keep getting a compile error (Compile Error: method or data member not found) upon tabbing out of the field this sub is attached to but I cannot reproduce the problem locally. The error occurs on this line:
If (Me.txtTimeReleased) <= (Me.ObservationTime) Then
and the part highlighted is '.txtTimeReleased'
Full code block:
Private Sub txtTimeReleased_LostFocus()
Dim badData As Variant
Dim resp As Variant
'Also check that time released is after time captured
If Not IsNull(Me.txtObservationTime) And Not IsNull(Me.txtTimeReleased) Then
If (Me.txtTimeReleased) <= (Me.ObservationTime) Then
resp = MsgBox("Release time must be after capture time." & vbCrLf & "Please double check this field's value: is it correct?", _
vbYesNo + vbExclamation + vbDefaultButton2, "Release Time Before Capture Time")
If resp <> vbYes Then badData = True
End If
End If
If badData = True Then
Me.cmbTaxonId.SetFocus 'set focus away so can set focus back
With Me.txtTimeReleased
.SetFocus
.SelStart = 0
.SelLength = 10
End With
End If
End Sub
Other things to note:
Both the table field and form control are formatted as 'Short Time' (24-hour time)
There is an input mask on that form control for 24-hour time; I use input masks very rarely and thus aren't familiar with them--perhaps the input mask could be causing the problem?
There are similar LostFocus subs on most of the other controls which do not produce this (or any other) error
Things I've tried:
Checking spelling
Fully decompling and recompiling the code: starting with shift, compact and repair with shift, open with /decompile flag while holding shift, compact and repair with shift, re-open with shift, and finally compile (without error)
Replacing the form in their database with one that works fine for me on the same data
Google
Things that seem odd to me:
I can't reproduce the error locally.
The error is triggering on the second instance of
Me.txtTimeReleased rather than the first: it has already passed a Not
IsNull(Me.txtTimeReleased) check.
The fact that it's a compile error: could that be masking something else?
Thanks for your time, and please let me know if there's any additional information that would be useful. Any thoughts are most welcome!

You checked for Null txtObservationTime and txtTimeReleased, but compare then txtTimeReleased and ObservationTime. Maybe solution is:
If Not IsNull(Me.txtObservationTime) And Not IsNull(Me.txtTimeReleased) Then
If (Me.txtTimeReleased) <= (Me.txtObservationTime) Then

Opening the .mdb with the /decompile flag is one of the first things I would have suggested, but you said you already tried that.
Here's another undocumented trick to deal with "hidden" compile problems that get baked in by VBA behind the scenes:
First, make a backup copy of your .mdb just to be safe (this is, after all, an undocumented technique).
Then, save your form to a text file using SaveAsText:
SaveAsText acForm, "MyFormName", "C:\MyFormName.txt"
Finally, re-load your form using the equally undocumented LoadFromText:
LoadFromText acForm, "MyFormName", "C:\MyFormName.txt"
Compile.
Compact.
Repair.
Hope for the best.
Good luck.

I suggest you use variables:
intThat = Me.txtTimeReleased
If intThis <= intThat Then
Try using ! instead of a dot:
intThat = Me!txtTimeReleased
If intThis <= intThat Then
And now, the answer that worked for me last week:
Comment out the offending line.
Run a compile that is successful.
Restore the offending line.
The compile may work now. Don't ask me why.

Related

Trouble with Access 2010 .SetFocus command syntax

Extremely puzzling:
Upon opening a simple form from another form by vba, the cursor moves to a particular field.
However, when this field is Null there is each second time Error 2110. The syntax to be used changes every time as shown below.
Even more puzzling:
Upon clicking "Debug", the error proves to be imaginary: on the corresponding code line, one can simply continue with F5 or F8 and the procedure ends correctly with the focus where desired.
I found a provisory workaround which does not generate the error message but would like if possible to avoid such limping coding:
'…
Debug.Print Me![MyTextField].Enabled ' always True
Debug.Print Me.Name ' always correct form
Me.Repaint
On Error Resume Next
[MyTextField].SetFocus ' without Me!
Me![MyTextField].SetFocus
' Forms![MyForm]![MytextField] : same result as with Me!]
' one time error with Me! but not without Me!,
' next time vice versa, and so forth…
On Error GoTo 0
'…
When [MyTextField] is not Null, both syntaxes work fine without generating an error.
What is wrong with this .SetFocus command ? "Repairing" the database didn't help.
You can't set focus to the control that has focus. It would give you a very easy way to set up a infinite loop.
You would have to set focus to another control first.
Minty's right. An easy workaround is doing it in an if statement or create a bool to see if IsNull(fieldhere) = true then exit sub or your action here. Or more simply maybe try:
if MyTextField.gotfocus = true then
do something
else
MyTextField.setfocus
I recently ran into this issue in something similar and had to create a public bool function and test it on load events. Please note that I'm a beginner in access so there's probably many better ways to complete this :)

"Invalid use of Null" error on DoEvents statement in MsAccess

I have a weird situation in Access. Normally, the Invalid use of Null error is quite a simple thing - assigning a null to a string variable or some such. But I'm getting the error in a place where it seems to me it should not be happening. Here is the code snippet:
bch = Form_Akces.txtMaxCisla.BackColor
If Err <> 0 Then Stop
Form_Akces.txtMaxCisla.BackColor = vbYellow
If Err <> 0 Then Stop
DoEvents
If Err <> 0 Then Stop ' This is where I get the error
With qdf_GPsp
What's been happening is that I get this error only sometimes, usually only on the first time I run the code in a while. If I close the database and immediately re-open it, usually I do not get the error. It's been driving me nuts for quite a while, so I put in all these "If Err <> 0 Then Stop" statements, trying to track down where it happens. It's a live system, and users know to simply restart the app, but it's a massive PIA, and kind of embarrassing to boot.
Can anybody think of something to try or examine? I'm not exactly an amateur in Access, but this is far outside anything I have ever run across. Why a DoEvents statement should generate such an error is beyond me, especially since I am not doing anything even in the preceeding statements that should generate such an error, that it might be somehow 'held' until the processor gets an opportunity to throw the error. If I take out the DoEvents, I simply get the same error somewhat further down the line. txtMaxCisla is an unbound text field on the form Form_Akces, from which the routine containing this code is called. It is only on start-up - once everything is loaded and running, this never happens again. And it only happens once in a while - no pattern to it that I have been able to detect.
It's been going on for a couple of months, through numerous compile, decompile, recompile, compress and repair cycles, with no discernible change except that sometimes it happens other places, again with no reason for it that I can see.
Update *
No luck - it still crashes, and for absolutely NO reason that I can see. Here's the code now:
Public Sub ReloadMaxNumbers(tmc As TextBox)
Dim rst As DAO.Recordset, x$, xb$, xe$, bch&
On Error GoTo 0
If Err <> 0 Then Stop
DoEvents
If Err <> 0 Then Stop
...
The code stops on the SECOND test, after the DoEvents, with the same error, "Invalid use of Null". I realize this code is completely retarded, but it's the result of tracking back, trying to find the root of the error. Without this, it crashes further down the road somewhere, with this same error. At this point I can't think of anything else to even try.
I'm puzzled by Form_Akces in your code. If I create a form named Akces, the form's code module is named Form_Akces. But you said "on the form Form_Akces". So I am confused whether Form_Akces is the name of the form or the form's code module. Perhaps Access is also confused.
Either way, since you said the code is in the form's code module, I suggest you substitute Me for Form_Akces
Edit: I misunderstood your situation. That code you showed us is actually from a procedure in another code module, not the form's code module. In that case I would do something like this for the external procedure DoSomething:
Public Sub DoSomething(ByRef frm As Form)
bch = frm.txtMaxCisla.BackColor
frm.txtMaxCisla.BackColor = vbYellow
DoEvents
' whatever else you need
End Sub
Then in the form's code module where you call DoSomething:
DoSomething Me
And if DoSomething only operates on a single control each time, you could just pass a reference to that control instead.
Public Sub DoSomething(ByRef ctl As Control)
This approach will allow DoSomething to be re-used for other forms with no changes required because the target form name is not "hard-wired" into the procedure. Also, it won't break if you rename your Akces form. In the second variation, it would also accommodate changes to the control name.

access to oldValue for control in continous form generates error 3251 in beforeUpdate when a checkbox on form is updated

This is one of the stranger issues I have seen in MS Access. I have the following code in a continuous form:
Private Sub thisForm_BeforeUpdate(Cancel As Integer)
If Not Cancel Then
Debug.Print "pre-logging data changes..."
' here we need to doublecheck to see if any values changed.
' we simply iterate through the whole list, re-setting oldValue
' and newValue.
For Each control In thisForm.Section(acDetail).controls
If control.ControlType = acTextBox Or _
control.ControlType = acComboBox Or _
control.ControlType = acListBox Or _
control.ControlType = acOptionGroup Or _
control.ControlType = acCheckBox Then
Debug.Print control.Name
oldValues(control.Name) = control.oldValue
newValues(control.Name) = control.value
End If
Next
End If
End Sub
oldValues and newValues are Dictionary objects (although likely not related to the issue).
My form has 3 textbox controls, and a checkbox control. One of the text box controls is disabled, and is populated via the results of a simple inner join (to get the human readable name associated with a foreign key). The data source comes from the form's recordsource (no DLookup or anything is used).
If I edit one of the other two textbox controls, this code runs absolutely fine. HOWEVER, if I toggle the checkbox on the form, i get a runtime error 3251. In the watches window, I get the error again when i try to view the properties of "control". It shows the value of oldValue for the disabled control to be "Reserved Error".
If it did this consistently, I would think it was due to the control being disabled; but since it works without a problem when the other textboxes receive edits, and only breaks when the checkbox is toggled; I am stumped. I'm almost inclined to believe I found a bug in access, but I could use some extra input.
Anyone else every encounter an issue like this?
EDIT: Upon digging further, I found that in actuality only one of the 3 editable fields will not trigger this error. It holds string data. The other two controls hold a date value, and a yes/no value. Now I am even more confused.
i've got two ideas to that issue.
First one: If the RecordSource of your Form is an ODBC-Table thats linked to a SQL-Server then you should set a standard value for the CheckBox-Column. Otherwise it will try to set NULL to False and throw an error saying that somebody else edited the current record.
Second idea: Sometimes Access just has a little "hiccup" when it compiles the code. You could make a backup of your database and then try to decompile it using "C:\Program Files\Microsoft Office 2007\Office12\MSACCESS.EXE" "C:\yourFolder\yourDatabase.accdb" /decompile in the Run... Window (of course you have to insert the Path as it is on your machine). That often helps solving strange Problems.

Disable warning: You copied a large amount of data onto the clipboard

While debugging queries written in MS Access 2007 (problem was the same in all previous versions too), I'll run the query and then copy the results into Excel. Depending on results, I switch batch to Access to refine the results and go back into design mode of the query. At this point, I get an annoying warning: you copied a large amount of data onto the clipboard. ...Do you want to save this data on the clipboard? I have never wanted to do this.
The MS Office clipboard is disabled so this function is happening with the standard Windows clipboard. Is there a way to disable the warning and assume No as the default?
There is a very easy solution to this. The warning message only happens if there is a LARGE amount of stuff on the clipboard. Therefore - make sure there is only a small amount of stuff there before you close.
For example, in a macro I wrote I do this:
Selection.PasteSpecial Paste:=xlPasteValues, Operation:=xlNone, SkipBlanks _
:=False, Transpose:=False
Windows("iostatZd15.1").Activate
ActiveWindow.WindowState = xlNormal
ActiveSheet.Range("A1").Copy
ActiveWindow.Close
The second-last line (immediately before the close) is a "dummy" - a command to simply replace the current (BIG) clipboard with a very small amount of data. It works.
I think you may have to disable the MS clipboard. Try this:
Quit any programs that are running.
Click Start, and then click Run. Type regedit and click OK.
In the Registry Editor, click to select the following subkey (folder): HKey_CURRENT_USER\Software\Microsoft\Office\9.0\Common\General
On the Edit menu, point to New and click DWORD Value. With New Value #1 selected, type AcbControl, and then press ENTER.
On the Edit menu, click Modify. In the Edit DWORD Value dialog box, click Decimal under Base. Type 1 in the Value data box. Click OK and quit the Registry Editor.
NOTE: You cannot disable (or enable) the Office Clipboard for only a single Office program by modifying the registry.
Here's the MS KB article
You could set the OnClose event of the form up to clear the clipboard.
Put the below code into a module in your database.
Private Declare Function apiOpenClipboard Lib "User32" Alias
"OpenClipboard" (ByVal hWnd As Long) As Long
Private Declare Function apiEmptyClipboard Lib "User32" Alias
"EmptyClipboard" () As Long
Private Declare Function apiCloseClipboard Lib "User32" Alias
"CloseClipboard" () As Long
Function EmptyClipboard()
If apiOpenClipboard(0&) <> 0 Then
Call apiEmptyClipboard
Call apiCloseClipboard
End If
End Function
Then in the Close event of your form use:
EmptyClipboard
In my experience, you only get this message when you close an application. Are you closing Excel before returning to Access? If so, don't close it and see if you no longer get the message.
EDIT after trying instructions for producing the error:
The only way to avoid the error message is to turn off notifications before entering design view, as in:
DoCmd.SetWarnings False
And you'd want to turn it back on after you are done with your editing.
But there's no place to run this code, since you're just using the Access UI to edit a query.
I don't quite understand why this warning is considered a problem. Maybe you're pasting, going back to design view, changing criteria, running again, pasting again? If so, turning SetWarnings off might do the trick.
If you wanted it to happen automatically, you could conceivably use the Screen.ActiveDatasheet object to do this. What you'd want to do is write a function:
Public Function ChangeWarnings(bolSetting As Boolean) As Boolean
DoCmd.Setwarnings bolSetting
End Function
...then when you open your query in datasheet view, in the Immediate window, type these two lines:
Screen.ActiveDatasheet.OnActivate = "=ChangeWarnings(False)"
Screen.ActiveDatasheet.OnDeactivate = "=ChangeWarnings(True)"
You could also certainly write code that sets this up for you.
One note -- it doesn't "stick" for the Screen.ActiveDatasheet object when opening or closing a different one. It applies only to the Datasheet that is active when you assign the event actions.
For Excel:
Fexcel = New Microsoft.Office.Interop.Excel.Application
Fexcel.DisplayAlerts = False
Do same for Access
Application.CutCopyMode = False
I run into this problem all the time. It seems silly to have to do this, but the following solution kills it dead.
' Copy something small into the clipboard
Range("A1").Copy
' Turn off CutCopyMode i.e., the "crawling ants"
' Application.CutCopyMode = False solves a lot of problems, I do it as a precaution after I copy anything
Application.CutCopyMode = False
CutCopyMode = FALSE does not turn off the all clipboard copying (as stated by another poster)

Disabling multi-line fields in MS Access

Is there a way to disable entering multi-line entries in a Text Box (i.e., I'd like to stop my users from doing ctrl-enter to get a newline)?
I was able to do it on using KeyPress event.
Here's the code example:
Private Sub SingleLineTextBox_ KeyPress(ByRef KeyAscii As Integer)
If KeyAscii = 10 _
or KeyAscii = 13 Then
'10 -> Ctrl-Enter. AKA ^J or ctrl-j
'13 -> Enter. AKA ^M or ctrl-m
KeyAscii = 0 'clear the the KeyPress
End If
End Sub
The way I did it before (and the last time I worked in Access was around '97 so my memory is not so hot) was raising a key-up event and executing a VBA function. It's a similar method to what you do with an AJAX suggest text box in a modern webform application, but as I recall it could get tripped up if your Access form has other events which tend to occur frequently such a onMouseMove over the entire form object.
Using the KeyPress event means that your code will fire every time the user types. This can lead to screen flickering and other problems (the OnChange event would be the same).
It seems to me that you should use a single event to strip out the CrLf's, and the correct event would be AfterUpdate. You'd simply do this:
If InStr(Me!MyMemoControl, vbCrLf) Then
Me!MyMemoControl = Replace(Me!MyMemoControl, vbCrLf, vbNullString)
End If
Note the use of the Access global constants, vbCrLf (for Chr(10) & Chr(13)) and vbNullString (for zero-length string).
Using a validation rule means that you're going to pop up an ugly error message to your user, but provide them with little in the way of tools to correct the problem. The AfterUpdate approach is much cleaner and easier for the users, seems to me.
Thanks Ian and BIBD. I created a public sub based on your answer that is reusable.
Public Sub PreventNewlines(ByRef KeyAscii As Integer)
If KeyAscii = 10 Or KeyAscii = 13 Then KeyAscii = 0
End Sub
Private Sub textbox_KeyPress(KeyAscii As Integer)
Call PreventNewlines(KeyAscii)
End Sub
Screen flicker should never be an issue, as these are handled events, not constant polling (and it's per control further limiting the scope). Seems to me like an invalid argument, as every text editor is executing some code per keystroke.
Thanks
not entirely sure about that one, you should be able to remove the line breaks when you render the content though, or even run a vbscript to clear it out, you just need to check for chr(13) or vbCrLf.
If you don't want an event interfering, you can set up the Validation Rule property for the textbox to be
NOT LIKE "*"+Chr(10)+"*" OR "*"+Chr(13)+"*"
You will probably also want to set the Validation Text to explain specifically why Access is throwing up an error box.
Jason's response works well. Just to add to it..
If you want to allow the user to leave the text box blank, you could use this:
Not Like ""+Chr(10)+"" Or ""+Chr(13)+"" Or Is Null