Storing Values When a Macro Ends

When a macro ends, the values stored in its variables are lost. If a macro needs to preserve a value, it must store that value outside itself, preferably in a place from which the value can be easily retrieved. Consider, for example, a document-numbering macro that runs each time a document is created and assigns a unique number to the new document. Each time a document is created, the macro must "remember" the number it assigned to the previous document the last time it ran, so that it can generate an appropriate new number. Then the macro must store the new number so that the number can be referenced the next time the macro runs.

This section describes how a macro can use a settings file, document variables, document properties, or AutoText entries to store information.

Settings Files

A settings file is a file used by programs and macros to store values; you can think of a setting as a variable stored in a file. In Windows terminology, WIN.INI, the settings file used by Microsoft Windows 3.x and many 16-bit Windows-based applications, is a "public" settings file because it can be used by more than one application. Settings files created for use by particular applications are "private" settings files. In Windows, settings files are text files and can be opened by a text editor like any other text file. On the Macintosh, settings files are not text files; they can only be edited directly using the ResEdit™ program.

WordBasic provides the SetPrivateProfileString statement and the GetPrivateProfileString$() function for accessing private settings files. You
use SetPrivateProfileString to assign a setting to a private settings file. Here is
the syntax:

SetPrivateProfileString Section$, KeyName$, Setting$, Filename$

Section$ is the name of a section within the settings file. KeyName$ is the name of the "key" — the equivalent of a variable name. Setting$ is the value you are assigning to the key. Filename$ is the name of the settings file. If the file doesn't exist, SetPrivateProfileString creates it. Here's what a typical Windows settings file might look like if you opened it in a text editor.

The settings files for Windows-based applications usually have filenames with
the .INI filename extension. ("INI" is short for "initialization"; a settings file is
also known as an initialization file because an application that is starting up, or initializing, can use its initialization file to retrieve settings from the last time it ran.) Although you can give any extension to the Windows settings files you create, using the .INI extension helps to make their purpose clear. On the Macintosh, it's similarly useful to include "Settings" in a settings filename. One advantage of creating a settings file with SetPrivateProfileString is that the file is stored automatically in the Windows folder in Windows or in the Preferences folder on the Macintosh (assuming you don't specify a path for Filename$). Since the instruction doesn't specify the name of the Windows or Preferences folder, your macro isn't dependent on a particular folder name or structure, and you can distribute it to other users without modification.

WordBasic does not include statements or functions to handle numeric values in settings files. To store a numeric value, first use the Str$() function to convert it to a string. To retrieve the value, use the Val() function to convert the string setting back to a number.

You use GetPrivateProfileString$() to retrieve the value of the specified KeyName$ stored in a settings file. Here is the syntax:

GetPrivateProfileString$(Section$, KeyName$, Filename$)

Section$, KeyName$, and Filename$ are used in the same way as the arguments in the SetPrivateProfileString statement.

You can use any number of settings files, but it's best to avoid using more files than necessary. In fact, you can use a single settings file for all your macros. Section headings provide a way to group settings and prevent key-name conflicts. For example, two different macros can both use a key called "Directory 1" without conflict, assuming the two key names are associated with different section names. In Windows, a settings file is just a text file, so you're not restricted to only using WordBasic instructions to access it. If you've forgotten what you've stored, you can always use Word to open a Windows settings file in a document window. On the Macintosh, you can use the ResEdit program to edit a settings file.

Examples

Here is a simple document-tracking macro that assigns a number to every new document. The macro is an AutoNew macro that runs whenever a new document is created. The macro uses GetPrivateProfileString$() to retrieve the current document number, increments it by 1, and then uses SetFormResult to insert the number in a form field. Finally, the macro uses SetPrivateProfileString to store the new number in the settings file.


Sub MAIN
docnum$ = GetPrivateProfileString$("DocTracker", "DocNum", "MACRO.INI")
docnum$ = Str$((Val(docnum$) + 1))
SetFormResult "DocNumField", docnum$
SetPrivateProfileString "DocTracker", "DocNum", docnum$, "MACRO.INI"
End Sub

Using a For…Next loop to retrieve or assign a large number of settings is a very useful technique. The following subroutine uses a For…Next loop to retrieve a list of seven folder names from a settings file and load them into an array. The key names for the folder names include numbers: "Dir 1" for the first key,
"Dir 2" for the second key, and so on. The loop uses these numbers to enumerate
the key names so that, instead of requiring a separate GetPrivateProfileString$() for each key name, the subroutine can use just one instruction.


Sub GetDirNames
For count = 1 To 7
    dirListname$ =  "Dir" + LTrim$(Str$(count - 1))
    dirNames$(count - 1) = GetPrivateProfileString$("DirList", \
                            dirListname$, "MACRO.INI")
Next
End Sub

This subroutine is used in the ChangeDirectory macro provided in the EXAMPLES.DOT (Windows) or MACRO EXAMPLES (Macintosh) template supplied on the Microsoft Word Developer's Kit disk. The macro displays the dialog box shown in the following illustration. By selecting one of the folders listed, the user can quickly move to that folder.

Using the WIN.INI File

WIN.INI is the "public" settings file used by Windows 3.x. Using the SetProfileString statement and GetProfileString$() function, you can store information in and retrieve information from the WIN.INI file in the same way you can with private settings files.

In addition to Windows 3.x, 16-bit Windows-based applications such as Word version 6.0 for Windows store settings information in WIN.INI, and this can lead to a large, inefficient file. For this reason, it's usually best not to store private settings in the WIN.INI file. But SetProfileString and GetProfileString$() can be useful for retrieving and changing Windows environment settings in WIN.INI.

Note

Windows 95 and Windows NT do not use the WIN.INI file. Instead, they store settings in the registry. SetProfileString and GetProfileString$() are available in Windows 95 and Windows NT, but there is no reason to use them, as they do not affect settings in the registry; in effect, they become limited versions of SetPrivateProfileString and GetPrivateProfileString$() that work with just one settings file that happens to be called WIN.INI.

Example

This Word version 6.0 example checks the Windows 3.x "long date" format. If the format doesn't match "dddd d MMMM yyyy" (for example, "Sunday 23 May 1993"), SetProfileString changes the setting to that format.


format$ = GetProfileString$("intl", "sLongDate")
If format$ <> "dddd d MMMM yyyy" Then
    SetProfileString "intl", "sLongDate", "dddd d MMMM yyyy"
End If

Accessing WINWORD6.INI and Word Settings (6)

Word version 6.0 for Windows settings are stored in a settings file called WINWORD6.INI; in Word version 6.0 for the Macintosh, they're stored in the Word Settings (6) file. In Windows, you can use GetPrivateProfileString$() and SetPrivateProfileString to retrieve and change settings. On the Macintosh, you can use GetProfileString$() and SetProfileString to change settings in the Word Settings (6) file. For example, the following Word version 6.0 for Windows instruction sets the Word DDETimeOut setting to 100 seconds in WINWORD6.INI:


SetPrivateProfileString "Microsoft Word", "DDETimeOut", \
"100", "WINWORD6.INI"

Here is the equivalent instruction for Word version 6.0 for the Macintosh:


SetProfileString "Microsoft Word", "DDETimeOut", "100"

Accessing the Windows Registry

In Windows 95 and Windows NT, the registry is a system-wide database used for storing software and hardware configuration settings. The registry is created during system setup and is updated whenever you add or remove software or hardware. Windows 95 and Windows NT store settings in the registry instead of the WIN.INI file. You can view and edit the contents of the registry using the Registry Editor (REGEDIT.EXE in Windows 95, REGEDT32.EXE in
Windows NT).

While most settings for Word version 6.0 for Windows are stored in WINWORD6.INI, most settings for Word version 6.0 for Windows NT and Word version 7.0 are stored in the registry under the following key: HKEY_CURRENT_USER\Software\Microsoft\Word\6.0 (or 7.0).

From WordBasic, you can access the registry information using the GetPrivateProfileString$() function. You use an empty string ("") instead of the name of a settings file to specify the registry. For example, the following instruction assigns the Word version 7.0 document path (DOC-PATH) from the registry to the variable a$:


key$ = "HKEY_CURRENT_USER\Software\Microsoft\Word\7.0\Options"
a$ = GetPrivateProfileString$(key$, "DOC-PATH", "")

You can also modify information in the registry using the SetPrivateProfileString statement. Note that even though you can use SetPrivateProfileString to add keys to the registry, macro settings are best stored in a private settings file to avoid corrupting important application settings.

Example

The DateFormat setting in the registry sets the default date format for Word version 7.0. This example uses the SetPrivateProfileString statement to set the date format to "dddd d MMMM yyyy." A future date is calculated and the result is then displayed in the new date format.


Sub MAIN
key$ = "HKEY_CURRENT_USER\Software\Microsoft\Word\7.0\Options"
SetPrivateProfileString(key$, "DateFormat", "dddd d MMMM yyyy", "")
MsgBox Date$(Now() + 7)
End Sub

Document Variables

A document variable is a variable stored as part of a document. It is available
only when the document in which it is stored is the active document. Document variables are similar to key names in a settings file; they are accessed through the complementary SetDocumentVar statement and GetDocumentVar$() function. Here is the syntax for SetDocumentVar:

SetDocumentVar VariableName$, Text$

VariableName$ is the name of the document variable and Text$ is the string value you are assigning to the variable. Document variables accept only string values. Here is the syntax for GetDocumentVar$():

GetDocumentVar$(VariableName$)

Document variables are available only through WordBasic instructions, so the user cannot inadvertently change them. And since they are contained within the document, they travel with it: If you move the document to another computer, for example, the document variables remain available. A document can contain any number of document variables.

If you add document variables to a template, the variables, including their values, will be stored in all new documents that are subsequently based on the template.

Note

Document variables are not saved when a document is saved in rich-text format (RTF).

If you plan to store a document variable in a document that may contain other document variables, you should ensure that the variable name you are planning to use does not already exist in the document. Two functions are provided for this purpose: CountDocumentVars() and GetDocumentVarName$(). CountDocumentVars() returns the number of document variables stored
in the active document. Given a number between 1 and the value returned by CountDocumentVars(), GetDocumentVarName$() returns the name of the corresponding document variable. For example, the following instructions determine whether a document variable named "TrackingNum" already exists
in a document:


For count = 1 To CountDocumentVars()
    If GetDocumentVarName$(count) = "TrackingNum" Then
        MsgBox "TrackingNum already exists."
        Goto bye
    End If
Next
bye:

Deleting a Document Variable

WordBasic does not include a command to delete document variables, but if you set a document variable to an empty string, the document variable is removed. For example, the following instruction removes a document variable called ReminderMsg:

SetDocumentVar ReminderMsg, ""

The following instructions remove all of the document variables from a document:

For count = 1 To CountDocumentVars()

SetDocumentVar GetDocumentVarName$(1), ""

Next

Another way to remove all of the document variables in a document is to save the document in rich-text format (RTF). Since document variables are not saved in RTF, they will no longer be in the document.


Example

This macro displays a dialog box showing the revision history for a document
and providing a text box in which the user can type a new entry. Each entry in the revision history is stored in a document variable. Before displaying the dialog box, the macro retrieves the revision entries from the document variables and loads them into an array that will be displayed in a list box. If the user creates a new revision entry, the macro adds the current date as a prefix and stores the entry in a new document variable.


Sub MAIN
If CountDocumentVars() > 0 Then
    Dim docVarArray$(CountDocumentVars() - 1)
    For count = 1 To CountDocumentVars()
        docVarArray$(count - 1) = \
GetDocumentVar$(GetDocumentVarName$(count)) Next Else Dim docVarArray$(0) End If Begin Dialog UserDialog 508, 214, "Revision History" Text 12, 133, 105, 13, "New Revision", .Text2 TextBox 12, 149, 453, 18, .NewRevision OKButton 380, 186, 88, 21 CancelButton 282, 186, 88, 21 Text 12, 6, 80, 13, "Revisions:", .Text1 ListBox 12, 21, 473, 106, docVarArray$(), .ListBox1 End Dialog Dim dlg As UserDialog x = Dialog(dlg) If dlg.NewRevision <> "" Then revVarName$ = "rev" + LTrim$(Str$(CountDocumentVars())) revText$ = Date$() + " - " + dlg.NewRevision SetDocumentVar revVarName$, revText$ End If End Sub

Here is the dialog box, showing some sample revisions.

Document Properties

Like document variables, document properties allow you to store information along with a document. Document properties can be viewed and modified in the Properties dialog box (File menu). Unlike document variables, document properties can be inserted into a document using the DOCPROPERTY field.

Note

Document properties are available only in Word version 7.0.

Document properties are defined using the SetDocumentProperty statement. Here is the syntax for SetDocumentProperty:

SetDocumentProperty Name$, Type, Value[$], CustomOrBuiltIn

Name$ is the name of the document property and Type specifies the data type you want to store in the document property. Value[$] is the number, string, or date you are assigning to the document property. CustomOrBuiltIn specifies whether you are defining a custom or built-in property. (Document properties include custom properties that you add as well as built-in properties such as "Company.")

Examples

This example prompts for a company name and then set the results in the built-in "Company" document property.


CompanyName$ = InputBox$("Type your company name", "Company Name")
SetDocumentProperty("Company", 0, CompanyName$, 1)

The text you type appears as the company name on the Summary tab in the Properties dialog box (File menu).

The following macro displays a dialog box showing the built-in and custom document properties for the active document. Prior to displaying the dialog box, the macro retrieves the document property names and stores them in an array. If the user chooses OK, the contents of the selected property are inserted into the document.


Sub MAIN
Dim prop$(CountDocumentProperties() - 1)
For count = 1 To CountDocumentProperties()
    prop$(count - 1) = DocumentPropertyName$(count)
Next
Begin Dialog UserDialog 340, 144, "Document Properties"
    OKButton 229, 104, 88, 21
    CancelButton 131, 104, 88, 21
    ListBox 24, 12, 293, 84, prop$(), .property
End Dialog
Dim dlg As UserDialog
n = Dialog(dlg)
If prop$(dlg.property) <> "" And n = - 1 Then
    Insert prop$(dlg.property) + ":" + Chr$(9)
    type = DocumentPropertyType(prop$(dlg.property))
    Select Case type
        Case 0, 2, 3
            text$ = GetDocumentProperty$(prop$(dlg.property))
            Insert text$
        Case 1
            Num = GetDocumentProperty(prop$(dlg.property))
            Insert LTrim$(Str$(Num))
        Case Else
    End Select
End If
End Sub

The previous macro inserts document properties as plain text. You can also insert document properties using the DOCPROPERTY field. For example, the following instruction inserts a field that references the "Company" document property:


InsertField .Field = "DOCPROPERTY Company"

The DOCPROPERTY field ensures that the latest property information appears in your document when the field is updated.

AutoText Entries

AutoText entries can be used to store information in a template. The SetAutoText statement defines a text-only AutoText entry. Here is the syntax:

SetAutoText Name$, Text$ [, Context]

Name$ is the AutoText entry name, Text$ is the text defined with the AutoText entry, and Context indicates where the AutoText entry is stored (the active template or the Normal template). The complementary GetAutoText$() function retrieves the contents of an AutoText entry.

Example

The following macro defines an entry named INVOICE# in the active template (a template other than Normal). Each time the macro is run, the invoice number in the INVOICE# AutoText entry is incremented by one. If this macro were named AutoNew and stored in a special invoice template, the macro would automatically insert an invoice number with each new invoice created.


Sub MAIN
number = Val(GetAutoText$("INVOICE#", 1)) + 1
InvoiceNum$ = LTrim$(Str$(number))
SetAutoText "INVOICE#", InvoiceNum$, 1
Insert "Invoice: " + invoicenum$
End Sub