How To Port WordBasic Macros To VBA

Applications:Programming
How To Port WordBasic
Macros To VBA
WordBasic, the macro language found in previous versions of Microsoft Word for Windows,
is no more. It has been replaced in Word 97 with Visual Basic for Applications, or VBA.
While VBA is very similar to WordBasic, it is sufficiently different that almost all non-trivial
macros will need some slight conversion work. Thankfully, this is not as difficult
as many users and support staff have feared.
By Tim Nott
W
ith the release of Office 97,
Microsoft finally completed
the implementation of Visual Basic for Applications (VBA) as a
suite-wide programming language.
Whereas this is undoubtedly a great
step forward, it can come as something
of a shock for those who have been
happily automating away in WordBasic since version 1 of Word for Windows.
This article has three parts. First, we
look at the short-term problems of upgrading WordBasic macros to work in
Word 97. Next comes an overview of
VBA, highlighting the conceptual and
practical differences, and finally a
hands-on session illustrating some of
the features and commands.
For the sake of clarity, note that Microsoft’s idiosyncratic version numbering for Word for Windows runs 1,
2, 6, 7, 97.
want to save the changes to the template. If you answer No then next time
you open this document - or any other
based on the same template - the process will be repeated.
If you answer yes, then you have the
choice of overwriting the existing template or creating a new file. As we shall
see, there are several compelling reasons why you might not want to overwrite the existing template. If you save
the template under a different filename, then you will still get the conversion process on opening the document
and the “Save changes to template”
prompt. The same happens if you save
the same filename to a different folder.
The only way to get rid of this infuriating behaviour is to go to the Tools/Options/File Locations dialog and
specify a different folder for Word 97
templates.
Saving the converted templates,
with their original filenames, to this
new location will cure the problem.
The second bit of bad news is that
Word doesn’t convert the macros to
native Visual Basic code. If you load a
converted macro into the Visual Basic
Editor you’ll see a number of changes
- any previously undeclared variables
will be declared and some variable
Existing Macros
The good news, at least in the short
term, is that Word 97 will convert the
macros in your existing Word 7 or
Word 6 templates. This happens
whenever you open a template, start a
new document based on a template, or
open an existing document based on
one. Helpful though this may be, it
does conceal a great deal of bad news.
Firstly, the conversion happens
automatically. If, in Word 97, you open
a document based on a Word 6 or 7
template there will be a delay while the
macros are converted. When you exit
the document, you’ll be asked if you
Update 105 (July 1997) Page 15
Figure 1 - Try to open an encrypted macro and you’ll be told
that it can’t be done.
PC Support Advisor
File: A0523.1
Applications:Programming
Sub MAIN
tempname$ = LCase$(GetDocumentProperty$(“Template”))
If tempname$ = “normal.dot” Then
nummacros = CountMacros(0, 0, 0)
/
isnotnormal = 0
Else
nummacros = CountMacros(1, 0, 0)
isnotnormal = 1
End If
EditSelectAll
EditClear
For n = 1 To nummacros
mname$ = MacroName$(n, isnotnormal)
If IsExecuteOnly(tempname$ + “:” + mname$) Then
Bold 1
Insert tempname$ + “:” + mname$ + “ is
execute-only”
Bold 0
InsertPara
Else
Insert tempname$ + “:” + mname$ + “ is
editable”
InsertPara
End If
Next n
End Sub
Figure 2 - Testing for the presence of execute-only macros in
Word 7 templates.
WordBasic
Visual Basic
FileNew .Template =
\“BIZFAX.DOT”,
\NewTemplate = 0
Documents.Add Template:=_
“FAX.DOT”, NewTemplate:= False
WordRight 2, 1
Selection.MoveRight Unit:=wd_
Word, Count:=2,Extend:=wdExtend
StartOfDocument
Selection.HomeKey Unit:=wdStory
RightPara
Selection.ParagraphFormat._
Alignment = wdAlignParagraph_
Right
Figure 3 - WordBasic and VBA equivalents.
File: A0523.2
PC Support Advisor
names may be changed. The bulk of the
existing WordBasic commands and
functions, however, won’t be replaced
by their VBA equivalents but are
treated as WordBasic “objects”. For example, the VBA equivalent of the
WordBasic command “Insert string” is
“Selection.TypeText
Text:=string”.
But the command is converted to
“WordBasic.Insert string”.
Similarly, WordBasic functions will
be enclosed in square brackets.
Despite this “pidgin VBA” approach, converted macros in general
work well enough, though there can
sometimes be unexpected behaviour.
In particular, WordBasic macros may
contain syntax errors that are never
spotted because the code is never executed - it may, for example, form part
of an error-testing routine where the
error has never arisen.
Visual Basic, on the other hand, first
compiles the entire code into compressed statements that are in turn executed by the interpreter, so any such
skeletons in the cupboard will be exposed immediately when the macro is
run.
The third episode of the bad-news
saga is that there is a rather nasty bug
with execute-only (also known as encrypted) macros. An execute-only
macro is one that can’t be edited by the
user - the idea being that end-users
can’t meddle with the source code. To
make a macro execute-only, you have
to create another macro to copy it to
another template with the “ExecuteOnly” switch. Typically, the
WordBasic code would run:
CopyMacro ”source:macro1",
”user:macro1", ExecuteOnly
which copies the existing macro1 from
SOURCE.DOT to USER.DOT and encrypts it. If the user then selects the
macro from the list, they won’t get an
Edit button. Note that the process is not
reversible - you can’t unencrypt an
execute-only macro.
When Word 97 converts earlier
macros it preserves the encryption - try
to open one in the Visual Basic editor
and you’ll get a message box saying the
project is locked and unviewable - see
Figure 1.
The bug is that if you convert a tem-
Update 105 (July 1997) Page 16
Applications:Programming
WordBasic Macros
plate containing any encrypted macros, all macros in that template will be
encrypted. VBA code can only be protected at project level - ie, a document
or template; individual macros can’t be
encrypted. Note also this doesn’t apply
to NORMAL.DOT - this is backed up
to NORMAL.WBK the first time you
run Word 97, and any execute-only
macros are not converted.
It would be difficult to accidentally
encrypt a macro, but many Microsoft
or third-party add-on macros come in
encrypted form. Although you can
check for execute-only macros by
scrolling through the list of macros and
“Although both VBA and Wordbasic are
dialects of Basic, there are considerable
differences, both in concepts and in practice.”
seeing which are editable, this is a tedious and error-prone business. Fortunately, WordBasic provides the
“IsExecuteOnly()” function to test for
these. If you create a Global macro (ie,
WordBasic
Visual Basic
MsgBox “Hello” +
\Chr$(9) + “World”
MsgBox “Hello” & vbTab &_
“World”
Insert “Name: ” +
\Chr(13) + Chr$(10)
\+ “Address: ”
Selection.InsertAfter_
Text:="Name: “ & vbCrLf &_
”Address: “
Figure 4 - Strings and constants.
stored in NORMAL.DOT) with the
code in Figure 2, this provides a way of
checking.
Create a new document based on
the template you wish to examine and
run the macro: it will clear the contents
of the new document, if any, and create
a list of all macros noting whether they
are editable or not. Apart from the
highlighting of execute-only ones in
bold, all bells, whistles and batch processing has been left as an exercise for
the reader.
Preparation
All of this makes upgrading a potentially hazardous business, especially so if you are servicing a mixed
environment of Word 97 and previous
versions. It is essential, therefore, to
take preventative measures before upgrading or running both versions side
by side.
The first essential is to back up existing templates. The second is to ensure that templates for Word 97 are
stored in a different folder to those for
6 or 7. The third is to weed out all
execute-only macros before doing any
conversion.
Objects, Properties, Methods
Figure 5 - Word 97’s new VBA macro editor in action.
Update 105 (July 1997) Page 17
PC Support Advisor
Although both VBA and Wordbasic
are dialects of Basic, there are considerable differences, both in concepts
and in practice. Whereas WordBasic
consists of a flat set of commands, VBA
is structured as a hierarchy of objects.
Objects can exist on their own, or in
collections. For instance “Selection” is
a unique object and “Documents(”Myletter.doc”)” a member of
the collection of open document objects.
Objects have properties - a document has a title and an author, a selec-
File: A0523.3
Applications:Programming
tion has a font style and size. A property of an object can return another
object, which itself has properties that
return objects. A full-stop is used to
drill down through objects. For instance, “Selection.Font.Bold” returns
the bold property of the font object,
which is in turn a property of the selection object.
In WordBasic, statements and functions are used to perform related tasks.
For example, the statement “Bold 1”
turns bold formatting on, whereas the
function ”Bold()” returns the state of
boldness. In VBA, read/write properties can be read or set via the same
object hierarchy. There is no need for a
separate function and statement: “Selection.Font.Bold = True” turns on
bold formatting, whilst “boldstate =
Selection.Font.Bold” returns the state.
Objects aren’t just confined to documents and their parts. For example, the
Office Assistant is an object that has
properties
including
animation,
sounds and visibility. Options is another object that has properties such as
AutoWordSelection and BackgroundSave that correspond to the choices in
Word’s Tools/Options menu. You’ll
“Whereas WordBasic consists of a flat
set of commands, VBA is structured as a
hierarchy of objects. Objects can exist on
their own, or in collections.”
find a map of the complete Word object
hierarchy in the MS Word Visual Basic
Help file (VBAWRD8.HLP).
Manipulation
As well as having properties that
can be changed, objects can be manipulated using methods. The TypeText
method, for instance, is equivalent to
the WordBasic “Insert” command but
the syntax is very different. The latter
is free-ranging - “Insert “Hello
world”” - does just that, at the current
insertion point in the document.
In VBA we need to specify an object
(the target for the action) and a method
(the action itself) together with any ar-
guments. So the above example becomes “Selection.TypeText Text:=
“Hello world””. Note that to assign a
property to an object you use an equals
sign, but to pass an argument to a
method you use a space between the
method and the argument name, and
a colon followed by an equals sign between the argument name and its
value.
Commas separate additional arguments. Figure 3 shows some WordBasic statements alongside their VBA
equivalents. Note that the underscore
character replaces the backslash when
breaking an instruction over more than
one line.
The Word Visual Basic Help file
contains a complete list of WordBasic
to VBA equivalents, which you will
find in the “Converting from WordBasic...” subsection of the “Getting
started...” chapter. Beware, though, as
some commands are more equal than
others. Consider the following WordBasic one-liner:
ChDir “C:\myfiles\letters\bank”
I have a variant of this in an
Autonew macro for every template,
pointing to the appropriate folder. It
helps ensure documents get saved to
the correct folder, and saves the
trouble of clicking up and down the
tree in the File/Save dialog. The list of
equivalents shows the command unchanged, but it doesn’t work - you
need to use:
ChangeFileOpenDirectory
“C:\myfiles\letters\bank”
Figure 6 - The form for our simple billing system example.
File: A0523.4
PC Support Advisor
It’s immediately apparent that VBA
code is considerably more verbose
than WordBasic. Fortunately, there are
Update 105 (July 1997) Page 18
Applications:Programming
WordBasic Macros
a number of labour-saving devices at
our disposal. One such is the
With...End With block. This lets you
specify an object, then carry out a series
of commands without having to reidentify the object each time. For example, to change multiple font options in
WordBasic you might use:
FormatFont .Font = “Courier
New”, .Bold = 1, .Points = 12
In VBA, this becomes three statements, each assigning a different property to the Font object:
Selection.Font.Name = “CourierNew”
Selection.Font.Bold = True
Selection.Font.Size = 12
Using the With...End With statement eliminates the repetition.
With Selection.Font
.Name = “Courier New”
.Bold = True
.Size = 12
End With
Another time-saving control is the
For Each...Next loop, which repeats a
set of statements for each element in a
collection or array. Unlike a standard
For...Next loop, you don’t need to
specify the number of iterations. You
can also exit the loop, say from an If
statement, with Exit For.
Variables And Constants
Whereas WordBasic has just two
types of variables (or arrays), string
and numeric, Visual Basic has 10, ranging from Boolean (2 bytes) through
high-precision currency (8 bytes), and
date. The latter ranges from 1 January
100 to 31 December 9999, so shouldn’t
cause any millennium worries for the
next 8000 years or so.
The 32,000-character limit on string
variables is expanded to around two
billion characters. You don’t have to
specify a data type when declaring a
variable - VBA will default to the Variant type, which encompasses string,
numeric and date forms. Nor do you
have to end a string variable with a
dollar sign. VBA also makes substan-
Update 105 (July 1997) Page 19
tial use of constants in a variety of
ways. One example is in building
strings - although you can still use the
Chr$() function to insert tabs and carriage returns, VBA provides the constants vbTab and vbCrLf to do this.
Figure 4 shows some examples note that the ampersand replaces the
plus sign for concatenating strings.
Another use of constants is in returning or setting properties of an object instead of using a numeric value.
For example, the property of a toolbar
button being visually “pushed in” is
returned by:
CommandBars(“MyToolbar”).
Controls(n).State% 0
This evaluates to 0 for up, -1 for
down. Though more longwinded it
makes code much easier to understand
if you use the constants msoButtonUp
and msoButtonDown instead.
Practicalities
You can still record and play back
macros in the time-honoured way.
This is often a useful way to generate
code - especially when you are not sure
of the commands - that can be refined
by later editing. The in-place WordBasic editor is a thing of the past, however, as is the concept of macro code as
one, continuous piece of text.
You launch the Visual Basic editor
from Word’s Tools/Macro menu.
Though there’s a far more crowded
environment than the WordBasic
equivalent, it isn’t as daunting as it
looks. By default, there are two small
panes on the left of the screen, with the
remainder available for editing code
and objects - see Figure 5.
The Project Explorer shows a project for each open Word document (or
Excel worksheet or PowerPoint presentation), any templates on which
open documents are based, plus the
normal template. Each project can contain a variety of objects, grouped into
folders. Of these, the Microsoft Word
Objects folder contains the ThisDocument object. This can store code for the
document that responds to events,
such as opening or closing. The References folder, unsurprisingly, shows
the references to other projects - for
example, a document’s template.
For now, the folders that concern us
are Modules and Forms. Each module
Private Sub UserForm_Initialize()
With Billform.txtClient
.AddItem “Smith and Jones”
.AddItem “Barnard’s Bank”
.AddItem “Robinson Assurance”
.ListIndex = 0
End With
End Sub
Figure 7 - Adding some events to the sample billing system.
Private Sub amtHours_Exit(ByVal Cancel As MS_
Forms.ReturnBoolean)
If Not IsNumeric(amtHours.Value) Then
MsgBox “Please enter a number for the hours”
Cancel = True
End If
End Sub
Figure 8 - Add some idiot-proofing.
PC Support Advisor
File: A0523.5
Applications:Programming
can contain one or more subroutines or
functions, known as procedures. Each
form corresponds to a custom dialog
box. Note that, unlike WordBasic,
documents as well as templates can
contain macros.
Some, but not all, objects have properties, which are shown in the Properties Window. Select ThisDocument
and you’ll see a list of properties corresponding to the option settings of the
document (eg, whether spelling errors
are underlined) and its current state
(eg, whether it has been saved since the
last editing action).
To create a new procedure, go to the
Project Explorer, right-click anywhere
in the project, and select Insert - you’ll
get the choice of Module, Class Module
or User Form. To edit an existing module or form, right-click on it, then
choose View Code.
Boxing Clever
The separate WordBasic visual dialog editor, with its clumsy paste-tocode approach, is another thing of the
past. Instead, custom dialog boxes,
known as User Forms, are stored as
Public
Public
Public
Public
Public
Public
Public
independent objects in the Forms
folder for the project, and you can create and test dialogs independently of
procedures that call them.
Designing a dialog involves switching between the Object Window,
where you create and edit controls
visually, the Properties Window,
where you set properties for the controls, and the Code Window, where
you write code that defines how the
box and its controls respond to events.
Try this. Create a new form, add a
text label and a button with the appropriate tools from the palette. Click anywhere on the form, but outside the two
controls you have added, then scroll
through the list in the Properties Window - you’ll see a complete list of all
the properties pertaining to the form
itself.
Find Caption and replace the default value of UserForm1 with some
other text - you’ll see the title bar of the
form change as you type. Select the text
label, and you’ll find the contents of the
Properties Window changes. Note that
with the label or the button you can
change the caption either from the
Properties Window or by typing di-
forgetit As Boolean
clientname As String
jobdescript As String
hoursbilled As Variant
hourlyrate As Variant
billtotal As Variant
Sub autobill()
Figure 9 - Creating a module.
Private Sub btnCreate_Click()
forgetit = False
clientname = txtClient.Text
jobdescript = txtJob.Text
hoursbilled = amtHours.Value
hourlyrate = amtRate.Value
billtotal = amtTotal.Value
Unload Me
End Sub
Figure 10 - The Click procedure for the btnCreate button.
File: A0523.6
PC Support Advisor
rectly into the control. With the button
selected, change the value of the Top
property to 80 and the Height to 20. It
should then be roughly two-thirds of
the way down the box.
Next, get the box to respond to an
event. Double-click on the button, or
click on the View Code button at the
top of the Project Explorer, and the
Code Window will appear, with an
empty procedure for the default action
- Click - already in place. At the top of
the Code Window are two drop-down
lists, one for the controls, and the other
for the events applicable for each. In
the first make sure CommandButton1
is selected. From the second list select
MouseMove. A new, empty subroutine will be created - add a second line
so it reads:
Private Sub CommandButton1_MouseMove...
CommandButton1.Top = 200 CommandButton1.Top
End Sub
If you’ve renamed, rather than recaptioned, the control then substitute
accordingly. You are now ready to test
the dialog - switch back to object view,
and hit the Run button on the toolbar.
Word will grab back the focus and the
dialog box will appear. All it does at
this stage is frustrate the user - the
button responds to the event of the
mouse moving over it by dodging out
of the way. If you click the Close button
on the title bar, the box will disappear
and you’ll return to the VBA editor. It’s
a fairly pointless example in itself, but
it does show how a dialog can respond
to events and alter itself dynamically at
run time. A more useful example
might be an Advanced... button that
expands the box to reveal further controls.
It is way beyond the scope of this
article to consider all the properties,
controls and events of custom dialogs.
The best way to get familiar with these
is to experiment with the controls and
the Properties Window. Note that you
can create multi-paged dialogs, you
can group controls in a frame grouped option buttons, for instance,
will be mutually exclusive - and generally emulate the look and feel of the
built-in Office dialog boxes.
Update 105 (July 1997) Page 20
Applications:Programming
WordBasic Macros
Experimenting with properties reveals ways of customising the look and
font of controls, the behaviour of the
Enter and Tab keys in text boxes, the
order in which the Tab key steps
through controls, whether controls are
initially hidden and so on. For the rest
of this article, we’ll concentrate on cre-
Public forgetit As Boolean
Public clientname As String
Public jobdescript As String
Public hoursbilled As Variant
Public hourlyrate As Variant
Public billtotal As Variant
Private Found As Boolean
Private Typeitin As String
Public Sub autobill()
Billform.Show
If forgetit = True Then
MsgBox “Operation cancelled”, vbExclamation
Else
Documents.Add Template:="billtemplate"
ActiveDocument.Bookmarks(“ad dress”).Select
Found = False
For Each i In ActiveDocument.AttachedTemplate._
AutoTextEntries
If i.Name = clientname Then
Found = True
ActiveDocument.AttachedTemplate.AutoTextEntries _
(clientname).Insert Where:=Selection.Range
End If
Next i
If Found = False Then
MsgBox (“No autotext entry, please add address_
manually”)
Selection.InsertAfter (clientname)
End If
ActiveDocument.Bookmarks(“details”).Select
With Selection
.InsertAfter Text:=jobdescript & “ - ” &_
hoursbilled & “hours at $” & hourlyrate & “_
per hour.”
.InsertParagraphAfter
.InsertAfter Text:="Total: $" & billtotal
.Collapse (wdCollapseEnd)
End With
End If
End Sub
Figure 11 - Complete code for the Autobill module.
Update 105 (July 1997) Page 21
PC Support Advisor
ating a custom solution that uses just a
few of the features.
Our Billing System
Let us suppose that you want to
automate a simple consultancy billing
system. You want a macro to prompt
for a client name, hours chargeable,
hourly rate and description of service,
then automatically create an invoice.
You have a few regular clients, so you
want their names to appear in a drop
down list. In Figure 6 we’ve created a
simple dialog and named its parts by
selecting each one then changing the
name field in the properties window.
The dialog itself is named Billform,
then the first control is a combo box
named txtClient. Below that is a text
box named txtJob, then three more text
boxes - amtHours, amtRate, amtTotal.
Below these come two buttons btnCreate and btnCancel. The captions
were typed in-place on the buttons,
and the text labels added above each
control. Since the labels take no active
part in the proceedings, they retain
their default names.
The next step is to set the tab order,
which reveals a rather nifty feature of
the VBA editor. Select the txtClient
combo box then scroll through the
properties to TabIndex. This should be
zero - ie, this is the control that will
have the focus when the dialog starts.
Check that the TabStop property is set
to True.
Click on the txtJob text box, and
you’ll find that the property window
has kept your place at TabStop. Make
sure again that this is True - ie, the
focus stops here rather than bypassing
- and set TabIndex to 1, creating the
next stop on the journey. Check that
TabKeyBehaviour is False - so pressing
the tab key will move on from the box
rather than inserting a literal tab character.
Repeat for the amtHours and
amtRate boxes with TabIndex values
of 2 and 3. The amtTotal box won’t
normally be filled in by the user, so set
TabStop to False. Set the two buttons’
Tabstop values to 4 and 5. All the labels
will default to false TabStops, so they
need not concern us further.
Test the dialog with the Run button
- you should find tabbing and entering
File: A0523.7
Applications:Programming
values works from left to right, top to
bottom, skipping the Total box.
Now it’s time to add some events to
the box. First, let’s give it some initial
values. Double-click on a blank part of
the form (or use the button on the Project Explorer) to open the code window
for the form. Select UserForm from the
object list on the left, and Initialize
from the procedure list. Complete the
procedure by entering the code in Figure 7.
You’ll find that when you test the
dialog, the names appear in a list when
the button in the combo box is clicked.
The default name will correspond to
the value of .ListIndex, the first name
being zero. The user still has the option
of typing in any other name. If you
want a blank box rather than a default
name, omit the .ListIndex line.
Next, we’ll add a little idiot-proofing. In the code window, select the
amtHour object and the Exit procedure.
Complete it as shown in Figure 8.
This ensures the user types a numeric value in the Hours box: if not, a
message is displayed and the focus
won’t shift until they do. Repeat this,
with a corresponding message for the
amtRate control’s Exit procedure, but
here, add:
Else amtTotal.Value = Format
(amt-Rate.Value *
amtHours.Value, , “##,##0.00")
before the End If statement. This will
automatically update the total, formatted to two decimal places, when the
user tabs or clicks out of the Rate box.
Test the dialog again.
Note that the enter key performs in
the same way as the tab key, moving
between fields. Let’s modify this, supposing that the job description might
need to run over more than one line.
Go to txtJob properties, then set the
Multiline, Wordwrap and EnterKeyBehaviour properties to True. The Job
box will then behave like a text-editing
window and accept returns as literal.
You can even add scroll bars if you
wish, but we’ll skip the bells and whistles and move on to the buttons.
Although we’ve been testing the
mechanics of the dialog, in real use it
will be called from, and pass data back
to, a macro (or module, to use VBA
terminology). So first let’s create that
module and declare some public variables that the dialog and module can
exchange.
Right-click in the Project Explorer
and create a new module in the same
project. Name it Autobill. An empty
code window will appear with General and Declarations in the object and
procedure boxes. Type the code shown
in Figure 9.
The editor will automatically complete this by creating a new section for
the Sub and adding an End Sub. Now
go back to the Billform code (remember you can use the Window menu in
the VBA editor), and create the code for
the buttons. If the user cancels, then all
we need to do is to close the dialog and
return an indication that he or she has
cancelled. So, complete the Click procedure of the btnCancel object to read:
Private Sub btnCancel_Click()
forgetit = True
Unload Me
End Sub
is shown in Figure 11. This calls the
form with the Show method. If the user
cancels, then a message box appears
(note the use of the vbExclamation constant instead of the numeric value 48)
and nothing further happens. If the
Create button is pressed, then a new
document is created based on
BILLTEMPLATE.DOT. The For
Each... Next loop scans the Autotext
entries for a match for the client’s
name. If found, the entry is pasted in at
the Address bookmark. If not, the
name is pasted in and the user is asked
to add the rest of the address.
Next, the selection is moved to the
Details bookmark and the rest of the
billing details passed from the dialog
box are inserted into the document,
using a With block. The Collapse
method deselects the text that has just
been inserted, so it isn’t overwritten.
And that concludes this simple example, and the article. Though both
can only offer a brief dip into VBA
programming, I hope that they give
you the impetus to take the plunge.
The Unload statement, unsurprisingly, closes its object. The Me keyword is another timesaver - when used
in the code for a form or control it
represents the code name of the user
form. We can now complete the form
by writing the Click procedure for the
btnCreate - see Figure 10.
Going back to the module code, all
we now need to do is call the dialog,
and do something with the data returned. Since we’re rapidly running
out of space, I’m going to cheat a little
here and make the following assumptions. There is a user template in the
default template folder named
BILLTEMPLATE.DOT that contains:
1. Autotext entries that expand the
names used in the client list to full
names and addresses.
2. Bookmarks in the template named
address and details.
3. Suitable boilerplate text to encase
the invoice data.
4. A mechanism for inserting an
invoice number and the date - this
is left as an exercise for the reader.
The complete code for the module
PCSA
The Author
Tim Nott (timn@cix.co.uk) is an IT
writer based in France.
Did you like this tech support article? Then click here for lots more, all FREE!
New Reviews from Tech Support Alert
Anti-Trojan Software Reviews
A detailed review of six of the best anti trojan software programs. Two products
were impressive with a clear gap between these and other contenders in their
ability to detect and remove dangerous modern trojans.
Inkjet Printer Cartridge Suppliers
Everyone gets inundated by hundreds of ads for inkjet printer cartridges, all
claiming to be the cheapest or best. But which vendor do you believe? Our
editors decided to put them to the test by anonymously buying printer cartridges
and testing them in our office inkjet printers. Many suppliers disappointed but we
came up with several web sites that offer good quality cheap inkjet cartridges
with impressive customer service.
Windows Backup Software
In this review we looked at 18 different backup software products for home or
SOHO use. In the end we could only recommend six though only two were good
enough to get our “Editor’s Choice” award
The 46 Best Freeware Programs
There are many free utilities that perform as well or better than expensive
commercial products. Our Editor Ian Richards picks out his selection of the very
best freeware programs and he comes up with some real gems.
Tech Support Alert
http://www.techsupportalert.com