Wait for data to be input then run sub. - vba

I need a very simple system that saves a bar code number to a sheet every time it is scanned. It works great but I have to click a cmd button in between each scan or hit enter. Is there any was I could use the execute after the text box changes? But if I use the
Private Sub txtCode_Change()
As a title then it only takes the first number of the code and uses that instead of waiting the .25 seconds for the rest of the bar code to be imputed. Any ideas or help would be greatly appreciated.

You probably can configure your bar-code scanner to send an Enter or a Tab key after the scanned bar-code.
If your scanner sends a Tab key, you can use the TextBox_AfterUpdate event:
Private Sub txtCode_AfterUpdate()
'Do something.
End Sub
If your scanner sends an Enter key, you can use the TextBox_KeyDown event:
Private Sub txtCode_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, _
ByVal Shift As Integer)
If KeyCode = vbKeyReturn Then
'Do something.
End If
End Sub
If your bar-code is a fixed-length string, you can still use the TextBox_Change event like the following:
Private Const BARCODE_LENGTH As Integer = 12
Private Sub txtCode_Change()
If Len(txtCode.Text) = BARCODE_LENGTH Then
'Do something
End If
End Sub
Hope that helps.

Related

Empty pre-filled TextBox on MouseDown/MouseUp only FirstTime

I'm newbie in word-vba (just to let you know that my question could be really stupid).
I would like to clear a textbox only when I click in the textbox the first time.
I've tried For... Next but I wasn't able to comfigure it correctly
Private Sub SWName_Field_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
SWName_Field.Text = ""
End Sub
I would like that the code will work exactly the same way it works but when I put some text and for example the user make a mistake or typo error the second click in the textbox shouldn't clear the text inside.
Thank you for the support
There's no inbuilt activity state identifier in any UserForm control. So you need to use meta data to specify and identify whether or not your mousedown is happening for the first time.
Use Tag property of the control for that.
See the code comments for details.
Private Sub TextBox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
'/ Use the Tag field to determine and store the state of Text Box.
If Len(Me.TextBox1.Tag) < 1 Then
'/ If Mousedown for the very first time then TextBox's tag is empty.
'/ Go ahead, clean the textbox.
'/ And set a text in tag.
Me.TextBox1.Text = ""
Me.TextBox1.Tag = "Text Cleared"
End If
End Sub
You can use a Static local variable to "remember" whether the handler was executed at least once or not:
Private Sub SWName_Field_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Static executed As Boolean
If Not executed Then
SWName_Field.Text = ""
executed = True
End If
End Sub
The state of the Static local is tied to your UserForm instance - the value will be "remembered" for as long as the form instance is alive.
This means, if you're showing the form's default instance, the state won't necessarily be reset. You will want to ensure you get a fresh default form state every time the form is shown, not just the first time - to do this you New up the form:
With New UserForm1
.Show
End With
If you just do UserForm1.Show, then you don't control when the form instance gets created - VBA does.
You'll also want to control when the form instance gets destroyed - you can do that by handling the form's QueryClose event:
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = VbQueryClose.vbFormControlMenu Then
Cancel = True ' cancel the destruction of the object
Me.Hide ' hide the instance instead
End If
End Sub
With that, the object will be destroyed when execution reaches End With. Without it, the object will be destroyed if the user clicks the "X" button, and you probably don't want that to happen (especially if you need to access the form's state after it's closed).

Detect click on textbox in form

I want a certain function to be run every time someone clicks on a textbox in my form. So far I have managed to detect when it gets focus and when it is doubleclicked, using the following two eventhandlers, but I am unsure about how to catch when it is clicked once while it already has focus.
Does anyone here have any experience with catching such an event? I don't seem to find any obvious suspects in the dropdown-menus of the VBA editor.
Private Sub tbxTil_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
Me.tbxTil = format(oppdater_dato(CDate(Me.tbxTil)), "dd.mm.yy", vbMonday, vbFirstFourDays)
End Sub
Private Sub tbxTil_Enter()
Me.tbxTil = format(oppdater_dato(CDate(Me.tbxTil)), "dd.mm.yy", vbMonday, vbFirstFourDays)
End Sub
You can use the Mouse events, something like this:
Private Sub tbxTil_MouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
MsgBox "Click"
End Sub

Listen to key press when the program is in the background

I am currently working with a program which is supposed to run in the background but also check if "mod + o" is pressed then do something. But I cannot figure out how a vb.net program can listen to key presses when the program is not Selected / Opened.
You can use P/Invocation to be able to use WinAPI's GetAsyncKeyState() function, then check that in a timer.
<DllImport("user32.dll")> _
Public Shared Function GetAsyncKeyState(ByVal vKey As System.Windows.Forms.Keys) As Short
End Function
Const KeyDownBit As Integer = &H8000
Private Sub Timer1_Tick(sender As Object, e As System.EventArgs) Handles Timer1.Tick
If (GetAsyncKeyState(Keys.LWin) And KeyDownBit) = KeyDownBit AndAlso (GetAsyncKeyState(Keys.O) And KeyDownBit) = KeyDownBit Then
'Do whatever you want when 'Mod + O' is held down.
End If
End Sub
EDIT:
To make the code only execute one time per key press, you can add a little While-loop to run until either of the buttons are released (add it inside your If-statement):
While GetAsyncKeyState(Keys.LWin) AndAlso GetAsyncKeyState(Keys.O)
End While
This will stop your code from executing more than once while you hold the keys down.
When using this in a Console Application just replace every System.Windows.Forms.Keys and Keys with ConsoleKey, and replace LWin with LeftWindows.

One column in a vb.net Datagridview should not allow paste of non-integers

I have a datagridview and one of the columns is a Quantity column that should only allow integers. No negative symbols or decimal points. I have prevented the user from typing in any characters but they can paste them in. I could stop this in validation but I would ideally like to not even show characters that are pasted in. How would I detect and remove pasted in letters and in what event?
Ideally I would also like for only the paste to not work, so if the field already had a 2 in it and they pasted "test" then the 2 would remain, although that isn't as important.
Here's one approach:
'Set a flag to show when the form has finished initialising
Dim initialising As Boolean = True
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Form is initialised so set boolean to false
initialising = False
End Sub
Private Sub DataGridView1_CellValueChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellValueChanged
'Only process once the form is initialised as values don't exist yet!
If Not initialising Then
If Not IsNothing(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value) Then
'If the clipboard contains text
If Clipboard.ContainsText Then
' Check to see if the value of the cell matches whats in the clipboard
If CStr(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value) = Clipboard.GetText Then
'You know its been pasted
If Not IsNumeric(CStr(DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex).Value)) Then
'This value should be rejected
Else
'This value is allowed
End If
End If
End If
End If
End If
End Sub
See my commentated code for an explanation.
I'm not sure you will want to do it on this event as it doesn't fire the event until the user leaves the cell. Hopefully however my approach of checking the value against what is in the clipboard might help you to identify if its a pasted value.
You'd have to implement a validating method and call it in some of the DataGridView's events (I'm thinking KeyDown/Keypress and MouseClick).
I think it's bad practice, because you'll be struggling to find more ways in which the user can trick your application; most apps nowadays let the user input whatever they want, but keep the user from completing her task until she has sanitized her input. Most also give clear on-screen instructions on how to do so.
Something like this
Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
End Sub

Multiple questions for Visual Basic

How would I do the following in Visual Basic Express?
a) Press "delete", "home", and "shift" on the keyboard with the program. // Still need to figure out how to do this.
b) Detect when "z" and "x" are pressed. // I'm using buttons instead of this part now.
Thanks so much! :)
Windows Form Application
Here is "ONE" way.. it detects the Enter press in .NET Win Forms. The 13 represents "Enter".
Public Function KeyAscii(ByVal UserKeyArgument As KeyPressEventArgs) As Short
KeyAscii = Asc(UserKeyArgument.KeyChar)
End Function
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If KeyAscii(e) = 13 Then
MsgBox("you press ENTER key")
End If
End Sub
More key types can be found by using something like this to detect your key presses.
Private Sub Form_KeyPress(KeyAscii As Integer)
Debug.Print "KeyAscii: " & KeyAscii
End Sub
Private Sub Form_Load()
Form1.KeyPreview = True
End Sub
I think the SendKey function would meet your needs.
a) To send keyboard commands, you can use this SendKeys method.
b) To capture keystrokes check out this support article.