Most VBA applications are designed to work within Excel and other Microsoft Office programs, like Powerpoint and Excel. VBA offers a way to interact with web requests and deal with HTTP responses (however clumsy it may be) through APIs and web scraping, too.

But sometimes you want to interact with non-MS Office programs that are not web content. In that case, you can use SendKeys. Admittedly, SendKeys is also somewhat clumsy and it’s not the most reliable, but it can get the job done in a pinch. VBA is really designed and optimized for MS Office applications, hence Visual Basic for (Microsoft) Applications, but SendKeys is useful when you want to deal with other programs.


SendKeys and The Active Window

Many tutorials start off with a warning on using SendKeys, and they have a good reason. SendKeys literally sends the indicated keystrokes to whatever element is active. Ideally this is the place you want the keystrokes to impact, such as a cell in a worksheet, an open notepad, or a browser URL bar.

However, this can cause some problems. If the wrong window is active, you’ll be sending keystrokes to the wrong window. Moreover, the active element at exactly the time SendKeys executes receives the keystrokes. Thus, you cannot step through your code to verify its correctness. In fact, you can’t even run some bits of code from the VBA Editor, as the VBE will still be active!

To illustrate: open the VBE, input this code, and run the macro with F5. What happened?

Sub sendKeysTest()

Cells(1, 1).Select

SendKeys "Test value"

End Sub

You’ll end up with something like this, which probably is not what you intended:

Incorrect result
Sent keys to the wrong place!

Despite you trying to activate Cell A1, the VBE was still active at the time of running, so SendKeys placed the keystrokes at the cursor in the VBE instead of in your desired Cell.

It’s imperative to first activate whatever element you want SendKeys to impact. If the workbook is your target, run your code from the Macros selection box in the GUI. This will ensure the workbook is active. If you want to send keystrokes to another program, you’ll need to activate it. We’ll talk more about how to do that in a bit.


Sending Keyboard Shortcuts

Technically, you can use SendKeys to send keyboard shortcuts to MS Office programs. If you want to save a workbook after making modifications via some subroutine, it’s theoretically possible to send the Ctrl+s keyboard shortcut to save.

I’d strongly recommend against using SendKeys to do this, though. It’s far more robust to use “pure VBA” to save the workbook with a Workbook.Save. This method permits precise naming of a specific workbook, thereby ensuring it’s exactly the workbook you want to save. Moreover, .Save executes as “pure VBA”, without the awkward injection of an I/O device (keystrokes) designed for us humans.

Nonetheless, if you’d like to send keyboard shortcuts, it’s possible to do so with SendKeys. You just need to take care that the workbook is the active window.


Special Characters

Pressing Ctrl+S to save a file uses the control key, which is part of the special character set for SendKeys. You can send any key you want, but if it’s a non-alphanumeric character, you’ll need to reference it in a special way.

The three most common special characters you’ll use, especially for shortcuts, will be control, alt, and shift. To send these as compound keystrokes (i.e., keystrokes sent concurrently), use the following substitutions:

  • SHIFT = +
  • CTRL = ^
  • ALT = %

So, to send the keyboard shortcut for save, we’d use SendKeys "^s".

Now, sometimes you might actually want to display a plus-sign or a percent-sign. To do so, you’d need to place it in curly braces, { }, so VBA knows you want that character, not its special double-role as a compound key combination.

So, to send 10% to a cell, we’d use SendKeys "10{%}". The % is “escaped” by the curly braces, and VBA knows you want the actual symbol instead of the ALT key.

Finally, there are several keys that have other functions (like the function keys F1-F16), tab, arrows, and so forth. These should be placed inside the curly braces, and they take the values below:

Special Character Table
SendKeys Special Character Table


Make powerful macros with our free VBA Developer Kit

This is actually pretty neat. If you have trouble understanding or remembering it, our free VBA Developer Kit can help. It’s loaded with VBA shortcuts to help you make your own macros like this one - we’ll send a copy to your email address below.

Sure, I'll take a free VBA Developer Kit

If you’d rather be able to copy and paste the correct VBA SendKeys special character codes, here’s a plain text version of the list:

BACKSPACE 	  	=  	{BACKSPACE}, {BS}, or {BKSP}
BREAK	  		=  	{BREAK}
CAPS LOCK	  	=  	{CAPSLOCK}
DEL or DELETE		=  	{DELETE} or {DEL}
DOWN ARROW	  	=  	{DOWN}
END	  		=  	{END}
ENTER	  		=  	{ENTER} or ~
ESC	  		=  	{ESC}
HELP	  		=  	{HELP}
HOME	  		=  	{HOME}
INS or INSERT		=  	{INSERT} or {INS}
LEFT ARROW	  	=  	{LEFT}
NUM LOCK	  	=  	{NUMLOCK}
PAGE DOWN	  	=  	{PGDN}
PAGE UP	  		=  	{PGUP}
PRINT SCREEN		=  	{PRTSC}
RIGHT ARROW		=  	{RIGHT}
SCROLL LOCK		=  	{SCROLLLOCK}
TAB	  		=  	{TAB}
UP ARROW	  	=  	{UP}
F1	  		=  	{F1}
F2	  		=  	{F2}
F3	  		=  	{F3}
F4	  		=  	{F4}
F5	  		=  	{F5}
F6	  		=  	{F6}
F7	  		=  	{F7}
F8	  		=  	{F8}
F9	  		=  	{F9}
F10	  		=  	{F10}
F11	  		=  	{F11}
F12	  		=  	{F12}
F13	  		=  	{F13}
F14	  		=  	{F14}
F15	  		=  	{F15}
F16	  		=  	{F16}

Opening and Activating Other Programs

Sending keystrokes inside Excel to Excel is not all that useful, especially when more robust methods exist. Including SendKeys in your macro is more useful when you want to interact with other applications.

First, you need another program open. We’ve written several tutorials explaining how to open and activate external programs with VBA using different methods, including VBA Shell and AppActivate.

We’re going to spend a few minutes refreshing your memory on these topics.

Opening other applications with Shell

You can use Shell to open other applications. It only takes two arguments, the filepath for the app and an attribute for the opened window. For our purposes, let’s open Notepad, a favorite app of mine for storing a few quick notes:

Shell "notepad.exe", vbNormalFocus

Notepad will open a new, normal-sized instance with focus already on it. You may need the full filepath for non-standard programs. Focus is important, as this means Notepad will already be active and SendKeys can work right away.

Let’s copy and paste the range A1 to C10 from our spreadsheet to a new notepad file:

Sub copyAndPaste()

Range("A1:C10").Copy

Shell "notepad.exe", vbNormalFocus

SendKeys "^v"

End Sub

Run this macro and you’ll see a notepad window with the contents of your cell pasted inside. Is it clean? No. Is it quick and does it get the job done? Yes. You could even bring up the save prompt for your new notepad file with "^s". Granted, there are much better ways to write to a text file with VBA.

Switching to open windows with AppActivate

If you run the macro above 3 times, you’ll end up with 3 separate notepads with the same text. If you want to switch to an open application, you can use the AppActivate statement, instead.

AppActivate requires the TITLE of the application. If you have multiple programs with the same name, it will switch to the last active one.

If your program title has changed (such as after having saved the notepad), you can use the exact name to specify which window to open. For instance, I have a plaintext file name Snippets.txt, and I can single it out like this, even if 5 other notepads are open:

AppActivate "Snippets.txt - Notepad"

Note on Shell and AppActivate

Technically, Shell returns the PID (process ID) of the opened application. Unfortunately, AppActivate uses the window title, not the PID. You can look up the title of a window with its PID, but you must do so through the Windows API. That is way outside the scope of this tutorial, but I wanted readers to be aware that it is possible to cross-reference.


Automate Tasks

Why spend time learning about SendKeys? Well, to save time later, of course!

I’ve found SendKeys useful in opening multiple URLs in a browser all at once. This example combines SendKeys with Application.Wait to ensure smooth execution between keystrokes transmissions.

Sub openURLSAutomatically()

AppActivate "Mozilla Firefox"

For i = 1 To 10
    targetURL = Cells(i, 1)
    SendKeys "^t"
    Application.Wait Now + TimeValue("00:00:01")
    SendKeys targetURL & "~"
    Application.Wait Now + TimeValue("00:00:01")
Next i

End Sub

The .Wait statements ensure Firefox has time to actually open new tabs, focus on the URL box, and execute the Enter command before opening the next new tab. Application.Wait only lets you pause in 1-second increments, but you can use VBA sleep for finer control.


SendKeys sends keystrokes to the active element in the active window. It’s clumsy, unreliable and only recommended as a last resort. That said, it can be helpful in a pinch. If you must use SendKeys, I’d also recommend doing as much processing as you can before invoking the statement. Concatenate, calculate, and error correct before sending the keys to reduce the likelihood of process-related hiccups.

I hope you found this tutorial helpful. We’ve cross-linked to a number of related VBA posts throughout this article. If you like all these guides, please subscribe using the form below.