Zack
asked on
Capturing keypress in Excel Worksheet with VBA
Hi - Is there a way to capture keypresses in an excel worksheet? I can't use _change. I need to capture it immediately as it would in a userform. I found a page where it can happen but I'm not sure where to put the various code. Here is the code.
Option Explicit
Declare Function SetWindowsHookEx Lib _
"user32" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, _
ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Declare Function CallNextHookEx Lib "user32" _
(ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, lParam As Any) As Long
Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long
Declare Function GetActiveWindow Lib "user32" () As Long
Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Const HC_ACTION = 0
Const WM_KEYDOWN = &H100
Const WH_KEYBOARD_LL = 13
Dim hhkLowLevelKybd As Long
Dim blnHookEnabled As Boolean
Dim enumAllowedValues As AllowedValues
Dim objTargetRange As Range
Dim objValidationRange As Range
Dim vAns As Variant
Type KBDLLHOOKSTRUCT
vkCode As Long
scanCode As Long
flags As Long
time As Long
dwExtraInfo As Long
End Type
Enum AllowedValues
alpha
numeric
End Enum
Function LowLevelKeyboardProc _
(ByVal nCode As Long, ByVal wParam As Long, lParam As KBDLLHOOKSTRUCT) As Long
'\hook keyboard only if XL is the active window
If GetActiveWindow = FindWindow("XLMAIN", Application.Caption) Then
If (nCode = HC_ACTION) Then
'\check if a key is pushed
If wParam = WM_KEYDOWN Then
'\if so, check if the active cell is within the target range
If Union(ActiveCell, objTargetRange).Address = objTargetRange.Address Then
'\if only numeric values should be allowed then
If enumAllowedValues = 1 Then
'\check if the pushed key is a numeric key or a navigation key
'\by checking the vkCode stored in the laparm parameter
If Chr(lParam.vkCode) Like "#" Or _
lParam.vkCode = 37 Or lParam.vkCode = 38 Or lParam.vkCode = 39 Or _
lParam.vkCode = 40 Or lParam.vkCode = 9 Or lParam.vkCode = 13 Then
'\if so allow the input
LowLevelKeyboardProc = 0
Else
'\else filter out this Key_Down message from message qeue
Beep
LowLevelKeyboardProc = -1
Exit Function
End If
'\if onle alpha values should be allowed then
ElseIf enumAllowedValues = 0 Then
'\check the laparam parameter
If Chr(lParam.vkCode) Like "#" Then
'\if numeric prevent the input
Beep
LowLevelKeyboardProc = -1
Exit Function
Else
'\otherwise allow the input
LowLevelKeyboardProc = 0
End If
End If
End If
End If
End If
End If
'\pass function to next hook if there is one
LowLevelKeyboardProc = CallNextHookEx(0, nCode, wParam, ByVal lParam)
End Function
Public Sub Unhook_KeyBoard()
If hhkLowLevelKybd <> 0 Then UnhookWindowsHookEx hhkLowLevelKybd
blnHookEnabled = False
Cells.Clear
End Sub
Sub ValidateRange(r As Range, ByVal v As AllowedValues)
'\store these in global variables for they will be
'\needed later in the filter function
enumAllowedValues = v
Set objTargetRange = r
'\don't hook the keyboard twice !!
If blnHookEnabled = False Then
hhkLowLevelKybd = SetWindowsHookEx _
(WH_KEYBOARD_LL, AddressOf LowLevelKeyboardProc, Application.Hinstance, 0)
blnHookEnabled = True
End If
End Sub
Sub test()
'\ignore any mishandling of the following
'\input boxes by the user
On Error Resume Next
Cells.Clear
Set objValidationRange = Application.InputBox _
("Selet one or more Cells ", "Custom Data Validation...", Type:=8)
If objValidationRange Is Nothing Then GoTo errHdlr
objValidationRange.Interior.Color = vbGreen
vAns = InputBox("To allow only alpha values in the selected range enter 1 " _
& vbCrLf & vbCrLf & "To allow only numeric values in the selected range enter 2 ")
If vAns = 1 Then
ValidateRange objValidationRange, AllowedValues.alpha
ElseIf vAns = 2 Then
ValidateRange objValidationRange, AllowedValues.numeric
Else
GoTo errHdlr
End If
objValidationRange.Cells(1).Select
Set objValidationRange = Nothing
Exit Sub
errHdlr:
MsgBox "criteria error- Try again !", vbCritical
Unhook_KeyBoard
End Sub
Better yet, can you explain briefly what you're trying to do? Just in case there's something that comes to mind as an alternative in addition to what you're trying, which I'll attempt to explain with the code you have, now.
Cheers
Dave
Cheers
Dave
What exactly are you trying to accomplish?
Are you trying to make a data validation dropdown list shrink as the user types data? Microsoft Excel MVP Debra Dalgleish shows how here:http://www.contextures.on.ca/xlDataVal10.html
Are you trying to make a data validation dropdown list shrink as the user types data? Microsoft Excel MVP Debra Dalgleish shows how here:http://www.contextures.on.ca/xlDataVal10.html
Exactly. There are also KeyDown, etc., events for controls on a userform, so not sure you need the sophistication you've posted to get what you want.
Tell us your story and we'll help.
Dave
Tell us your story and we'll help.
Dave
ASKER
I'm trying to get a _keypress type event with a worksheet. As soon as a user presses any alpha or numeric key on the worksheet it captures it and runs a procedure or possibly ignores it. I have application.onkey for function keys so I don't want it to interfere with alpha nums.
Thanks! Zack
Thanks! Zack
Is this a worksheet control in a userform, or the base Excel worksheet?
Dave
Dave
ASKER
base excel worksheet
Ok. There's an excellent primer on the code you're trying to use. Give me a few as I think I had a solution that did this, otherwise I'll build...
http://www.codeguru.com/columns/vb/article.php/c4829
Dave
http://www.codeguru.com/columns/vb/article.php/c4829
Dave
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks that works!! Keep monitoring this thread. I will open up another one for extra assistance. Thanks for your help!
Zack
Zack
ASKER
Wow excel 2003 is being a real piece of crap! Everytime I change the hook and it errors out Excel crashes arg... I guess i will have to come up with something totally different. :(
Thanks again for the help tho!
Thanks again for the help tho!
ASKER
I opened up another question - https://www.experts-exchange.com/questions/27141936/Excel-VBA-Allow-user-to-double-click-but-prevent-overwriting-cell.html
What do you mean "change the hook"? Ok. If you want to modify the code, ensure you've UNHOOKED. Unplanned crashes can result from modifying code while its trying to run it...
ASKER
oooooops. Do I feel dumb...Yep - I forgot to unhook. Sorry man. That works awesome now. I feel really dumb. :( :( :(
I'm used to changing stuff on the fly when it crashes. I forgot you said to unhook first...
Thanks again!
Zack
I'm used to changing stuff on the fly when it crashes. I forgot you said to unhook first...
Thanks again!
Zack
Hey - I've been there, too. Crashed many times on things like this, addins, timers, etc., before I thought, "whoa", let's get the cart behind the horse :)
Dave
Dave
ASKER
Hehe. Actually I do have a quick question about select cases. Is there a way to have like a to z instead of doing "a", "b", "c", etc. Thanks!
you mean a test for alpha characters?
You could use the ascii codes, or just test for the text. See code (commented is looking at it from an ascii code basis, which could be useful if you're trying to trap a function key or something):
Dave
PS - ask a related question by clicking it at the top right hand corner where you add a new post.
Sub processKeyPress(keyPressed As String)
'Select Case Asc(keyPressed)
Select Case keyPressed
'case 65 to 90, 97 to 122 'for Asc(keyPressed)
Case "a" To "z", "A" To "Z":
Application.StatusBar = "key Pressed was: " & keyPressed
'put code here if capital alpha key was pressed
Case "*":
Call Unhook_KeyBoard
Application.StatusBar = False
Case Else
'do whatever
End Select
End Sub
Dave
PS - ask a related question by clicking it at the top right hand corner where you add a new post.
Note an asterisk now unhooks. Or you could have a button to run the Unhook, etc.
Dave
Dave
ASKER
dlmille - go here so i can award you points for this additional question and respond. https://www.experts-exchange.com/index.jsp?qid=27142619
Thanks!
Zack
Thanks!
Zack
You didnt' need to do that - I meant for future follow-ups where others might help (unless its bug related)....
But, I posted this in the post you created. It will benefit the knowledgebase.
Dave
But, I posted this in the post you created. It will benefit the knowledgebase.
Dave
ASKER
That's cool it's appreciated. I know the more points you get you can get your monthly membership waived as I have had in the past, so it's all good. :)
Hi guys. Can anyone be kind enough to convert this for Win64 ? My attemps are not functional and not worth posting!
Dave