Never ending loop while setting focus to control on validating event in cantrol validating event - vb.net

I am writing below code for validating compulsary field account no. in form.
User's requirement is set focus back on field when error comes :
If txtAccountNo = "" Then
MessageBox.Show("Account no filed can't be left empty")
txtAccountNo.SetFocus
Exit Sub
End If
It's working properlly. But suppose user don't want to fill form and exiting from aaplication.
Message box keep on appearing till user enters account no.
How can I avoid this situation?
Please help.

Set a flag to indicate user has seen messagebox. Check the flag to prevent any future messagebox. Make sure the flag is set before setting focus back to textbox e.g.
dim bMsgBox as boolean=false
If txtAccountNo = "" and bMsgBox = false Then
MessageBox.Show("Account no filed can't be left empty")
bMsgBox=true
txtAccountNo.SetFocus
Exit Sub
End If

You could put all the validation rules in one function / procedure / subrutine (I'm not familiar with VB, mostly C++ / C# user). Then call this function only when user is committing the data filled in, and set focus to first control with mandatory data not filled or invalid data entered.
Say you have a form with 3 controls to be filled in:
a date control not mandatory - dteDate
a text box mandatory - txtAccoutInfo
a text box mandatory - txtAddress
and 2 buttons:
button Save and button Cancel.
When 'Save' button is pressed you first call the function / procedure to validate user input. If date entered is invalid in dteDate, you set focus on it and return / exit the function; if no text is entered in txtAccountInfo then set focus on it and return / exit the function; if no text is entered in txtAddress then set focus on it and return / exit.
When 'Cancel' is pressed you don't call this function, but just quit.

Related

Button to check for missing values in a MainForm and Subforms in MS Access

New to Access (still), have only basic VBA skills.
I've got 3 subforms (subfrm_PackingSteps1 , subfrm_MetalDetection and subfrm_Weights - the first 2 are continuous and the other one is single form) within a main form (frm_daily_packing_record) that users go through and input data. The user should be able to input data in no particular order, and only at the end there would be a button to confirm that the user is ready to save this form.
I'd like to have this button on the main form that checks each control (in main form and subforms) for empty values. I found and adjusted a code to check the recordset of one of the continuous forms (see below), but I can't figure out:
how to include a code that checks each control instead of manually adding all of them (I've used a function before that utilises the Tag property, but can't add it to this)
how to keep the button in the main form while checking the controls/recordsets in the other subforms.
Thanks in advance.
Private Sub ConfirmBtn_Click()
Dim blnSuccess As Boolean
blnSuccess = True
Me.Recordset.MoveFirst
Do While Not Me.Recordset.EOF
If IsNull(Me.pc) Or IsNull(Me.InnerP) Then
blnSuccess = False
Exit Do
End If
Me.Recordset.MoveNext
Loop
If blnSuccess = True Then
MsgBox "You may proceed to save this record"
Else
MsgBox "You still have some empty fields to fill in!", vbCritical + vbOKOnly, "Empty Fields!"
End If
End Sub
I personally don't like this because it is too code-heavy and can easily break when the form is modified.
Instead may I suggest doing it slightly different, for each field have vba code .ondirty or .onupdate and do the validation checking right as the user is actually on that field.
This has 2 benefits, it is creating the validation when you are creating each form field and it STOPS the user right when their first mistake or bad data is entered. The last thing I want is to enter 50 fields, scroll to the bottom, submit fails then scroll back and try to find where the mistake was. If validation is done while the user it doing the actual data entry, when you get to the bottom you should have valid data and the submit should succeed without further testing.
Less code to debug and timely messages to the user if an error is caught!

Why is text clearing from the text field of a combobox if message is displayed?

I'm working in VB.NET, Visual Studio 2017. I have a combobox with DropdownStyle = Dropdown. If the user types something invalid in the text field of the combobox (invalid means it doesn't match a value in the combobox) then we display a message and then return focus to the text field with the text highlighted, so they can see what they typed. The message is displayed from the Validating event.
This works fine if they don't open the dropdown. If they do open the dropdown and, while it is open, they type in an invalid entry, the message displays but the entry they typed clears.
I have put in debug statements to see what events are firing. Before the message displays, I get a DropDownClosed (text is still there), then a TextChanged (text is still there), then a second TextChanged (text is now empty). I think something about losing focus to display the message may be triggering something, but I can't figure out what.
I can save off the text and then replace it after the message displays, but while the message is up, the text field is blank.
Any ideas?
While I still don't understand the series of events that causes the problem, I found a solution. Just before the message is displayed from within the Validating event of the combobox, I set focus to the combobox. I'm guessing that tabbing away from the invalid entry loses focus, and because the dropdown is open, it then closes which somehow clears the entry. Go figure.
Here is the code from the validating event:
If testInList Then
ResultTextBox.Enabled = True
Else
TestComboBox.Focus
'If test is not in combobox, display message.
MyUtility.MicroUtilities.DisplayMessage(
My.Resources.RES_MSG_INVALID_TEST, MessageBoxIcon.Information, , , True)
e.Cancel = True
End If
The "TestComboBox.Focus" line has fixed the issue of the text disappearing. However, if the user's invalid entry is a partial match for an item in the dropdown, then the text in the text field of the combobox is updated to that item, so now it looks like they typed a valid entry but are getting an message that it's invalid. For example, if there is an entry in the dropdown of "NAMC" and they type "NA" (with the dropdown open) and tab away, the entry changes to "NAMC".
Any ideas on how to prevent that?
p.s. The AutocompleteMode is set to None.
So again, I don't understand the sequence of Events that causes the issue, but I've found something that works. If I move the new "TestCombobox.Focus" line outside of the If condition, the text remains in the text field before, during and after the message displays:
TestComboBox.Focus()
testInList = TestEntryValid()
If testInList Then
EnableResultFields(True)
Else
'If test is not in combobox, display message.
MyUtility.MicroUtilities.DisplayMessage(
My.Resources.RES_MSG_INVALID_TEST, MessageBoxIcon.Information, , , True)
e.Cancel = True
End If
This moves the .Focus before TestEntryValid, but I don't see anything in there that would trigger any events:
Private Function TestEntryValid() As Boolean
Dim item As String = TestComboBox.Text
Dim validTest As Boolean = False
If item.Length > 0 Then
Dim index As Integer = TestComboBox.FindStringExact(item)
If index > -1 Then
validTest = True
End If
End If
Return validTest
End Function
If anyone can explain why this works, I'd love to know. If not, thanks to everyone who responded!

Make the Text box disappear for the current selected record

I have a checkbox in my main form which causes a text box and a button to disappear and appear when it is not checked and checked respectively. The code below works correctly:
Private Sub Check288_Click()
If Me.Check288.Value = True Then
MsgBox "Please Enter Reference Number and fill in the name", , "Database"
Text293.SetFocus
Me.MTM_Signature.Visible = True
Me.btn_8DGen.Visible = True
Else
Me.MTM_Signature.Visible = False
Me.btn_8DGen.Visible = False
End If
End Sub
My problem is this code is affecting the whole list of records instead of the current chosen record. I have an auto numbered primary key (ID) for identifying each records. Is there any way for me to make the text box and button disappear only for the current record. I am new to access VBA. Thank you.
In the event of Check288_Click() display a modal form and let the user enter the Reference Number. When closing the pop-up form update the database. You can use conditional formatting to hide (blend) the text box if you do not want to show it when empty.

Validating Attachment in Richtext field

I am using below code to validate the Attachment in Richtext field.
If I will not used Call source.Refresh(True)
then validation is not working, but this code is also refreshing document everytime querysave is called in buttons.
So is there any option or any other idea so that I should not user this Refresh part or entire code to validate .
If anybody have more efficient code then please share this.
If Source.Document.YesNo20(0)="Yes" Then
Call source.Refresh(True)
Dim rtitem As NotesRichTextItem
Set rtitem = source.Document.GetFirstItem( "Atchmnt20" )
NotesEmbeddedObjectArray = rtitem.EmbeddedObjects
If Isempty ( NotesEmbeddedObjectArray ) Then
Messagebox "Please enter an attachment in 20a. As you selected option Yes"
continue=False
Exit Sub
End If
End If
There's a way in LotusScript to check attachments presence even for new (not saved) documents.
Create a hidden computed field, for instance AttachmentNames with formula:
#If(#AttachmentNames!=""; "1"; "");
In LotusScript do the following:
'in new documents Form field may be empty
If doc.Form(0) = "" then
doc.Form = "YourFormAlias"
End If
'computing doc contents with the form
call doc.ComputeWithForm(false, false)
If doc.AttachmentNames(0) = "" then
MsgBox "Please attach a file",,"Attention"
Continue = False 'if you are running this code in QuerySave
Exit Sub
End If
Validating rich text fields in Lotus Notes is a bit of a dark art, but can you not just do this? (where doc is the back-end):
If(doc.HasEmbedded) Then Continue = True
There are other things you can do. Check this Lotus Developer Domain post, which covers attachments, text, embedded objects, all sorts:
http://www-10.lotus.com/ldd/nd6forum.nsf/0/8b3df10667d355768525719a00549058
Can you validate RT field with formula?
I created a hidden field below my rich text field with this Input Validation formula:
REM {Validate just when saving};
#If(!#IsDocBeingSaved; #Return(#Success); "");
REM {Should contain some file};
_filenames := #AttachmentNames;
#If(
#Elements(_filenames)=0;
#Return(#Failure("You should attach at least one file"));
#Success);
Assuming that you want to avoid the Refresh because it takes too long, here is what you may want to look at and if feasible, try to change:
Maybe you can use the "Entering" event of the RichText field in conjunction with a global variable (in the form) to skip the Refresh in your code, if the RichText field wasn't touched at all.
Are there keyword fields with "Refresh choices on document refresh" option enabled that may be safe to disable? Or even place a button that would bring up a dialog and populate the field with the selected keyword(s) - refreshing the choices won't be neccessary then, as you can always present up-to-date choices through #DbColumn/#DbLookup or NotesUIWorkspace.PickListStrings.
Is there any code (LotusScript or Formula) in "Queryrecalc" and/or "Postrecalc" form events that may be possible to optimize? For example by using a global variable (in the form) as a flag whether to execute the code in Queryrecalc/Postrecalc - set it to false just before calling Refresh in your code, then set it back to true (because this Refresh only serves to update the RichText field to the backend document).

Prevent moving to next record when hitting Enter?

I have a form in Access 2003 that should only be working with a single record. I can set the Cycle property to Current Record, but the form still jumps to the next record when I press Enter. My first thought was a KeyPreview property, but I'm not seeing one. My other thought is maybe the KeyPress or KeyUp event, but I thought I'd ask in case of unintended consequences. Any ideas?
The Cycle property only affects the TAB key.
To control the behaviour of the Enter Key that's a global property.
Go to Tools/Options - Keyboard tab and on "Move After Enter" select "Next Field"
There are KeyPress and KeyDown events that you can use to trap the Enter key too but that's more work.
This can also be done in vba.
Application.GetOption "Move After Enter" 'get current setting
Application.SetOption "Move After Enter", 0 'don't move
Application.SetOption "Move After Enter", 1 'Next Field
Application.SetOption "Move After Enter", 2 'Next Record
http://www.pcreview.co.uk/forums/enter-key-moving-next-field-t3454281.html
The moment keys like TAB, Alt, PgUP, PgDn, Enter are pressed at the end of adding the record (after the last field mostly), the database auto saves all the info you entered on the form and wipes out the fields so that you can enter the next value. So what happens is that the data is saved but the form looks empty.
3 things to do:
Form Cycle Property set to Current Record.
Form Key Preview Property set to Yes.
Add following code to the KeyDown Event of the form:
'33 - PgUp; 34 - PgDown; 9 - Tab; 18=Alt; 13=Enter
Select Case KeyCode
Case 33, 34, 18, 9, 13
KeyCode = 0
Case Else
'Debug.Print KeyCode, Shift
End Select
I found this while scouring the web and don't take credit/responsibility for the code but I don't know where I found it. Works for me!
The Cycle property only works with the Tab key.
There are two options you could pursue.
You could trap the Enter key in KeyDown/KeyUp/KeyPressed
- OR -
You could filter the data source to the one record you want them editing, and disable adding new records through that form.
You can add below code to your form 'BeforeUpdate' event. If use want to move to next record, it will ask user to save then close the form before they can move to another recorde.
Private Sub Form_BeforeUpdate(Cancel As Integer)
Select Case MsgBox("Save?", vbYesNo)
Case vbYes
DoCmd.Close
Case vbNo
Cancel = True
End Select
End Sub
If you go into Access Options on the file page, go to Client Settings and the first setting will let you choose where your focus changes to when you press enter. At least in Access 2013.