Using Sequential File Access

WordBasic includes a set of statements and functions you can use to access
text files without opening them in a document window. This kind of interaction
is called file input and output, or file I/O. Using file input, a macro can "read"
a file to retrieve information from it ("input" refers to input from the file into the macro). Using file output, a macro can "write" to a file to store information ("output" refers to output from the macro to the file). WordBasic supports sequential file I/O, or sequential file access, a kind of file I/O supported by most varieties of the Basic programming language. In sequential file access, the information in the file is usually read or written in sequence, from the beginning of the file to the end.

Sequential file access is used most often to provide a macro with information.
For example, a macro designed to work on a series of files can use sequential
file access to retrieve a list of filenames from a text file.

The advantage of sequential file access is that it's fast. If a macro needs to read or store information, sequential file access can do it more quickly than statements that open a file in a document window. The disadvantage, of course, is that sequential file access is more rigid than working with a file in a document window. It's difficult to go directly to a specific place in a file, and you can't
read from a file and write to it at the same time.

Note

Sequential file-access statements and functions are designed to work with text-only files, not Word document files. While it is possible to open a Word document for sequential access, it isn't useful to do so because Word documents contain formatting codes that make the file very difficult to read from or write to through sequential access. To work with a Word document, open it in a document window.

Opening a File for Sequential Access

When you open a file for sequential access, you specify whether you want to read from the file or write to it. If a macro needs both to read from and write to a file, it must open the file to read from it, close it, and then reopen the file to write to it. A macro can have as many as four files open at a time for sequential access.

To open a file for sequential access, you use the Open statement, which has the following syntax:

Open Name$ For Mode As [#]FileNumber

Name$ is the name of the file to open and FileNumber is a number between 1
and 4 that other sequential access instructions use to refer to the open file. Mode indicates how the file is to be used: for input, output, or appending. The modes are described as follows.

Mode

Explanation

Input

Opens the text file so that data may be read from the file into the macro. When you open a file for input you can use Read, Input, Line Input, and Input$() instructions to read from the file. If the specified text file isn't found, an error occurs.

Output

Opens the text file so that data may be written from the macro to the file. When you open a file for output, you can use Write and Print instructions to write to the file. Opening a file for output deletes the existing contents of the file, even if you do not write to the file. If the specified text file isn't found, a new file is created.

Append

Opens the text file so that data may be written from the macro to the file. When you open a file to append, you can use Write and Print instructions to write to the file. The existing contents of the file remain and the information you write is added to the end of the file. If the specified text file isn't found, a new file is created.


The following diagram shows the relationship between a macro and a text file in the different modes, along with the sequential file-access statements and functions available in those modes.

Writing to a File

WordBasic includes two statements for writing to a file: Write and Print. You can use these statements to write both strings and numbers. Each instruction creates a single line in a text file. In Windows, each line of the text file ends with the carriage-return and linefeed characters (character codes 13 and 10); on the Macintosh, each line ends with a single carriage-return (character code 13). You can think of each line as a single data record that can have multiple fields containing different values. Each Write and Print instruction writes sequentially to the text file, adding one line of data after another for as long as the file is open.

Write

The Write statement is designed to write data that can be easily read by the complementary Read statement. The syntax of Write is as follows:

Write #FileNumber, Expression1[$] [Expression2[$]] [¼]

FileNumber refers to the number you assigned to the file when you opened it. An Expression contains the data you're writing to the file. Usually, Expression is a string or numeric variable, but it could also be a numeric expression or a function that returns a string or number. For example, the following instruction writes the currently selected text to a file:


Write #1, Selection$()

Write places quotation marks around string values, but not around numeric values; it places a comma between each value as a delimiter. For example, the instruction


Write #1, name$, age, employeeNum

creates a line such as the following in the text file:


"John Jones", 32, 12345

Print

Unlike Write, the Print statement does not have a complementary statement designed to read whatever it writes. Print is most useful if you want to write data to a file that may be read by another application. You can also use Print to write information to be read by the Line Input statement. The syntax for Print is as follows:

Print #FileNumber, Expression1[$] [; or , Expression2[$]] [; or , ¼]

FileNumber refers to the number you assigned to the file when you opened it. Expression contains the data you're writing to the file, usually a variable, number, or string.

String and numeric values can be separated by either a semicolon or a comma. Values separated by a semicolon are joined together in the text file with a space inserted before numbers. For example, the instruction


Print #1, name$; age; employeeNum

creates a line such as the following in the text file:


John Jones 32 12345

Values separated by a comma are separated by a tab character in the text file. For example, the instruction


Print #1, "Jones", "123 1st Street"

results in the following line, with a tab character between "Jones" and "123 1st Street":


Jones    123 1st Street

None of the WordBasic sequential access instructions that read files recognize
tab characters as delimiters, but many applications support file formats that use
tab characters as delimiters. For example, you could use Print to create a tab-delimited file for a database program.

Reading from a File

The sequential file-access statements Write and Print write information sequentially, adding one line of information after another for as long as the file
is open. The information is read in the same way; after one instruction reads information, the next instruction begins reading the next piece of information, in sequence. All the statements and functions that read sequential files read a line at a time (delimited by a paragraph mark), except Input$(), which reads a specified number of characters.

Read

The Read statement is designed to read information written with Write. Here is the syntax:

Read #FileNumber, Variable1[$] [Variable2[$]] [Variable3[$]] [¼]

Read can read both numeric and string values and can read multiple values from a single line when the values are delimited by commas. It removes quotation marks from string values (placed there by Write) and can also accept strings that are not enclosed in quotation marks. Read can accept a string with as many as 65,280 characters; longer strings are truncated. The following example reads values into one string variable and two numeric variables:


Read #1, name$, age, employeeNum

Input

Like Read, the Input statement can read multiple values from a single line when the values are delimited by commas. However, Input does not remove quotation marks from strings, so it doesn't work well with Write, which places quotation marks around string values. Input uses the same syntax as Read, as shown in this example:


Input #1, name$, age, employeeNum

Line Input

The Line Input statement reads an entire line, including commas or other delimiters, and places it into a string variable. Here is the syntax:

Line Input #FileNumber, Variable$

Variable must be a string variable, even if the line contains numbers only. A line is delimited by a paragraph mark. Line Input can accept lines as long as 65,280 characters; longer lines are truncated.

Input$()

With the Input$() statement, you specify exactly how many characters to read. Here is the syntax:

Input$(NumChars, [#]FileNumber)

NumChars is the number of characters Input$() reads from the file identified
by FileNumber. Input$() can read any number of lines (as many lines as are contained in the specified number of characters) and returns every character within the specified range of characters, including delimiters such as commas
and carriage returns.

Input$() is generally not as useful as the other statements that read sequential files, but you can use it to read a file that uses delimiters that the other sequential file-access statements and functions don't support.

In the following example, Input$() is used to read a file in which values are delimited by a space character. The file contains 20 employee numbers, which Input$() reads into an array. Each employee number is five characters long and is separated from the following number by a space. Each time Input$() reads five characters, it also moves the point at which data is read five characters ahead, so that the next Input$() instruction begins reading the next character. Because there is a space between each number, the macro includes the instruction space$ = Input$(1, #1), whose purpose is just to read the space preceding the next number. Otherwise, the second Input$() instruction would begin by reading
the space character and miss part of the next employee number.


Dim empNums(19)
Open "EMPNUMS.DAT" For Input As #1
    For count = 0 To 19
        empNums(count) = Val(Input$(5, #1))
        space$ = Input$(1, #1)
    Next
Close #1

Closing a File

As mentioned earlier, once you've opened a file in a specific mode — for input, output, or appending — you have to close it before you can open it in a different mode. For example, if a macro opens a file to read some information from it and then needs to overwrite the existing information or append additional information, it must close the file and then reopen it in the appropriate mode. Here is the syntax of the Close statement:

Close [[#]FileNumber]

FileNumber is the number of the file to close. If FileNumber is not specified, all files opened with the Open statement are closed.

Other Sequential Access Statements and Functions

WordBasic includes four other sequential file-access statements and functions: Eof(), Lof(), Seek, and Seek().

Eof()

The Eof() function returns a value of –1 when the end of a file has been reached. Typically, Eof() is used to control a While¼Wend loop that reads a file until it reaches the file's end. Here is the syntax for Eof():

Eof([#]FileNumber)

FileNumber is the number assigned to the file when it was opened. The following example reads a list of Word document filenames from a text file. For each document filename, the corresponding file is opened, the DoFormattingRoutine subroutine (not shown here) performs various formatting actions, and the file is closed. The Eof() function controls a While¼Wend loop, so that every filename in FILES.TXT is read until the end of the file is reached.


Sub MAIN
Open "FILES.TXT" For Input As #1
While Not Eof(#1)
    Read #1, file$
    FileOpen file$
    DoFormattingRoutine
    FileClose 1
Wend
Close #1
End Sub

Lof()

The Lof() function returns the length of a file, in bytes, opened with an Open instruction. Each byte corresponds to one character in the file. Among other things, you can use Lof() to determine whether a file contains any information. Here is the syntax for Lof():

Lof([#]FileNumber)

FileNumber is the number you assigned to the file when you opened it. The following example determines whether a file contains any information before opening it for output and overwriting it. After the file is opened for input, the Lof() function is used to determine whether or not the file already contains information. If it does, a message box is displayed, asking if you want to overwrite the file. If you choose the Yes button in the message box, the file
is closed and then reopened for output.


YES = - 1
Open "EMPNUMS.DAT" For Input As #1
If Lof(#1) > 0 Then
    answer = MsgBox("Do you want to overwrite this file?", 4)
    If answer = YES Then
        Close #1
        Open "EMPNUMS.DAT" For Output As #1
        'Series of instructions to write information to the file
    End If
End If
Close #1

Seek, Seek()

The Seek statement changes the point in a file at which information is retrieved or stored. Here is the syntax:

Seek [#]FileNumber, Count

The Seek() function returns the point in the file where information will next be retrieved or stored. Here is the syntax:

Seek([#]FileNumber)

Usually the Seek statement and Seek() function are used together. You use the Seek() function to return the position of an item; then you use the Seek statement to move directly to that location.

You can use Seek with other sequential access statements and functions to write information into the middle of a file rather than appending it at the end, but this technique has limited use. Whatever is written to the file overwrites the corresponding number of characters in the same position in the file.

The following example is part of a macro to sort mail messages by sender and by subject. The text file MSGS.TXT contains sender names and subject categories. This example searches for the heading "Monthly Reports" in the file, records its position in the variable readposition, and then closes the file. Next, the file is opened to append information to the file, and then closed again. Finally, the file is reopened for input and the instruction Seek #1, readposition moves directly to the position where the "Monthly Reports" heading is located.


Open "MSGS.TXT" For Input As #1
While Not Eof(#1) And searchtext$ <> "Monthly Reports"
    readposition = Seek(#1)
    Line Input #1, searchtext$
Wend
Close #1
Open "MSGS.TXT" For Append As #1
    'Series of instructions to append data to the file
Close #1
Open "MSGS.TXT" For Input As #1
Seek #1, readposition