How to move cursor in text box with enter in text box?
Here is my code, it gives me a syntax error.
Private Sub TextBox2_Change()
Sheets("30").Range("D18") = TextBox2.Value
TextBox2.Enter Then Sheets("30").Range("E19").Select
End Sub
Instead of using the Change event, use the KeyUp event and check for the KeyCode vbKeyReturn:
Private Sub TextBox2_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = KeyCodeConstants.vbKeyReturn Then
Sheets("30").Range("E19").Select
End If
End Sub
Related
I have a textbox control in a subForm which is a singleForm. However, when I press enter key it adds a new record and the previous record hides away. I have the form property already set to current record.
I used the code below to trap enter key, that works.
Private Sub txt_1_KeyDown (KeyCode As Intger, Shift as Integer)
Select case KeyCode
Case vbKeyCode
KeyCode = 0
Me.parent.Combo.SetFocus
End Select
End Sub
However, now I cannot add a new line using Ctrl + Enter within the textbox since the code fires as soon as I press enter. Can someone help how to change the code above so that it only traps enter key and keeps the default Access behavior of adding new line on pressing Ctrl + Enter.
You will need a conditional expression testing that:
The Enter key (ASCII character 13) has been pressed
The Shift argument of the event handler is zero, indicating no Ctrl, Shift, Alt have been pressed in conjunction with the Enter key.
The code might look something like this:
Private Sub txt_1_KeyDown(KeyCode As Intger, Shift As Integer)
If KeyCode = 13 And Shift = 0 Then
KeyCode = 0
Me.Parent.Combo.SetFocus
End If
End Sub
You need to check for the Shift argument like this:
Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = vbKeyReturn Then
If Not Shift = acCtrlMask Then
MsgBox "Enter"
KeyCode = 0
Me.parent.Combo.SetFocus
End If
End If
End Sub
Try checking for the key code:
Private Sub txt_1_KeyDown(KeyCode As Intger, Shift as Integer)
Select Case KeyCode
Case vbKeyEnter
KeyCode = 0
Me.parent.Combo.SetFocus
Case Else
' Leave key code as is.
End Select
End Sub
I have to set ActiveX control tab order in MS Word using VBA. So here is the basic code:
Private Sub radioFull_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
If KeyCode = 9 Then
radioIntern.Activate
End If
End Sub
Problem is I have an active Restrict Editing Protection on the document set by password. Thus after starting protection, while pressing a tab on any control, it deny to functioning saying that I have a protection on the document.
So, during execution of the above function, I first have to un-protect the document, moving tab to next field and then re-protect by the following function:
Private Sub ToggleProtect()
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:="password"
Else
ActiveDocument.Protect Password:="password", NoReset:=True, _
Type:=wdAllowOnlyFormFields, _
UseIRM:=False, EnforceStyleLock:=False
End If
End Sub
Private Sub radioFull_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
If KeyCode = 9 Then
ToggleProtect
radioIntern.Activate
ToggleProtect
End If
End Sub
It works well. So I intend to shorten the main code a little bit more by something like this:
Private Sub radioFull_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
tabOrder(KeyCode, controlName)
End Sub
and the tabOrder function in this case like the follwoing:
Public Sub tabOrder(K as integer,t as string)
If KeyCode = K Then
ToggleProtect
t.Activate
ToggleProtect
End If
End Sub
But I am not familiar on VBA function argument. So please tell me how to pass the argument or write the function correctly so that I can maintain tab order in MS Word form?
Even though the MS Forms controls are derived from MSForms.Control VBA is apparently unable to "cast" them to this data type. It can work with the general type, however. The trick is to declare the procedure argument as data type Variant.
While I was at it, I made another small optimization to the code by declaring an object variable of type Word.Document for passing the document to ToggleProtect. While it's unlikely, it is theoretically possible that the user will change documents during code execution, making the ActiveDocument a different one than that which triggered the code. So if you get the target document immediately then the code will always execute on the correct document, no matter which one currently has the focus.
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
Dim doc As Word.Document
Set doc = Me
tabOrder KeyCode, doc, Me.TextBox1
End Sub
Public Sub tabOrder(ByVal KeyCode As MSForms.ReturnInteger, _
ByRef doc As Word.Document, ByRef t As Variant)
If KeyCode = 9 Then
ToggleProtect doc
t.Activate
ToggleProtect doc
End If
End Sub
Private Sub ToggleProtect(doc As Word.Document)
If doc.ProtectionType <> wdNoProtection Then
doc.Unprotect Password:="password"
Else
doc.Protect Password:="password", NoReset:=True, _
Type:=wdAllowOnlyFormFields, _
UseIRM:=False, EnforceStyleLock:=False
End If
End Sub
In your KeyDown event, it looks like you want to pass the KeyCode and the Control. Therefore, the arguments you pass must match the signature of the tabOrder sub. Look how KeyCode is defined and copy/paste to your tabOrder sub. The second argument will be defined as Control allowing for any control to be passed. Here is an example of what I am talking about:
Private Sub radioFull_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
tabOrder KeyCode, radioFull
End Sub
Public Sub tabOrder(ByVal KeyCode As MSForms.ReturnInteger, ByRef t As MSForms.Control)
If KeyCode = 9 Then
ToggleProtect
t.Activate
ToggleProtect
End If
End Sub
I've built a form in Excel. It consists of 3 command buttons and a frame containing checkboxes. The checkboxes are dynamically populated at userform_initialize based on tables in an excel sheet (the idea being easy user customization). The reason for the frame is that there can be a lot of checkboxes and I want the user to be able to scroll through them.
My goal now is to create keyboard shortcuts for the form. Where I get stuck is that I can't brute force write KeyDown handlers for each of the checkboxes because I don't know which ones will exist. I realize that it would also just be better if I could have the event handler at the form level. Googling has found me the form's KeyPreview property. Unfortunately, the properties window in VBA IDE doesn't show it and when I try to access it programmatically by setting Me.KeyPreview = True at userform_initialize VBA throws a compile error: "Method or data member not found" - what I would expect given it isn't in the properties window, but was worth a try.
I feel like there's something I'm obviously missing so I thought I'd ask before spending time learning how to write and then rewriting the form entirely as a class as in the MSDN example code:
https://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview(v=vs.110).aspx.
Am I that lucky?
I confess to being at the limit of my VBA knowledge and I'm looking to go expand on it. Any general concepts or context I should red would be greatly appreciated.
UPDATE
I'm now thinking about GetAsyncKeyState and Application.Onkey.
From what I understand, GetAsyncKeyState only works within an infinite DoEvents loop. I tried initiating one hoping the form would still load but of course it didn’t – I’m stuck in the loop.
The problem with Application.Onkey is that I can't assign the event function to the key within the userform module. This puzzles me because other event handlers can go in the userform module. In fact, I’d put it in the Userform_Initialize procedure. Is it because it's not a form event but an application event?
EDIT
I seem to have something that works, but for the strange issue described here:
Event handling class will not fire unless I use a breakpoint when initializing form
Thank you #UGP
Here is an example how it could work, found here:
To put in a class named "KeyPreview":
Option Explicit
Dim WithEvents u As MSForms.UserForm
Dim WithEvents t As MSForms.TextBox
Dim WithEvents ob As MSForms.OptionButton
Dim WithEvents lb As MSForms.ListBox
Dim WithEvents dp As MSComCtl2.DTPicker
Event KeyDown(ByVal KeyCode As Integer, ByVal Shift As Integer)
'Event KeyPress(ByVal KeyAscii As Integer)
Private FireOnThisKeyCode As Integer
Friend Sub AddToPreview(Parent As UserForm, KeyCode As Integer)
Dim c As Control
Set u = Parent
FireOnThisKeyCode = KeyCode
For Each c In Parent.Controls
Select Case TypeName(c)
Case "TextBox"
Set t = c
Case "OptionButton"
Set ob = c
Case "ListBox"
Set lb = c
Case "DTPicker"
Set dp = c
End Select
Next c
End Sub
Private Sub u_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift)
End Sub
Private Sub t_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift)
End Sub
Private Sub ob_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift)
End Sub
Private Sub lb_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift)
End Sub
Private Sub dp_KeyDown(KeyCode As Integer, ByVal Shift As Integer)
If KeyCode = FireOnThisKeyCode Then RaiseEvent KeyDown(KeyCode, Shift)
End Sub
To put in the userform:
Option Explicit
Dim WithEvents kp As KeyPreview
Private Sub UserForm_Initialize()
Set kp = New KeyPreview
kp.AddToPreview Me, 114
End Sub
Private Sub kp_KeyDown(ByVal KeyCode As Integer, ByVal Shift As Integer)
MsgBox "F3 was pressed..."
End Sub
It works with TextBoxes, OptionButtons, ListBoxes and DTPickers. Other Controls that could get focus will need to be handled aswell.
I'm wondering is there a way to detect if a specific key (like backspace) was pressed. This is what I'm shooting for:
Private Sub SomeTextBox_Change()
If len(Me.SomeTextBox.Value) = 3 and KEYPRESSED is NOT BACKSPACE Then
<.......Code Here>
Else
<.......Code Here>
End if
End Sub
You should use KeyPress event instead of Change event:
Private Sub TextBox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If Len(Me.SomeTextBox.Value) = 3 And KeyAscii <> 8 Then 'Backspace has keycode = 8.
<.......Code Here>
Else
<.......Code Here>
End If
End Sub
Full list of keycodes you can find here: http://www.asciitable.com/
This example assigns "InsertProc" to the key sequence CTRL+PLUS SIGN and assigns "SpecialPrintProc" to the key sequence SHIFT+CTRL+RIGHT ARROW.
Application.OnKey "^{+}", "InsertProc"
Application.OnKey "+^{RIGHT}","SpecialPrintProc"
for more examples and infos go on : https://msdn.microsoft.com/en-us/library/office/aa195807%28v=office.11%29.aspx
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode.Value = vbKeyF1 Then
MsgBox "F1 is pressed"
End If
End Sub
You should use KeyPress event instead :
Private Sub SomeTextBox_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If Len(Me.SomeTextBox.Value) = 3 And KeyAscii <> vbKeyBack Then
'<.......Code Here>
Else
'<.......Code Here>
End If
End Sub
And you can use KeyAscii = 0 to cancel the key that was entered!
Find a list of all Ascii values here http://www.asciitable.com/
I am trying to use the ActiveX ComboBox in excel. Everything works fine to the point of being populated from the drop down button click_event. But when it set the click event I find it is triggered even from keystrokes like the Arrow keys. Is this normal behavior, and if so how can I bypass this?
I am working on Excel 2007 VBA
This is the method i used to allow navigating in the combo box using keys , i will wait to see if there is a better solution.. : lastkey is a public variable
Private Sub ComboBox1_KeyDown(ByVal KeyCode As _
MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 38 Then
If ComboBox1.ListIndex <> 0 Then
lastkey = KeyCode
ComboBox1.ListIndex = ComboBox1.ListIndex - 1
KeyCode = 0
End If
ElseIf KeyCode = 40 Then
If ComboBox1.ListIndex <> ComboBox1.ListCount - 1 Then
lastkey = KeyCode
ComboBox1.ListIndex = ComboBox1.ListIndex + 1
KeyCode = 0
End If
End If
End Sub
Private Sub ComboBox1_Click()
If lastkey = 38 Or lastkey = 40 Then
Exit Sub
Else
MsgBox "click"
End If
End Sub
Yes this is normal behavior. Using the arrow keys navigates the items in the combo and hence the click event is fired.
To bypass that insert this code. This captures all the 4 arrow keys and does nothing when it is pressed. The only drawback of this method is that you will not be able to navigate using the Arrow keys anymore.
Private Sub ComboBox1_KeyDown(ByVal KeyCode As _
MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 37 To 40: KeyCode = 0
End Select
End Sub
FOLLOWUP
Dim ArKeysPressed As Boolean
Private Sub ComboBox1_Click()
If ArKeysPressed = False Then
MsgBox "Arrow key was not pressed"
'~~> Rest of Code
Else
ArKeysPressed = False
End If
End Sub
Private Sub ComboBox1_KeyDown(ByVal KeyCode As _
MSForms.ReturnInteger, ByVal Shift As Integer)
Select Case KeyCode
Case 37 To 40: ArKeysPressed = True
End Select
End Sub