Although the Excel object model and VBA code is very comprehensive in providing you with
For example, you cannot find the amount of available space on a disk device. You cannot read the keyboard directly ‚ you only can read incoming keys on a
API calls are a very advanced subject and can provide an
API (application programming interface) allows you to access the built-in programming functions from DLL and EXE files, particularly the ones that drive Windows. Other third-party applications also use DLL files for libraries of functions, and if you are lucky, you may even be supplied with documentation on how to work the functions.
API calls are normally functions that return a value of some type, although they often take some action at the same time. There are also subroutines that only take action (remember the earlier distinction between a function and a subroutine). To use them, you must first declare the function or subroutine you wish to use, and this is the hardest part. The
Declare
statement sets up the description of the function or subroutine statement within the Dynamic Link Library (DLL) file. It describes which DLL will be used, what the
Here are some examples of API calls and how to use them within your VBA code.
For this example, you are going to use an API call that gets the spare disk space from a disk device. For the record, this particular API call gets around the 2GB problem. The original Microsoft API call only read disk
First of all, you must make the declaration. You do this in the declarations section of a module. The syntax for this particular declaration is as
Private Declare Function GetDiskFreeSpaceEx Lib "kernel32" _
Alias "GetDiskFreeSpaceExA" (ByVal lpDirectoryName As _
String, lpFreeBytesAvailableToCaller As Currency, _
lpTotalNumberOfBytes As Currency, lpTotalNumberOfFreeBytes _
As Currency) As Long
This is quite a long statement, and it has to be completely accurate to work. If you have access to Visual Basic, all the API declarations are contained in a file called API32.TXT and can easily be
Basically, this statement sets up a reference to the kernel32.dll that resides in the
The
Sub Test_Api()
Dim FreeBytesAvailableToCaller As Currency, TotalNumberOfBytes As _
Currency, TotalNumberOfFreeBytes As Currency
x = GetDiskFreeSpaceEx("c:\", FreeBytesAvailableToCaller, _
TotalNumberOfBytes, TotalNumberOfFreeBytes)
MsgBox "Total Space " & Format(TotalNumberOfBytes * 10000, "#,##0")
MsgBox "Free Space " & Format(TotalNumberOfFreeBytes * 10000, "#,##0")
End Sub
This code sets up
The call is then made passing the root directory "C:\" and the variables already defined. It is then a simple case of multiplying the value by 10,000 and formatting to comma format for easy display. You can check the values by going into Windows Explorer or NT Explorer and selecting File Properties from the menu, as shown in Figure 17-1.
Figure 17-1:
Getting the total space from a disk drive
API calls can also be used for reading and writing to files. One of their useful functions is creating INI files for your program. INI files are a means of storing settings for your program, such as for control settings that you want to be sticky or details of
An example might be a text box that holds a directory pathname that is set by the user. The user might put in a different pathname, but when the program is closed, it reverts to the default on reloading. This is
The INI file holds this information locally so that it can be retrieved when the program is loaded next time. Of course, you could use a portion of the spreadsheet to store these values, but this could easily be overwritten by other data.
There are two declarations that can be used for your INI file. (There are other declarations for reading and writing to INI files, but you are going to use these in the example.)
Private Declare Function GetPrivateProfileString Lib "kernel32" Alias _
"GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal _
lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As _
String, ByVal nSize As Long, ByVal lpFileName As String) As Long
Private Declare Function WritePrivateProfileString Lib "kernel32" Alias _
"WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal _
lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As _
Long
These need to be added into the declarations section of a module. They set up references to the kernel32.dll file and describe how the parameters will be passed. You can then use code to pass the parameters and write to the file:
Sub Test_INI()
x = WritePrivateProfileString("Parameters", "Path", "C:\temp\", "myini.ini")
s$ = Space$(256)
x = GetPrivateProfileString("Parameters", "Path", "", s$, 256, "myini.ini")
MsgBox s$
MsgBox x
End Sub
The first line
The first parameter (Parameters) is the section of the INI file to write the new string. The second parameter is the key name or the entry to set; if set to Null, it will delete all keys within this section. The third parameter is the value to write for the key. This is "C:\temp\"; if set to Null, it will delete the existing string for that key. The fourth parameter is the
This now creates MYINI.INI. If you look in your Windows directory, you will see that the file has been created. If you double-click it, it will be loaded into Notepad because it is a text file, and should look like this:
[Parameters]
Path=C:\temp\
The next API call reads the path back in. However, before this can happen, you must create a variable for it to be placed in.
The
Space$
command has been used to create a string of spaces 256 long. Also, this variable must be specified as a string,
GetPrivateProfileString
works in a similar way to
WritePrivateProfileString
, but there are more parameters to pass. The first and second parameters are the same as before and give details of the section and key to be read. The third parameter has a default value to return if the entry is not found. The fourth parameter contains the variable name for the result to be passed to. The fifth parameter contains the maximum number of
The variable calling the API (
x
) will give the number of characters returned.
S$
will contain the key, terminated by a Null character. If the
Both these API calls are very
This method is often used in programs to keep track of user settings so that when the user enters the program subsequently, it is set to that user's personal settings.
Microsoft no longer uses INI files; they use keys in the Registry to record this information.
Another useful purpose of API calls is to read the keyboard and find out if a certain key has been pressed. There are events on user forms to manage keyboard events, but these only apply to a particular form or a particular control on the form that has the focus at that time.
For example, suppose you write a macro to do a
Private Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) _
As Integer
This will allow you to examine any key while the program is running. You can even differentiate between left and right SHIFT keys or CTRL keys:
Sub Test_Key()
x = 0
Do Until x = 1
If GetKeyState(&H9) < 0 Then x = 1
DoEvents
Loop
MsgBox "You pressed the TAB key"
End Sub
This program sets up a simple Do Until..Loop that keeps running until x=1. This will never happen until the GetKeyState line turns up a value for the specified key that is less than 0 ‚ that is, it has been pressed. For the purposes of the example, the TAB key is used, which has a value of 09 in hexadecimal. When the TAB key is pressed, x changes its value to 1 and exits from the loop. The message box is then displayed.
The
DoEvents
command is very important here. It literally allows the operating system to catch its
Run this code, and it goes into an infinite loop because x will never equal 1. Press any key on the keyboard and nothing happens. But press the TAB key, and the program will end with a message box. Of course, it helps if you know the values of the Virtual Key Codes if you want to use other key combinations. They are listed here:
|
Symbolic Constant Name |
Value (Hexadecimal) |
Mouse or Keyboard Equivalent |
|
VK_LBUTTON |
01 |
Left mouse button |
|
VK_RBUTTON |
02 |
Right mouse button |
|
VK_CANCEL |
03 |
CTRL-BREAK processing |
|
VK_MBUTTON |
04 |
Middle mouse button (three-button mouse) |
|
‚ |
05 ‚ 07 |
Undefined |
|
VK_BACK |
08 |
BACKSPACE |
|
VK_TAB |
09 |
TAB |
|
‚ |
0A ‚ 0B |
Undefined |
|
VK_CLEAR |
0C |
CLEAR |
|
VK_RETURN |
0D |
ENTER |
|
‚ |
0E ‚ 0F |
Undefined |
|
VK_SHIFT |
10 |
SHIFT |
|
VK_CONTROL |
11 |
CTRL |
|
VK_MENU |
12 |
ALT |
|
VK_PAUSE |
13 |
PAUSE |
|
VK_CAPITAL |
14 |
CAPS LOCK |
|
‚ |
15 ‚ 19 |
Reserved for Kanji systems |
|
‚ |
1A |
Undefined |
|
VK_ESCAPE |
1B |
ESC |
|
‚ |
1C ‚ 1F |
Reserved for Kanji systems |
|
VK_SPACE |
20 |
SPACEBAR |
|
VK_PRIOR |
21 |
PAGE UP |
|
VK_NEXT |
22 |
PAGE DOWN |
|
VK_END |
23 |
END |
|
VK_HOME |
24 |
HOME |
|
VK_LEFT |
25 |
LEFT ARROW |
|
VK_UP |
26 |
UP ARROW |
|
VK_RIGHT |
27 |
RIGHT ARROW |
|
VK_DOWN |
28 |
DOWN ARROW |
|
VK_SELECT |
29 |
SELECT |
|
‚ |
2A |
Original equipment manufacturer (OEM) specific |
|
VK_EXECUTE |
2B |
EXECUTE |
|
VK_SNAPSHOT |
2C |
PRINT SCREEN |
|
VK_INSERT |
2D |
INS |
|
VK_DELETE |
2E |
DEL |
|
VK_HELP |
2F |
HELP |
|
VK_0 |
30 |
|
|
VK_1 |
31 |
1 |
|
VK_2 |
32 |
2 |
|
VK_3 |
33 |
3 |
|
VK_4 |
34 |
4 |
|
VK_5 |
35 |
5 |
|
VK_6 |
36 |
6 |
|
VK_7 |
37 |
7 |
|
VK_8 |
38 |
8 |
|
VK_9 |
39 |
9 |
|
‚ |
3A ‚ 40 |
Undefined |
|
VK_A |
41 |
A |
|
VK_B |
42 |
B |
|
VK_C |
43 |
C |
|
VK_D |
44 |
D |
|
VK_E |
45 |
E |
|
VK_F |
46 |
F |
|
VK_G |
47 |
G |
|
VK_H |
48 |
H |
|
VK_I |
49 |
I |
|
VK_J |
4A |
J |
|
VK_K |
4B |
K |
|
VK_L |
4C |
L |
|
VK_M |
4D |
M |
|
VK_N |
4E |
N |
|
VK_O |
4F |
O |
|
VK_P |
50 |
P |
|
VK_Q |
51 |
Q |
|
VK_R |
52 |
R |
|
VK_S |
53 |
S |
|
VK_T |
54 |
T |
|
VK_U |
55 |
U |
|
VK_V |
56 |
V |
|
VK_W |
57 |
W |
|
VK_X |
58 |
X |
|
VK_Y |
59 |
Y |
|
VK_Z |
5A |
Z |
|
VK_LWIN |
5B |
LEFT WINDOWS (Microsoft Natural Keyboard) |
|
VK_RWIN |
5C |
RIGHT WINDOWS (Microsoft Natural Keyboard) |
|
VK_APPS |
5D |
APPLICATIONS (Microsoft Natural Keyboard) |
|
‚ |
5E ‚ 5F |
Undefined |
|
VK_NUMPAD0 |
60 |
Numeric keypad |
|
VK_NUMPAD1 |
61 |
Numeric keypad 1 |
|
VK_NUMPAD2 |
62 |
Numeric keypad 2 |
|
VK_NUMPAD3 |
63 |
Numeric keypad 3 |
|
VK_NUMPAD4 |
64 |
Numeric keypad 4 |
|
VK_NUMPAD5 |
65 |
Numeric keypad 5 |
|
VK_NUMPAD6 |
66 |
Numeric keypad 6 |
|
VK_NUMPAD7 |
67 |
Numeric keypad 7 |
|
VK_NUMPAD8 |
68 |
Numeric keypad 8 |
|
VK_NUMPAD9 |
69 |
Numeric keypad 9 |
|
VK_MULTIPLY |
6A |
MULTIPLY |
|
VK_ADD |
6B |
ADD |
|
VK_SEPARATOR |
6C |
SEPARATOR |
|
VK_SUBTRACT |
6D |
SUBTRACT |
|
VK_DECIMAL |
6E |
DECIMAL |
|
VK_DIVIDE |
6F |
DIVIDE |
|
VK_F1 |
70 |
F1 |
|
VK_F2 |
71 |
F2 |
|
VK_F3 |
72 |
F3 |
|
VK_F4 |
73 |
F4 |
|
VK_F5 |
74 |
F5 |
|
VK_F6 |
75 |
F6 |
|
VK_F7 |
76 |
F7 |
|
VK_F8 |
77 |
F8 |
|
VK_F9 |
78 |
F9 |
|
VK_F10 |
79 |
F10 |
|
VK_F11 |
7A |
F11 |
|
VK_F12 |
7B |
F12 |
|
VK_F13 |
7C |
F13 |
|
VK_F14 |
7D |
F14 |
|
VK_F15 |
7E |
F15 |
|
VK_F16 |
7F |
F16 |
|
VK_F17 |
80H |
F17 |
|
VK_F18 |
81H |
F18 |
|
VK_F19 |
82H |
F19 |
|
VK_F20 |
83H |
F20 |
|
VK_F21 |
84H |
F21 |
|
VK_F22 |
85H |
F22 |
|
VK_F23 |
86H |
F23 |
|
VK_F24 |
87H |
F24 |
|
‚ |
88 ‚ 8F |
Unassigned |
|
VK_NUMLOCK |
90 |
NUM LOCK |
|
VK_SCROLL |
91 |
SCROLL LOCK |
|
VK_LSHIFT |
A0 |
LEFT SHIFT |
|
VK_RSHIFT |
A1 |
RIGHT SHIFT |
|
VK_LCONTROL |
A2 |
LEFT CTRL |
|
VK_RCONTROL |
A3 |
RIGHT CTRL |
|
VK_LMENU |
A4 |
LEFT MENU |
|
VK_RMENU |
A5 |
RIGHT MENU |
|
‚ |
E7 ‚ E8 |
Unassigned |
|
‚ |
E9 ‚ F5 |
OEM specific |
|
VK_ATTN |
F6 |
ATTN |
|
VK_CRSEL |
F7 |
CRSEL |
|
VK_EXSEL |
F8 |
EXSEL |
|
VK_EREOF |
F9 |
ERASE EOF |
|
VK_PLAY |
FA |
PLAY |
|
VK_ZOOM |
FB |
ZOOM |
|
VK_NONAME |
FC |
Reserved for future use |
|
VK_PA1 |
FD |
PA1 |
|
VK_OEM_CLEAR |
FE |
CLEAR |
You can also use an API call to play a sound within your code from a WAV file. The old macro programming language had a command to do this, but it has not been included in VBA, or for that matter in Visual Basic itself, which makes it a bit
Public Declare Function PlaySound Lib "winmm.dll" Alias "PlaySoundA" _
(ByVal lpszName As String, ByVal hModule As Long, ByVal dwFlags As _
Long) As Long
You can then play the WAV files within your code:
Sub test_sound()
x = PlaySound("c:\windows\media\chord.wav", 0, 2)
x = PlaySound("c:\windows\media\ding.wav", 0, 2)
End Sub
This example plays two standard Windows sounds. If you have a microphone on your computer, you can record your own sound effects or speech onto a WAV file and play them back in this way.
These examples give some idea of the power of API calls within a program. There are many books written on this subject if you wish to examine this topic further.