Using your VB Skills within Word

Note: I am using Word 6.0 for these examples. WordBasic is a slightly more primitive environment than you will see in Word 7 or 8, but the principles remain largely the same. We will be looking at several environments. As usual, concepts are more important than details

The language

WordBasic was the first major scripting language

Closely tied to QBASIC

Evolved with VB

Eventually evolved into VBA, but last to translate

Variables

No DIM statement!! All variable creation done on the fly

Only two types. If it ends with $, it is a string. Otherwise, numeric

EG userName$ -- string myValue - numeric

Most variables are local

Strings are King in WordBasic. ALL input and output happens in strings. Use numeric variables only for mathematical calculations.

Convert from number to string with the Str$(numericValue) function,

Convert from string to number with Val(StringValue) function

Control structures

Standard if - elseif -end if structure

While - wend (no do loop)

For - next loop

Select Case

Input / Output

Use the InputBox$ function to ask the user a question through a modal dialog.

Syntax: userName$ = InputBox$("What is your name?")

Use the MsgBox command to tell the user something in a modal dialog

Syntax: MsgBox("Hi there, this is my message")

Note that there is fancier syntax for both inputBox$ and MsgBox

Especially interesting is the function version of MsgBox that allows yes/no questions

Output to the screen is handled through the insert statement

Syntax: Insert "This is the string value I want to insert"

Input from the screen essentially done through Selection$()

This function returns the value of the text currently selected

Syntax: myString$ = selection$()

Word - specific functions

Often related to default location on menubar

(EG EditSelectAll, FileClose)

For best results, record and analyze (see below)

Recording a macro

Under Tools, choose Macro, then type a name and press "Record"

Do what you want to do. It's best if you have rehearsed

A special toolbar with a circle (record) and box (stop) will appear

Click on the stop button to stop recording

Use Tools_Macro Edit to look at the code generated by the macro

Each thing you did will result in a line or two of code

Modifying the results

When editing a macro, the first key is to examine it closely and try to determine what caused what to happen.

Comment the auto-generated code to indicate what you think is going on

It may run with no modifications, but it may need some.

In general, you may have to add control structures.

If you add variables, you will need to also add some way of getting values to or from the variables

(See examples)

Using complex commands

You may find you want to do a command such as search and replace, or open file, that usually calls up a complex dialog box.

The way to deal with these commands is to write code up to the point where such a command is needed.

Then Use the record one button (a circle with a one beside it) to record only one command.

Execute the entire command through menus, toolbars, dialogs, or whatever.

Keep going until the command returns you to an editing screen

The code generated by the command will be dumped to the current cursor position of the current MACRO editing file.

This code could be ugly.

Usually it consists of a command name followed by a bazillion dot arguments, such as this:

FormatFont .Points = "16", .Underline = 0, .Color = 2, .Strikethrough = 0, .Superscript = 0, .Subscript = 0, .Hidden = 0, .SmallCaps = 0, .AllCaps = 0, .Spacing = "0 pt", .Position = "0 , .Kerning = 0, .KerningMin = "", .Tab = "0", .Font = "Desdemona", .Bold = 1, .Italic = 0, .Outline = 0, .Shadow = 0

FormatFont is the command, and everything else is one of the details that can be changed in the Format Font dialog box.

All this must be one line (logically, although not physically)

The good news is that you don't usually need the whole thing. If you want to change the font to 12 point "Times New Roman", you could simply use code like this:

FormatFont .Points = "16" .Font = "Times New Roman"

The order of the arguments does not matter, but you must assign them with names as shown.

This is a bit more involved than doing positional arguments (the traditional way of VB) but it allows for functions with a LOT of arguments. (as most dialog boxes are)

Everything else would be left as it was.

To get help on all the tricky parameters, use the F1 key liberally. By hitting F1 on FormatFont, I found all kinds of help on what exactly each parameter means and what kinds of values they can accept.

Modifying toolbars

The best part of making macros is that they allow you to customize the look and feel of word itself

You can add and modify menus, key commands, and toolbars.

I find it best to modify toolbars, because they are easiest to remove and do not interfere with other commands.

(Whenever you change key bindings, you mess up people who have memorized default keys, like maybe yourself)

Any of these can be changed by calling up the customize dialog (from tools menu)

Select the ToolBars tab, and you will see something like this:

Scroll until you see Macros, and select it. Then you will also see a list of macros you have created.

Take the name of a macro, and drag it to an existing toolbar or an empty spot.

A toolbar will be created for you if you did not drop the macro into an existing one.

Now you will see some existing icons you can use. Choose text icon for the simplest option, or one of the existing icons. You can even design your own icon (cool!!)

It is also possible to copy and paste icon images from existing menus. Use the right button over a button to copy or paste its image. (That's how I made the list icons on my html toolbar

Examples

Blank HTML document

Here's a simple macro that defines a minimal HTML document

(If you don't know HTML, that's ok. It just uses a set of text tags. You'll get the hang of it.)

The basic idea is this: HTML uses a set of ASCII tags inside angle brackets (<>) called TAGS to format pages. Almost every page starts with the same basic set of tags, so it would be really great if I could have a simple way of generating a default blank page.

Expected outcome:

<html>

<head>

<title>TITLE</title>

</head>

<body bgcolor = "White">

<center>

<h1>HEADLINE<hr></h1>

</center>

<hr>

&copy; Andy Harris

</body>

</html>

The code to generate it:

Sub Main

'Andy's HTML Skeleton

cr$ = Chr$(13) 'carriage return

insert "<html>" + cr$

insert "<head>" + cr$

insert "<title>TITLE</title>" + cr$

insert "</head>" + cr$

insert "<body bgcolor = 'White'> " + cr$

insert "<center>" + cr$

insert "<h1>HEADLINE<hr></h1>" + cr$

insert "</center>" + cr$

insert "" + cr$

insert "<hr>" + cr$

insert "&copy; Andy Harris" + cr$

insert "</body>" + cr$

insert "</html>" + cr$

End sub

Notes

Mostly, the code is identical to the output except it is a series of insert statements.

Note also the use of cr$, a variable which is being used as a constant.

This is being used as the newline character, much as "\n" in C-like languages.

Notice also that I changed the quotes inside the body bgcolor line.

The double quotes confused the insert statement.

Fortunately, I could use single quotes here.

You can also use the ASCII value for the quote sign, although you'd have to look it up.

BTW, since this is so straightforward, I used keyboard macros to automate creating this code!!!! See how useful this is???!?

After I wrote this, I learned the insertPara function. It does the same thing as my cr variable. It probably would be better to use insertPara, but my code works.

A Better Skeleton

Discussion

Here's the one I really use.

Notice a few improvements…

Source Code

Sub MAIN

'skeleton

'Creates a blank default page

'define carriage return

cr$ = Chr$(13)

'get the page name from the user

PageName$ = InputBox$("Page Name?")

Insert "<html>" + cr$

Insert "<head>" + cr$

Insert " <title>" + PageName$ + "</title>" + cr$

Insert "</head>" + cr$

Insert cr$

Insert "<body bgColor = 'White'>" + cr$

Insert "<center>" + cr$

Insert "<h1>" + PageName$ + "<hr></h1>" + cr$

Insert "</center>" + cr$

Insert cr$

Insert cr$

Insert cr$

Insert "<hr>" + cr$

Insert "&copy;Andrew J. Harris <br>" + cr$

Insert "IUPUI Dept. of Computer and information Science<br>" + cr$

Insert "<a href = mailto:aharris@cs.iupui.edu>"

Insert "aharris@cs.iupui.edu</a>" + cr$

Insert "</body>" + cr$

Insert "</html>" + cr$

LineUp 9

End Sub

Comments

Notice that the code is largely the same.

The most significant addition is the use of a PageName$ variable

Note also the LineUp command at the bottom. This causes the editor to move the cursor up nine lines, so it is in the blank area. I can then immediately edit the blank part of my document.

In this way, when the macro is run, this is the output:

Output


<html>

<head>

<title>Andy's Practice Page</title>

</head>

<body bgColor = 'White'>

<center>

<h1>Andy's Practice Page<hr></h1>

</center>


<hr>

&copy;Andrew J. Harris <br>

IUPUI Dept. of Computer and information Science<br>

<a href = mailto:aharris@cs.iupui.edu>aharris@cs.iupui.edu</a>

</body>

</html>

When I save the page as pure ASCII text (NO WORD MARKUPS, of course) and load it into a browser, this is what I see:


The Italic Macro

Justification

In HTML, when you want a word or phrase to be italicized, you surround it with <I> and </I> tags. I wanted a button that would do this behavior, but it needed to be more sophisticated than that.

If the user had not selected anything, the button should just produce this code:

<I></I>

then move the cursor between the tags, so she can start editing whatever should be italicized.

As you can imagine, this simply involves an insert tag, and whatever command moves the cursor backwards.

This is useful for creating a document, but not for editing existing documents.

What I really need is something that can detect if I have selected some existing text.

If so, that text should be surrounded by <I> and </I> tags.

There's a couple of ways to do this, but probably the easiest would utilize this strategy:

Copy the results of the Selection$() function to a variable

Insert at the present point (the selected area) the starting "<I>"

This would wipe out the selection!! That's why we stored it in a variable

Now insert the value of the stored variable

Finally, insert the value of the ending tag ("</I>")

The code:

Sub MAIN

'writes the italic command

'if there is nothing selected, just write the codes

If Len(Selection$()) <= 1 Then

Insert "<i></i>"

CharLeft 4

Else

'if something is selected, surround that stuff with tags

temp$ = "<i>"

temp$ = temp$ + Selection$()

temp$ = temp$ + "</i>"

Insert temp$

End If

End Sub

The toolbar

I have taken these commands, and a number of others, and placed them on a toolbar.

My toolbar looks like this:



Dealing with Word '97

The issue

WordBasic is actually a backwards-looking language. It is more aligned to Qbasic and other procedural languages than the kind of object - based approach we are used to in VB.

The later versions of Office ship with a built in full-fledged (sorta) VB environment (!)

It supports a version of the VB syntax that will be very familiar to you.

The largest difference of course is the many application - specific objects available

Straight VB, for example, does not need to worry about a spell -checker, but VBA ought to have a way to refer to and control this item.

Cheating

Microsoft has always been pretty good about backward compatibility.

If you write a macro in Word 6.0 format, then load up its parent template into Office97, It will be automatically converted for you.

Actually, the conversion is trivial.

VBA introduces an object called WordBasic.

Its methods are identical to the commands of WordBasic

To translate a WordBasic Macro, simply append the WordBasic. Object name

Hi there in WordBasic 6.0

sub main()

insert "Hi there"

insertPara

end sub

Hi there in VBA '97

sub hiThere()

WordBasic.insert "Hi there"

WordBasic.insertPara

end sub

Discussion

As you can see, this is not very tricky

In fact, the syntax from WordBasic 2.0 through 6.0 stayed pretty constant, so WordBasic Macros have a fighting chance of working in a number of generations of Word.

It is still worth the time to learn the new syntax

Using VBA in Word97

Although many of the details are different, the general strategy is exactly the same!

Don't sweat the syntax!! Most of it will be generated for you.

The tools_macro menu works the same, but the editor is much more like standard VB than before.

The Editor is actually a separate program! You will need to switch back and forth to see results, although if you run a macro from the editor, you will see the results in Word immediately. (Wow, magic!)

You can see some sophisticated debugging tools that you may be used to.

As before, It's often a good idea to start by recording your keystrokes. This will give you a good idea of the general commands (actually object methods) being invoked.

Use the F1 key to analyze any methods you want to modify

For general control structures and data types, you can pretty much use standard VB.

Use the Object Browser to get a better feel for what objects and methods are available.

These general strategies will help you in other office applications as well. In fact, the strategy is the same even in WordPerfect, (although of course the syntax is completely different)

The HTML Skeleton in Word97 syntax

Sub htmlSkel()

'

' htmlSkel Macro

' Macro created 01/22/98 by Andy Harris

' Shows the HTML Skeleton in Office 97 Syntax

Dim pageName As String

pageName = InputBox("Page Name?")

Selection.TypeText Text:="<html>"

Selection.TypeParagraph

Selection.TypeText Text:="<head>"

Selection.TypeParagraph

Selection.TypeText ("<title>" + pageName + "</title>")

Selection.TypeParagraph

Selection.TypeText Text:="</head>"

Selection.TypeParagraph

Selection.TypeParagraph

Selection.TypeParagraph

Selection.TypeParagraph

'move up eight lines

Selection.MoveUp Unit:=wdLine, Count:=8

End Sub

The HTML Skeleton in WordPerfect Macro Syntax:

Application (WordPerfect; "WordPerfect"; Default; "US")

GetString(pageName; "Page Name?" )

Type (Text: "<html>")

HardReturn ()

Type (Text: "<head>")

HardReturn ()

Type (Text: "<title>" + pageName + "</title>")

HardReturn ()

Type (Text: "</head>")

HardReturn ()

HardReturn ()

Type (Text: "<body bgColor = 'White'>")

HardReturn()

Type (Text: "<center>")

HardReturn()

Type (Text: "<h1>" + pageName + "<hr></h1>")

HardReturn()

Type (Text: "</center>")

HardReturn ()

HardReturn ()

HardReturn ()

HardReturn ()

Type (Text: "<hr>")

HardReturn ()

Type (Text: "&copy; Andy Harris<br>")

HardReturn ()

Type (Text: "</body>")

HardReturn()

Type (Text: "</html>")

HardReturn()

PosLineUp ()

PosLineUp ()

PosLineUp ()

PosLineUp ()

PosLineUp ()

PosLineUp ()

PosLineUp ()