Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (5.72 MB, 490 trang )
Dim XlApp As Excel.Application
which the Automation client will understand, because it can now check the server's object library.
Note that we need to qualify the object name, since other object models have an Application
object as well.
Next, we want to start the Excel Automation server, create an Excel Application object, and get a
reference to that object. This is done in the following line:
Set XLApp = New Excel.Application
At this point, we have complete access to Excel's object model. It is important to note, however,
that the previous line starts the Excel Automation server, but does not start Excel's graphical user
interface, so Excel will be running invisibly. To make Excel visible, we just set its Visible
property to True:
XLApp.Visible = True
We can now program as though we were within the Excel VBA IDE. For instance, the following
code creates a new workbook, adds a worksheet to it, puts a value in cell A1, and then saves the
workbook:
Sub MakeWorkbook()
Dim XlApp As Excel.Application
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Set XlApp = New Excel.Application
XlApp.Visible = True
Set wb = XlApp.Workbooks.Add
Set ws = wb.Worksheets.Add
ws.Name = "Sales"
ws.Range("A1").Value = 123
wb.SaveAs "d:\temp\SalesBook"
End Sub
Note that the Excel server will not terminate by itself, even if the XLApp variable is destroyed. If
we have made Excel visible, then we can close it programmatically, as well as from the user
interface in the usual way (choosing Exit from the File menu, for instance). But if the Excel server
is invisible, it must be closed using the Quit method:
XlApp.Quit
(If we fail to terminate the Excel server, it will remain running invisibly, taking up system
resources, until the PC is restarted.)
E.2.1 An Alternative Approach
The approach described for programming Excel from within another application is the preferred
approach, since it is the most efficient. However, there is an alternative approach that you may
encounter, so let us discuss it briefly. As before, we assume that a reference has been set to the
Excel object library.
E.2.1.1 The CreateObject function
451
The CreateObject function can start an Automation server, create an object, and assign it to an
object variable. Thus, we can write:
Dim XLApp as Excel.Application
Set XLApp = CreateObject("Excel.Application")
This approach will execute more slowly than the previous approach using the New keyword, but it
is perfectly valid.
As before, we must remember to close Excel using the Quit method (or through normal means if
Excel is visible).
E.2.1.2 The GetObject function
If Excel is already running, the CreateObject function will start a second copy of the Excel
server. To use the currently running version, we can use the GetObject function to set a
reference to the Application object of a running copy of Excel. This is done as follows:
Set XLApp = GetObject(, "Excel.Application")
(The first parameter of GetObject is not used here.)
One of the problems with using GetObject is that it will produce an error if Excel is not running.
Thus, we need some code that will start Excel if it is not running or use the existing copy of Excel
if it is running.
The trick to this is to know that if GetObject fails to find a running copy of Excel, then it issues
error number 429 ("ActiveX component can't create object"). Thus, the following code does the
trick:
Dim XLApp As Excel.Application
On Error Resume Next
' Try to get reference to running Excel
Set XLApp = GetObject(, "Excel.Application")
If Err.Number = 429 Then
' If error 429, then create new object
Set XLApp = CreateObject("Excel.Application")
ElseIf Err.Number <> 0 Then
' If another type of error, report it
MsgBox "Error: " & Err.Description
Exit Sub
End If
E.2.1.3 No object library reference
We have been assuming that the client application has a reference to the server's object library.
However, it is still possible for a client application (an Automation client) to program the objects
of an Automation server (such as Excel) without such a reference. Under these circumstances, we
cannot refer to objects by name in code, since the client will not understand these names. Instead,
we must use the generic Object data type, as in the following code:
Dim XLApp As Object
Dim wb As Object
452
Set XLApp = CreateObject("Excel.Application")
XLApp.Visible = True
Set wb = XLApp.Workbooks.Add
wb.SaveAs "d:\temp\SalesBook"
This code will run even more slowly than the previous code, which, in turn, is slower than the first
version.
Thus, we have three versions of Automation:
•
•
•
Using the New keyword syntax (requires an object library reference)
Using CreateObject and specific object variable declarations (requires an object
library reference)
Using CreateObject with generic As Object declarations (does not use an object
library reference)
These versions of automation are sometimes referred to by the names very early binding, early
binding, and late binding, respectively (although you may hear these terms used somewhat
differently).
These terms refer to the time at which VBA can associate (or bind ) the object, property, and
method names in our code to the actual addresses of these items. In very early binding, all
bindings are done at compile time by VBA—that is, before the program runs. In early binding,
some of the bindings are done at compile time and others are done at run time. In late binding, all
bindings are done at run time.
The issue is now evident. The more binding that needs to be done at run time, the more slowly the
program will run. Thus, very early binding is the most efficient, followed by early binding, and
then late binding.
453
Appendix F. High-Level and Low-Level Languages
In this appendix, we'll examine the position of Visual Basic as a programming language by taking
a somewhat closer look at high-level and low-level languages, with some examples for
comparison.
A low-level language is characterized by its ability to manipulate the computer's operating system
and hardware more or less directly. For instance, a programmer who is using a low-level language
may be able to easily turn on the motor of a floppy drive, check the status bits of the printer
interface, or look at individual sectors on a disk, whereas these tasks may be difficult, if not
impossible, with a high-level language. Another benefit of low-level languages is that they tend to
perform tasks more quickly than high-level languages.
On the other hand, the power to manipulate the computer at a low level comes at a price. L owlevel languages are generally more cryptic—they tend to be farther removed from ordinary spoken
languages and are therefore harder to learn, remember, and use. High-level languages (and
application-level languages, which many people would refer to simply as high-level languages)
tend to be more user-friendly, but the price we pay for that friendliness is less control over the
computer and slower running programs.
To illustrate, consider the task of printing some text. A low-level language may only be able to
send individual characters to a printer. The process of printing with a low-level language might go
something like the following:
1.
2.
3.
4.
5.
6.
Check the status of the printer.
If the printer is free, initialize the printer.
Send a character to the printer.
Check to see if this character arrived safely.
If not, send the character again.
If so, start over with the next character.
The "lowest" level language that programmers use is called assembly language . Indeed, assembly
language has essentially complete control over the computer's hardware. To illustrate assembly
language code, the following program prints the message "Happy printing." Don't worry if these
instructions seem meaningless—you can just skim over them to get the feel. In fact, the very point
we want to make is that low-level languages are much more cryptic than high-level languages.
(Lines that begin with a semicolon are comments. We have left out error checking to save a little
space.)
; -------------------; Data for the program
; -------------------; message to print
Message
DB
'Happy printing', 0Dh, 0Ah
; length of message
Msg_Len
EQU
$-Message
; -------------------; Initialize printer 0
; -------------------mov ah,1
mov dx,0
int 17h
454
; --------------------; Printing instructions
; --------------------; get number of characters to print
mov cx,Msg_Len
; get location of message
mov bx,offset Message
; get printer number (first printer is printer 0)
mov dx,0
Print_Loop:
; send character to printer 0
mov ah,0
mov al,[bx]
int 17h
; do next character
inc bx
loop Print_Loop
For comparison, let us see how this same task would be accomplished in the BASIC programming
language:
LPRINT "Happy printing"
The difference is pretty obvious.
As we have discussed, high-level languages are usually designed for a specific purpose. Generally,
this purpose is to write software applications of a specific type. For instance, Visual C++ and
Visual Basic are used primarily to write standalone Windows applications. Indeed, Microsoft
Excel itself is written in Visual C++. As another example, FORTRAN (which is a contraction of
Formula Translation) is designed to write scientific and computational applications for various
platforms (including Windows). COBOL is used to write business-related applications (generally
for mainframe computers).
At the highest level in the programming language hierarchy, we find programs such as Excel VBA,
whose primary purpose is not to manipulate the operating system or hardware, nor to write
standalone Windows applications, but rather to manipulate a high-level software application (in
this case Microsoft Excel).
Just for fun, let us take a brief look at a handful of the more common programming languages.
F.1 BASIC
The word BASIC is an acronym for Beginners All-Purpose Symbolic Instruction Code, the key
word here being Beginners. BASIC was developed at Dartmouth College in 1963, by two
mathematicians: John Kemeny and Thomas Kurtz. The intention was to design a programming
language for liberal arts students, who made up the vast majority of the student population at
Dartmouth. The goal was to create a language that would be friendly to the user and have a fast
turn-around time so it could be used effectively for homework assignments. (In those days, a
student would submit a program to a computer operator, who would place the program in a queue,
455