Prevent multiline in MS Access text field? - vba

I want to prevent the user from entering multiline text in an MS Access text field (by pressing CTRL+Enter). There does not seem to be a multiline true/false property.
Currently i just cancel out the keypress, but this seems to be a little fishy... Is there a more professional way?
Private Sub Adr_Nachname_KeyPress(KeyAscii As Integer)
If KeyAscii = vbKeyReturn Or KeyAscii = 10 Then
KeyAscii = 0
End If
End Sub

Related

How do I check if a value a user is entering in Textbox is a numeric double?

I am trying to check if a user enters a number value in a textbox, decimal places accepted. Any help is highly appreciated.
Private Sub textbox1_AfterUpdate()
If IsNumeric(textbox1.Value) = False Then
Me!textbox1.Undo
MsgBox "only numbers are allowed"
Exit Sub
End If
Exit Sub
using BeforeUpdate event:
Private Sub textbox1_BeforeUpdate(Cancel As Integer)
If IsNumeric(textbox1.Value) = False Then
MsgBox "only numbers are allowed"
Me!textbox1.Undo
Cancel = True
Exit Sub
End If
Exit Sub
My current code does not execute at all. I have also tried it in the textbox1_BeforeUpdate event. Please see code.
New Code:
Public Function IsValidKeyAscii(ByVal keyAscii As Integer, ByVal value As
String) As Boolean
IsValidKeyAscii = (keyAscii = vbKeyDot And InStr(1, value, Chr$(vbKeyDot)) =
0) Or (keyAscii >= vbKey0 And keyAscii <= vbKey9)
End Function
Private Sub textbox1_KeyDown(KeyCode As Integer, Shift As Integer)
If Not IsValidKeyAscii(KeyCode, textbox1.value) Then KeyCode = 0
End Sub
You shouldn't be using VBA for this task at all.
Just set the field format property to General number. That's the built-in way to ensure users can only enter numbers in a field.
Write a validator function (could be in its own KeyInputValidator class or module), so you can reuse this logic everywhere you need it, instead of copy/pasting it for every numeric textbox you need:
Option Explicit
Private Const vbKeyDot As Integer = 46
'#Description("returns true if specified keyAscii is a number, or if it's a dot and value doesn't already contain one")
Public Function IsValidKeyAscii(ByVal keyAscii As Integer, ByVal value As String) As Boolean
IsValidKeyAscii = (keyAscii = vbKeyDot And InStr(1, value, Chr$(vbKeyDot)) = 0) Or (keyAscii >= vbKey0 And keyAscii <= vbKey9)
End Function
Then use it in the textboxes' KeyPress event handler (assuming this is a MSForms textbox control) to determine whether or not to accept the input - since the event provides a MSForms.ReturnInteger object, that object's Value property can be set to 0 to "swallow" a keypress:
Private Sub TextBox1_KeyPress(ByVal keyAscii As MSForms.ReturnInteger)
If Not IsValidKeyAscii(keyAscii.Value, TextBox1.value) Then keyAscii.Value = 0
End Sub
That way you don't need to undo any inputs, or pop any annoying warning or message boxes: the value in the field is guaranteed to be a valid numeric value!
EDIT the above event handler signature is for a MSForms control. Looks like Access uses a different interface:
Private Sub TextBox1_KeyDown(KeyCode As Integer, Shift As Integer)
Here the KeyCode is passed ByRef, so you can alter it directly. In other words, this becomes the logic:
If Not IsValidKeyAscii(KeyCode, TextBox1.value) Then KeyCode = 0
You can try using the lost focus event:
Private Sub TextBox1_LostFocus()
Dim blnNumber As Boolean
Dim strNumber As String
strNumber = TextBox1.Value
blnNumber = IsNumeric(strNumber)
If Not blnNumber Then
Me!TextBox1.Undo
MsgBox "only numbers are allowed"
Else
'And, if you want to force a decimal.
If InStr(strNumber, ".") < 1 Then
Me!TextBox1.Undo
MsgBox "only doubles are allowed"
End If
End If
End Sub
Also, check the Textbox1 element that you have listed in access. Is it's name TextBox1? or something else?
For example, in excel it is represented like the following: =EMBED("Forms.TextBox.1","") even though the name that the code references is TextBox1.

How to set tab order by a macro in MS Word?

I have a MS Word form with ActiveX control (not the form control). Suppose I have two textboxes and two option button as follows:
Name: [textBox1]
Address: [textBox2]
Gender: [opt1] Male [opt2] Female
Now if I want a tab order, I have to add following macro:
Private Sub textBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Then
textBox2.Activate
End If
End Sub
Private Sub textBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Then
opt1.Activate
End If
End Sub
Private Sub opt1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = 9 Then
opt2.Activate
End If
End Sub
Now in my real form there are 20 text boxes and 12 option buttons, so it is quite boring to write down keydown event for each form field. How can I write a macro so that it will first get the name of current form field on keydown (and validating it as tab keydown) and then go to next form field?
For the sake of tab order, I will then rename all form field chronologically such as field1, field2, field3......... etc, so that with an increment the code can move the tab to next form field.
Here is the screen shot of ActiveX tools those I used in forms:
I have cross-posted this topic to VbaExpress forum also.
You aren't going to be any happier with this answer than you were with my last...
The problem is that the keypress, or KeyDown, is only triggered by the fact that the focus is in an ActiveX control, and will be specific to that control. So you have no choice than a KeyDown event for every control. You can keep the code in the event to a minimum, but...
There's no way to identify controls on a document surface directly by name as a string. ThisDocument.ControlName is possible, but there's nothing like ThisDocument.Controls("ControlName") available that would let you substitute names, nor allow you to identify the name of the current control.
There is a way to do it, but it's convoluted. Since these are in-line with the text (no text wrapping) they belong to the document's InlineShapes collection. Their programming interface can only be addressed through the InlineShape's OLEFormat.Object property. This means the code needs to loop the InlineShapes collection twice: once to identify the ActiveX control where the key was pressed, once to identify the control which should be next.
The following code illustrates the principle. What it does not do is
work for more than 9 controls - that would require code that checks, from the right of the name, how many characters are numerical
go back to the first control if focus is in the last
Note that it might be possible to get around event code for each control. It would involve using the Windows API, which means it would fire every time the user presses Tab. But I have no idea whether the key presses would be captured when focus is inside a control. And you would have to test each time if this is the case - and you'd still have to be able to identify which control the focus is in.
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
GoToNextControl KeyCode, ThisDocument.TextBox1.Name
End Sub
Private Sub TextBox2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
GoToNextControl KeyCode, ThisDocument.TextBox2.Name
End Sub
Sub GoToNextControl(KeyCode As MSForms.ReturnInteger, controlName As String)
Dim ils As Word.InlineShape, ils2 As Word.InlineShape
Dim c As MSForms.Control
Dim baseName As String, nextName
Dim nameCounter As Long
baseName = Mid(controlName, 1, Len(controlName) - 1)
nameCounter = Right(controlName, 1)
If KeyCode = 9 Then
For Each ils In ThisDocument.InlineShapes
If ils.Type = wdInlineShapeOLEControlObject Then
If ils.OLEFormat.Object.Name = controlName Then
nextName = baseName & nameCounter + 1
For Each ils2 In ThisDocument.InlineShapes
If ils2.Type = wdInlineShapeOLEControlObject Then
If ils2.OLEFormat.Object.Name = nextName Then
ils2.Select
Exit Sub
End If
End If
Next
End If
End If
Next
End If
End Sub
All-in-all it might make more sense to stick to the legacy form fields or to content controls, or move this to a UserForm that then writes to the document.

Excel VBA Userform If Focus Changes Trigger

I have a couple user forms in VBA, id like to add a feature that when a user first clicks on a textbox (changes the focus to it), any text inside gets selected. I've seen this feature in some accounting applications and in your web browser when you first click the URL bar. Its essentially meant so that users can immediately overwrite a text field. Was wondering how I might do the same in VBA, but I'm still a novice. I looked through a couple sub triggers(dont know the correct term) but haven't seen any. I found one for when you click the text box but I don't want the text constantly being selected every time I click the field.
Thanks.
put this in your textbox event
Dim checked As Boolean
Private Sub TextBox1_Change()
If checked = True Then
TextBox1.SelStart = 0
TextBox1.SelLength = 0
checked = True
End If
End Sub
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
checked = False
End Sub
Private Sub TextBox1_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
If checked = False Then
TextBox1.SelStart = 0
TextBox1.SelLength = Len(TextBox1)
checked = True
End If
End Sub
once you click your textbox, it will hightlight the text, if you click the text, it will unhightlight and allow you to modified the text. if you click outside that textbox and click back inside that will rehighlight the whole text.

Preventing debugger when value is deleted from VBA textbox

My user form has several textbox's that can be edited by the user but it was reported to me that it was debugging. After a bit of investigation i found that the user was deleting the value out of the text box and this was causing a run-time error 13. How do i stop the run-time error if the user deletes the value and the servcredit textbox becomes a vbnullstring?
at present the text box has the 2 below pieces of code.
This inputs the numerical value into the excel sheets in the back.
Private Sub ServCredit_Change()
Worksheets("Calculator").Range("L18") = CDec(ServCredit)
End Sub
This ensure the user doesn't input a none numerical figure.
Private Sub ServCredit_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If (KeyAscii > 47 And KeyAscii < 58) Or KeyAscii = 46 Or KeyAscii = 32 Then
KeyAscii = KeyAscii
Else
KeyAscii = 0
MsgBox "Invalid Key Pressed"
End If
End Sub
You could simply test if there is a value:
Private Sub ServCredit_Change()
If Len(ServCredit.Text) <> 0 then
Worksheets("Calculator").Range("L18").Value2 = CDec(ServCredit)
Else
Worksheets("Calculator").Range("L18").Value2 = vbnullstring
end if
End Sub
You first need to check if ServCredit is numeric. CDec cannot cast a vbNullString into a number.
If IsNumeric(ServCredit) then
Worksheets("Calculator").Range("L18") = CDec(ServCredit)
else
Worksheets("Calculator").Range("L18") = 0
End If

Handling / Performing / Managing tasks in Userform with the help of keyboard ( shortcut keys )

I have a User-form
For most of Check-Boxes/ Buttons I assigned a Key. Can be execute by pressing:
Alt + Assigned-key
I had googled the following code.
Private Sub UserForm_Initialize()
Me.PASTE.Accelerator = "V"
Me.CEEMEA.Accelerator = "C"
End Sub
Problem is I have to Press Alt key to perform any given task.
Q. Is there any short way of doing this without pressing AltKey?
My progress After Robin's Original-Answer
Firstly I set focus on Macros Button.
Private Sub UserForm_Initialize()
Me.Macros.SetFocus
End Sub
Then on Macro_Keydown Event I put the following code.
Private Sub Macros_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode = vbKeyB Then
Bulgaria.Value = Not Bulgaria.Value
ElseIf KeyCode = vbKeyE Then
Estonia.Value = Not Estonia.Value
ElseIf KeyCode = vbKeyH Then
Hungary.Value = Not Hungary.Value
ElseIf KeyCode = vbKeyA Then
Latvia.Value = Not Latvia.Value
ElseIf KeyCode = vbKeyL Then
Lithuania.Value = Not Lithuania.Value
ElseIf KeyCode = vbKeyM Then
Macedonia.Value = Not Macedonia.Value
ElseIf KeyCode = vbKeyP Then
Poland.Value = Not Poland.Value
ElseIf KeyCode = vbKeyR Then
Romania.Value = Not Romania.Value
ElseIf KeyCode = vbKeyU Then
Ukraine.Value = Not Ukraine.Value
End If
End Sub
Updated answer
The original answer didn't really meet the brief because whilst handling the UserForm events for e.g. KeyDown works for a form with no other controls, it doesn't work for a form with controls. This is because the event only works when the form has the focus. When the form has other controls, it never receives the focus. Also, it is not possible to set the focus onto the UserForm. Almost all forms will have some other controls, so the original answer is practically useless. So let's shamelessly adapt an idea from Andy Pope on MSDN to meet the OP's requirements.
First, insert a VBA Class into the project with this code:
Public WithEvents m_objGroupCheckBox As MSForms.CheckBox
Private Sub m_objGroupCheckBox_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
MsgBox "Keypress was: " & Chr(KeyCode) & " on " & m_objGroupCheckBox.Caption
Select Case Chr(KeyCode)
Case 1:
UserForm1.CheckBox1.Value = Not UserForm1.CheckBox1.Value
Case 2:
UserForm1.CheckBox2.Value = Not UserForm1.CheckBox2.Value
Case "3"
UserForm1.CheckBox3.Value = Not UserForm1.CheckBox3.Value
End Select
End Sub
The Class defines a generic event handler for a CheckBox on the UserForm. For the purposes of this example, we will make key presses of 1, 2 and 3 toggle the checkbox state for the 3 CheckBoxs on the form.
Second, put the code in the Userform's initialize event. It creates a collection of this custom class that references back to the original checkboxes created on the UserForm.
Private m_colCheckBoxes As Collection
Private Sub UserForm_Initialize()
Dim lngIndex As Long
Dim objGroupCheckBox As clsGroupCheckBox
Set m_colCheckBoxes = New Collection
For lngIndex = 1 To 3
Set objGroupCheckBox = New clsGroupCheckBox
Set objGroupCheckBox.m_objGroupCheckBox = Me.Controls("CheckBox" & lngIndex)
m_colCheckBoxes.Add objGroupCheckBox, CStr(m_colCheckBoxes.Count + 1)
Next
End Sub
So now, if we have a UserForm in the designer like this, with each CheckBox named CheckBox1, CheckBox2 and CheckBox3:
Then, our generic event handler will allow us to define a single place to handle the KeyDown event and set CheckBox status in one spot.
Original answer - not as useful as it looks :(
You can directly handle the KeyDown event of the UserForm and enter your specific logic in there. Maybe you should check out KeyUp and KeyPress as well depending on how you think the form will work.
MSDN notes that '..."A" and "a" are returned as the same key. They have the identical keycode value. But note that "1" on the typewriter keys and "1" on the numeric keypad are returned as different keys, even though they generate the same character.' - MSDN Link
You can handle SHIFT, CTRL and ALT as well.
Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
If KeyCode >= vbKeyA And KeyCode <= vbKeyZ Then
MsgBox "You pressed " & Chr(KeyCode)
ElseIf KeyCode >= vbKeyF1 And KeyCode <= vbKeyF12 Then
MsgBox "Function time!"
End If
End Sub
'VBA Shortcut Keys not work in UserForm [Partially Solved]
Public Sub CallSub() 'code must be in Module
'-do this code-
Private Sub Workbook_Activate() 'code must be in (ThisWorkbook)
Application.OnKey "^{f5}", "callSub"
'^ this code only work with Excel Worksheet not in Userform
Private Sub XxX_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer) 'code must be in Userform with SHOWMODAL = False
If KeyCode = 17 Then AppActivate "microsoft excel"
'XxX means all CommandButton and Textbox and Listbox and Combobox
'Keycode 17 is Ctrl Key if you are using Ctrl+F5 - when you press Ctrl it will activate Excel Worksheet