2

I am using Excel VBA to copy text selection from an Access file (I'd prefer not to get into details as to why). I have it in a Do While loop that SHOULD press the tab key (works), then copies the data (fails), puts it into the clipboard (works), and sets the clipboard information to a variable (works), which then, for debugging purposes, does a debug.print of the variable (works). This is to cycle through a form to get to a "base point" where I can 100% use tabs and such to navigate to other parts of the form. See code please:

AppActivate ("Microsoft Access - Filename that is constant")

X = 0
Do While X < 14
Application.SendKeys "{TAB}", True
Application.SendKeys "^C", True

Sleep (500)

mydata.GetFromClipboard
cb = mydata.GetText

Debug.Print (cb)
If Len(cb) = 5 Then
X = 14
End If
X = X + 1
Loop
Set mydata = Nothing

I've tried getting this to work, but to no avail. What am I doing wrong or perhaps what would be a better solution?

Community
  • 1
  • 1
icebird76
  • 742
  • 3
  • 14
  • 36

2 Answers2

0

Though I hate Sendkeys and was wondering whether I should ask you about it but since you said not to ask why, I will keep my trap shut. :P

Try this small fix... If this works then that means, you need to give it some time before issuing the next sendkeys command.

Sub Sample()
    '
    '~~> Rest of your code
    '

    Application.SendKeys "{TAB}", True

    Wait 2

    Application.SendKeys "^{C}", True

    '
    '~~> Rest of your code
    '
End Sub

Private Sub Wait(ByVal nSec As Long)
    nSec = nSec + Timer
    While nSec > Timer
        DoEvents
    Wend
End Sub

what would be a better solution?

Use APIs as shown Here. This doesn't directly answer your question but it explains how the concept works.

So applying that would be something like this

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _
(ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Dim Ret As Long

Sub Sample()
    Ret = FindWindow(vbNullString, "Microsoft Access - Filename that is constant")

    If Ret <> 0 Then
        MsgBox "Window Found"
    Else
        MsgBox "Window Not Found"
    End If
End Sub

If you wish to become good at API’s like FindWindow, FindWindowEx and SendMessage then get a tool that gives you a graphical view of the system’s processes, threads, windows, and window messages. For Ex: uuSpy or Spy++. Another example which demonstrates how this API is used.

Community
  • 1
  • 1
Siddharth Rout
  • 147,039
  • 17
  • 206
  • 250
  • 1. Did not work. I tried it with sleep(milliseconds) and it doesn't work. Doing CTRL+C manually works. – icebird76 May 12 '15 at 21:56
  • 2. I mean "don't ask" with the copy/pasting Access form data. If you have a better solution to SendKeys, I'd like to hear it! – icebird76 May 12 '15 at 21:57
  • BTW did you try `SendKeys "^{C}"` instead of `.SendKeys "^C"` – Siddharth Rout May 12 '15 at 21:58
  • Already posted it :) You may have to refresh the page to see it :) – Siddharth Rout May 12 '15 at 21:59
  • Using API's is a more complex but reliable thing unlike `Sendkeys`. I would recommend reading about it :) – Siddharth Rout May 12 '15 at 22:01
  • APIs get long and confusing. Do you have an example for copy and pasting without me searching for a solution taking as long as I have searched for this SendKeys solution? – icebird76 May 12 '15 at 22:02
  • Once you have the `Hwnd`, using the code that I gave, you will have to then use `FindWindowEx` API to find the `Hwnd` of the control from where you want to copy and then use [This](http://www.devx.com/vb2themax/Tip/18632). I am afraid, I don't have a ready code for you – Siddharth Rout May 12 '15 at 22:05
  • @icebird76 really, spend some more time and use the API. What you ask is possible by API. Sure the SendKeys is quicker, but there are plenty of reasons why your send keys is dangerous. I highly suggest you to follow Siddarth's suggestion, longer but once for life. – Matteo NNZ May 12 '15 at 22:24
  • P.s. What is "mydata"? Are you sure the failure is on the SendKeys and not rather on where you try to get the clipboard content from? – Matteo NNZ May 12 '15 at 22:27
  • @Matteo NNZ I use a Dim mydata As New msForms.DataObject – icebird76 May 12 '15 at 22:38
0

I figured it out. I copied the code from here: http://www.vbaexpress.com/forum/showthread.php?38826-SendInput()-in-Excel-64Bit I changed VkkeyMenu to VbKeyControl and the "f" key to "C". I know it could be simplified to take up less lines, but I'd rather not mess with it if it works like the saying "If it ain't broke, don't fix it." Code:

Private Declare PtrSafe Function SendInput Lib "user32" (ByVal nInputs As LongPtr, pInputs As Any, ByVal cbSize As LongPtr) As LongPtr
Private Declare PtrSafe Function VkKeyScan Lib "user32" Alias "VkKeyScanA" (ByVal cChar As Byte) As Integer
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Private Type KeyboardInput '   creating variable type
dwType As Long '   input type (keyboard or mouse)
wVk As Integer '   the key to press/release as ASCSI scan code
wScan As Integer '   not required
dwFlags As Long '   specify if key is pressed or released
dwTime As Long '   not required
dwExtraInfo As Long '   not required
dwPadding As Currency '   only required for mouse inputs
End Type



' SendInput constants
Private Const INPUT_KEYBOARD As Long = 1


Private Const KEYEVENTF_EXTENDEDKEY As Long = 1
Private Const KEYEVENTF_KEYUP As Long = 2


' Member variables


Private TheKeys() As KeyboardInput
Private NEvents As Long




Sub testage()


ReDim TheKeys(0 To 3)


With TheKeys(0)

    .dwType = INPUT_KEYBOARD 'operation type
    .wVk = vbKeyControl 'press CTRL key

End With


With TheKeys(1)


    .dwType = INPUT_KEYBOARD ' operation
    .wVk = VkKeyScan(Asc("C")) 'press chr key

End With


With TheKeys(2)

    .dwType = INPUT_KEYBOARD 'operation type
    .wVk = VkKeyScan(Asc("C"))
    .dwFlags = KEYEVENTF_KEYUP 'release chr key

End With


With TheKeys(3)


    .dwType = INPUT_KEYBOARD ' operation type
    .wVk = vbKeyControl
    .dwFlags = KEYEVENTF_KEYUP 'release CTRL Key


End With
Call SendInput(4, TheKeys(0), Len(TheKeys(0)))


Erase TheKeys


End Sub
icebird76
  • 742
  • 3
  • 14
  • 36