Is there any way to clear the textbox on keypress like in excel.
I tried the following code but it clears the text when clicking on the textbox. I want it to clear it when a certain key is pressed.
Private Sub Text10_GotFocus()
Text10.Value = ""
End Sub
You could select the control's entire text content whenever that control gets focus. Then your keypress would replace the selected text.
If you want that to happen for every text box on every form, you can set "Behavior entering field" setting to "Select entire field". (In Access 2007, find that setting from Office Button -> Access Options -> Advanced, then look under the Editing heading of that dialog. For Access 2003, see this page.)
Not only will that setting be applied to form controls, but also to tables and queries in datasheet view. If that's not what you want, you can use VBA in your form's module to select the text for only specific controls:
Private Sub MyTextBox_GotFocus()
Me.MyTextBox.SelStart = 0
Me.MyTextBox.SelLength = Len(Me.MyTextBox)
End Sub
If you want to do that for multiple controls, you could create a general procedure:
Private Sub SelectWholeField()
Me.ActiveControl.SelStart = 0
Me.ActiveControl.SelLength = Len(Me.ActiveControl)
End Sub
Then call that procedure from the got focus event of an individual control like this:
Private Sub MyTextBox_GotFocus()
SelectWholeField
End Sub
Private Sub Field1_KeyPress(KeyAscii As Integer)
If KeyAscii = 65 Then Me.Field1 = ""
'Or: If Chr(KeyAscii) = "A" Then Me.Field1 = ""
End Sub
change the number to the ascii value of whatever key you are wanting to use to clear the field
Declare a Form Level variable
Private CanDelete as Boolean
When the TextBox receives focus, set CanDelete to True
Private Sub txtTest_GotFocus()
CanDelete = True
End Sub
On the KeyPress event, clear the text if CanDelete is True
Private Sub txtTest_KeyPress(KeyAscii As Integer)
If CanDelete Then
Me.txtTest = ""
CanDelete = False
End If
End Sub
Related
I am new to VBA and I'm trying to create a form in Access where a text box is enabled or disabled based on whether a check box is checked or unchecked.
So if the 'Survey Requested?' box is checked the 'Date Survey Requested' box is enabled for the user to enter a date.
I have the following code:
Private Sub CheckSurveyRequested_AfterUpdate()
If CheckSurveyRequested = True Then
DateSurveyReq.Enabled = True
Else
DateSurveyReq.Enabled = False
End If
End Sub
But this comes up with a '424 Object Required' error when I run line 5.
Anyone have a suggestion as to what I'm doing wrong here?
You should definitely use the AfterUpdate event---tying the behavior of your textbox to the click event means that a user using their keyboard to navigate the form won't get the same behavior.
Also, you should replicate this behavior when the form loads: If the default value for the checkbox is False, then your textbox should be disabled when the form loads.
Also, as #ErikA notes, you can do this with one readable line.
So I would recommend something like this:
Option Explicit
Private Sub chkSurveyRequested_AfterUpdate()
Me.txtDateSurveyReq.Enabled = Me.chkSurveyRequested.value
End Sub
Private Sub Form_Load()
Me.txtDateSurveyReq.Enabled = Me.chkSurveyRequested.value
End Sub
In order to not repeat yourself, you could move this code into a separate sub:
Option Explicit
Private Sub Form_Load()
' assign the function below to the AfterUpdate event of the checkbox.
Me.chkSurveyRequested.AfterUpdate = "=UpdateControls()"
' now execute the function directly
UpdateControls
End Sub
Private Function UpdateControls()
Me.txtDateSurveyReq.Enabled = Me.chkSurveyRequested.value
End Function
I would suggest the following -
Private Sub CheckSurveyRequested_AfterUpdate()
DateSurveyReq.Enabled = CheckSurveyRequested
End Sub
I have three Combo Boxes - When they are selected i would like it to check the tick box.
if the check box is ticked the Text box will then become Enabled, i currently have it set as disabled.
my question is how would i set the check box to be true when the three Combos are selected.
and how would i make it so that when the tick box is true it will enable the tex box
When all 3 combo boxes are set it will enable the checkbox. Once the value for any combo box is updated it calls a common function which checks whether all combo boxes have a value assigned and accordingly set the checkbox.
Private Sub cmbClientContact_AfterUpdate()
Call SetCheckBox
End Sub
Private Sub cmbClientName_AfterUpdate()
Call SetCheckBox
End Sub
Private Sub cmbProjectManager_AfterUpdate()
Call SetCheckBox
End Sub
Private Sub SetCheckBox()
If Nz(Me.cmbClientContact, "") <> "" And Nz(Me.cmbClientName, "") <> "" And Nz(Me.cmbProjectManager, "") <> "" Then
Me.Check25 = True
Me.Text27.Enabled = True
Else
Me.Check25 = False
End If
End Sub
Enable/disable textbox basis value of the checkbox
Private Sub Check25_AfterUpdate()
If Nz(Me.Check25, False) Then
Me.Text27.Enabled = True
Else
Me.Text27.Enabled = False
End If
End Sub
I would reccomend using the AfterUpdate event of all 3 combo boxes. Since the code is going to be the same (you're checking if all 3 combo boxes have a value), you can create one function to handle the check, and set that function to the AfterUpdate event of all 3 combo boxes when the form loads.
The function to update the controls (both the text box and check box) would be something like this:
Private Function UpdateControls()
Me.Text1.Enabled = Not (IsNull(Me.Combo1) Or IsNull(Me.Combo2) Or IsNull(Me.Combo3))
Me.Check1.Value = Not (IsNull(Me.Combo1) Or IsNull(Me.Combo2) Or IsNull(Me.Combo3))
End Function
You can call this function when the form initially loads, so the checkbox will be unchecked and the textbox will be disabled:
Private Sub Form_Load()
' update controls initially when the form loads
UpdateControls
End Sub
To make sure the same update happens whenever one of the combo box's values are updated, you can set each combobox's AfterUpdate event to the same function, like this:
Private Sub Form_Load()
' set each combo box's AfterUpdate event to run the check
Me.Combo1.AfterUpdate = "=UpdateControls()"
Me.Combo2.AfterUpdate = "=UpdateControls()"
Me.Combo3.AfterUpdate = "=UpdateControls()"
End Sub
So your final code might be something like this:
Private Sub Form_Load()
' set each combo box's AfterUpdate event to run the check
Me.Combo1.AfterUpdate = "=UpdateControls()"
Me.Combo2.AfterUpdate = "=UpdateControls()"
Me.Combo3.AfterUpdate = "=UpdateControls()"
' update controls initially when the form loads
UpdateControls
End Sub
Private Function UpdateControls()
Me.Text1.Enabled = Not (IsNull(Me.Combo1) Or IsNull(Me.Combo2) Or IsNull(Me.Combo3))
Me.Check1.Value = Not (IsNull(Me.Combo1) Or IsNull(Me.Combo2) Or IsNull(Me.Combo3))
End Function
Without knowing more specifics about the name schemas of your objects, this is my semi-vague answer:
One option (of many) is to use an On Click event procedure with the following:
If Not IsNull(Me.Combo1) _
And Not IsNull(Me.Combo2) _
And Not IsNull(Me.Combo3) Then
Me.Check1 = True
Me.Text1.Enabled = True
Else
Me.Check1 = False
Me.Text1.Enabled = False
End If
This assumes that the checkbox is named Check1 and the textbox is named Text1 and the comboboxes are Combo1, Combo2, and Combo3
It is a little confusing whether you meant Enabled or Visible, but if you meant Visible, just change the lines that say .Enabled to .Visible
I have a form with numerous images, each of which performs a series of actions when clicked. I can create a Private Sub with all of the actions for each button, however I think this is inefficient. Rather, I'd like to record all the actions in one Macro and then call this Macro when each image is clicked. To do so, I'd need the single Macro to refer to the current image selected and not refer to any image by name. Is this possible?
My current code includes the following:
Me.Image001.BorderColor = RGB(1, 1, 1)
Me.Image001.BorderWidth = 2
Me.Image001.BorderStyle = 1
I'd need to amend this so that it amends the border colour/width/style etc of whichever image is selected, and not a specific named image ('Image001').
Thanks!
You should use event sinking.
With event sinking you could bind to an event your own procedures.
You can see an example here http://p2p.wrox.com/access-vba/37472-event-triggered-when-any-control-changed.html
In simple words you create a module where you bind the event to your specific implementation . Then on the form you are interested you create a collection where you register the controls you want to "follow" the event sinking...
My sub sinking for checkboxes (i have alot)
1st a class module name SpecialEventHandler
Option Compare Database
Private WithEvents chkbx As CheckBox
Private m_Form As Form
Private Const mstrEventProcedure = "[Event Procedure]"
Public Function init(chkbox As CheckBox, frm As Form)
Set chkbx = chkbox
Set m_Form = frm
'Debug.Print frm.Name
chkbx.AfterUpdate = mstrEventProcedure
End Function
Private Sub chkbx_AfterUpdate()
'your Code here
End Sub
Private Sub Class_Terminate()
Set chkbx = Nothing
Set m_Form = Nothing
End Sub
Then on the form you want to use event sinking
Option Compare Database
Dim spEventHandler As SpecialEventHandler
Private colcheckBoxes As New Collection
Private Sub Form_Open(Cancel As Integer)
Dim ctl As Control
For Each ctl In Me.Detail.Controls
Select Case ctl.ControlType
Case acCheckBox
Set spEventHandler = New SpecialEventHandler
spEventHandler.init Controls(ctl.NAME), Me
colcheckBoxes.Add spEventHandler
End Select
Next ctl
End Sub
You could always create a Standard Sub, then call it on the click of the button. Something like
Public Sub changeColor(frm As Form, ctrl As Control)
frm.Controls(ctrl.Name).BorderColor = RGB(1, 1, 1)
frm.Controls(ctrl.Name).BorderWidth = 2
frm.Controls(ctrl.Name).BorderStyle = 1
End Sub
So when you click an image all you have to do is,
Private Sub Image001_Click()
changeColor Me, Image001
End Sub
I have an unbound textbox control. The user enters some valid text and leaves the control. The user then returns to the control and enters some invalid text. I want to show the user a message then rollback the value of the control to its previous state and keep the focus in that control.
I've tried the following approaches, none of which gets me exactly what I am looking for:
OPTION A: SendKeys
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then SendKeys "{Esc}"
End Sub
This does exactly what I want, but I really want to avoid using SendKeys. There are many problems that come with using SendKeys: Vista+ compatibility, keys being sent to a different application, etc.
OPTION B: Undo method of control
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then Me.MyTextBox.Undo
End Sub
This is simply broken for unbound controls (at least as of MS Access 2002/XP). This method does not restore the value of MyTextBox to the valid input. However, it does allow the user to change the focus to a new control while leaving the invalid input in place in Me.MyTextBox! Unbelievable!!!
OPTION C: Undo method of form
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then Me.Form.Undo
End Sub
The Undo here does absolutely nothing. But at least it doesn't break the BeforeUpdate Cancel=True code and allow the invalid data to stand.
OPTION D: Explicitly restore old value in BeforeUpdate event
Private mPrevMyTextBoxValue As Variant
Private Sub MyTextBox_AfterUpdate()
mPrevMyTextBoxValue = Me.MyTextBox.Value
End Sub
Private Sub MyTextBox_BeforeUpdate(Cancel As Integer)
Cancel = DataIsInvalid(Me.MyTextBox.Value)
If Cancel Then Me.MyTextBox.Value = mPrevMyTextBoxValue
'If Cancel Then Me.MyTextBox.Text = mPrevMyTextBoxValue
End Sub
Attempts to assign the previous value to either the .Value or .Text property of the textbox result in the same error message:
The macro or function set to the BeforeUpdate or ValidationRule property for this field is preventing {Program Name} from saving the data in the field.
OPTION E: Explicitly restore old value in AfterUpdate event
Private mPrevMyTextBoxValue As Variant
Private Sub MyTextBox_AfterUpdate()
If DataIsInvalid(Me.MyTextBox.Value) Then
Me.MyTextBox.Value = mPrevMyTextBoxValue
Me.MyTextBox.SetFocus
Else
mPrevMyTextBoxValue = Me.MyTextBox.Value
End If
End Sub
This is really close to the desired behavior. Unfortunately, it's impossible to keep the focus on the control because the AfterUpdate event runs before the Tab/Enter keypress or mouse-click events are processed. So even if we try to force the focus to the proper control (via the .SetFocus statement above), the program will immediately shift the focus to the control the user selected.
It seems to me that the "right" way to do this is to use the .Undo method of the control. That does not work for unbound controls, though. This is an inexplicable shortcoming, especially given the fact that an Escape key-press performs this functionality for an unbound field.
Is there a better way to do this or should I just stick to using SendKeys?
After getting to page 3 on google I decided to just muck around and see what sort of ordering happens when trying your Option E. Below is the best workaround method I was able to use to get focus to "Stay" on the textbox in question.
Private mPrevMyTextBoxValue As Variant
Private Sub Text0_AfterUpdate()
If Me.Text0.Value = 0 Then
Me.Text0.Value = mPrevMyTextBoxValue
Me.Text12.SetFocus
Me.Text0.SetFocus
Else
mPrevMyTextBoxValue = Me.Text0.Value
End If
End Sub
0 simulates that it failed the validation. It seems like if you set focus to something else before setting it back to the textbox you are working with it will stay there. I don't have an answer as to why unfortunately.
Edit: I have decided to try to program my theory as to how this works.
Private blnGoToNextControl as Boolean
Private Function SetFocus(ctrl As control)
blnGoToNextControl = True
If ctrl.HasFocus = True Then
'Do nothing
Else
ctrl.HasFocus = True
blnGoToNextControl = False
End If
End Function
This is my idea of how the SetFocus function works. So then after the AfterUpdate event runs it would check to see if the flag to go to next control is and see that it is set to false and not go to the next control.
Rough coding obviously but hopefully this gets my theory across?
If it is unbound, why not use the AfterUpdate event:
Private Sub MyTextBox_AfterUpdate()
If DataIsInvalid(Me!MyTextBox.Value) Then
Me!MyTextBox.Value = Null
Me!MyTextBox.SetFocus
End If
End Sub
or modify your other solution:
Private Sub MyTextBox_AfterUpdate()
Static mPrevMyTextBoxValue As Variant
If IsEmpty(mPrevMyTextBoxValue) Then
mPrevMyTextBoxValue = Null
End If
If DataIsInvalid(Me!MyTextBox.Value) Then
Me!MyTextBox.Value = mPrevMyTextBoxValue
Me!MyTextBox.SetFocus
Else
mPrevMyTextBoxValue = Me!MyTextBox.Value
End If
End Sub
Try moving the focus off the textbox, then back:
Me!MyTextBox.Value = mPrevMyTextBoxValue
Me!SomeOtherControl.SetFocus
Me!MyTextBox.SetFocus
That someothercontrol can be a tiny nearly hidden textbox.
I'm trying to modify existing code to add a popup box. This popup box is another form, and when a user clicks on a button on this form, I want a textbox on the base form to be populated. After that the popup disappears and then I need to access that value from the textbox on the base form.
The sequence should be:
Base form button click calls modal popup
Click in button on popup saves value to base form's textbox, then returns control.
Base form then uses this value to do something.
Base Form
Sub base()
DoCmd.OpenForm "PaperType", , , , , acDialog
MsgBox Me.TheAnswer 'This line gives a null error
End Sub
Popup Form
Private Sub btnRolls_Click()
'Me.Tag = 1
Forms!ReceiptDetail_sfrm!TheAnswer = 1
Me.Visible = False
End Sub
Private Sub btnSheets_Click()
'Me.Tag = 4
Forms!("ReceiptDetail_sfrm").TheAnswer = 4
Me.Visible = False
End Sub
You can do it that way, you probably need something like:
Private Sub btnRolls_Click()
Forms!ReceiptDetail_sfrm!TheAnswer = 1
Forms!ReceiptDetail_sfrm.Refresh
Me.Visible = False
End Sub
I've done what you're doing many times. I'm not at work to check my code right now for an example, but it's doable.
What I tend to do is hide the popup, then read from it:
Main Form:
Private Sub base()
DoCmd.OpenForm "PaperType", , , , , acDialog
'code waits for modal hide here
Me!TheAnswer = Forms("PaperType").SomethingOnThatFormThatStoresTheValue
DoCmd.Close acForm, "PaperType", acSaveNo
MsgBox Me.TheAnswer
End Sub
Popup
Private Sub btnRolls_Click
'may be hidden control
Me.SomethingOnThatFormThatStoresTheValue = TheValueToRead
Me.Visible = False
End Sub
Make sure that either A) Your popup can't be closed from the form itself, or B) Your calling code will handle the error of trying to read something that's no longer loaded (or both).
Apparently the correct answer is: "Don't do it this way!". Instead of trying to pass data between the forms, which is a pain, I made a table in Access which only has 1 field in 1 record. Then I store the value in there using DoCmd.RunSQL, and retrieve it from the other form using DLOOKUP().