A lot of your programming effort, and a lot of the material in this book, is geared toward getting information into your program and processing it. However, all the input and processing isn't much good if you can't get the results back out to the user. In this chapter, we focus on basic reporting and information display. When we use the term "reporting" we are not only referring to printed reports, but also on-screen information. The techniques discussed in this chapter can be used to produce both types of reports. You can also write report functions that are generic enough to be used for both the screen and printer.
If a paper report is not necessary, you can create fairly sophisticated-looking reports on-screen with some of Visual Basic's custom controls. In this section, we look at three controls suitable for doing this: the text box, the rich text box, and the list box.
You already know from earlier chapters that the Label and TextBox controls can display multiple lines of information in a variety of fonts and colors. If your report is mainly paragraphs of text, a TextBox control might be ideal. The MultiLine and ScrollBars properties allow the user to view more text than will fit on the screen at a time. By using the intrinsic constants vbCrLf to force a new line and vbTab to hit the tab stops, you can easily format a text box like the one in Figure 15.1.
FIG. 15.1
Simple reports can be created by using the TextBox control.
In Figure 15.1, all the formatting "logic" is in the text itself, not the text box. The way to code something like this is to fill the Text property incrementally:
Text1.Text = Text1.Text & "New Text"
However, rather than repeatedly accessing the Text property, it is more efficient to build your string in a local variable first and then assign it to the text box:
Dim stHeader As String stHeader = "Gorman's Motorcycles" & vbCrLf stHeader = stHeader & "1234 Fifth Street" & vbCrLf stHeader = stHeader & "Anytown, MI 67321" & vbCrLf txtRpt.Text = txtRpt.Text & stHeader & vbCrLf
Note in the preceding example the use of the constant vbCrLf to insert a special new line character. In addition, the tab character (vbTab) can be used to create a column effect:
stTemp = stTemp & " 1" & vbTab & "Carburetor" & vbTab & "$100.00" & vbCrLf
If each item in a column has a different length, you might want to use spaces instead of tab characters:
`This code inserts one column inPadSpaces = COLWIDTH - Len(stNewText) If inPadSpaces < 0 then inPadSpaces = 1 txtRpt.Text = txtRpt.Text & stNewText & Space(inPadSpaces)
Note the use of the Space() function, which creates a string with the specified number of space characters.
Text boxes can also be assigned large strings without any formatting, like the bottom (Guarantee) section in Figure 15.1. If no special characters are included and the Multiline property is set to True, the text box simply wraps words automatically.
See "Modifying Text with a Program," Chapter 14
TIP: To make sure your columns line up properly, use a nonproportional font, such as Courier.
A big drawback of using the TextBox control is that color and font options can only be applied to the entire text box. A rich text box, on the other hand, has no such limitations. It allows sections of text to be formatted individually and includes additional options such as bulleted lists and embedded objects.
The RichTextBox control is designed to work with the Rich Text File Format (RTF). RTF is a standard file format for documents, similar to DOC or HTML. Both WordPad and Microsoft Word have the capability to read and write RTF files. As a matter of fact, this feature is also built in to the RichTextBox control with the LoadFile and SaveFile methods:
Private Sub cmdLoad_Click() Rtb1.LoadFile "C:\MYFILE.RTF" End Sub Private Sub cmdSave_Click() Rtb1.SaveFile "C:\MYFILE.RTF" End Sub
In addition to loading and saving files, the text in a rich text box can also be manipulated with code. You probably can already imagine some useful applications. For example, you could generate reports from a database, save them to RTF format, and e-mail them to your users-- all from within a Visual Basic program.
The real strength of a RichTextBox control is in the formatting, which enables you programmatically to create sharp-looking documents like the one shown in Figure 15.2.
If you browse through the RichTextBox control's properties, you'll notice options for underlining, color, and font characteristics. The Sel prefix on many of them indicates that they affect only the selected (or highlighted) text. For example, the following code makes the selected text bold:
RichTextBox1.SelBold = True
FIG. 15.2
A rich text box allows you to use multiple formatting options within the same
text box.
As with the text box, you can assign text using the Text property. Every time you set this property, the RichTextBox converts it to RTF format. You can view the RTF codes (similar to viewing HTML source) in the TextRTF property or by opening an RTF file with a text editor.
Let's look at the code used to create the report in Figure 15.2. First, I added all the information using the Text property:
Dim s As String s = "Investment Options Report" & vbCrLf & vbCrLf s = s & "Client" & vbCrLf & "N. D. Lazenby" & vbCrLf & vbCrLf s = s & "Categories" & vbCrLf s = s & "Retirement plan" & vbCrLf s = s & "Stock options" & vbCrLf s = s & vbCrLf & "Profits" & vbCrLf rtb1.Text = s
Next, I formatted the first line, so I selected it with the SelStart and SelLength properties:
rtb1.SelStart = 0 rtb1.SelLength = Len("Investment Options Report") rtb1.SelFontSize = 12 rtb1.SelItalic = True rtb1.SelBold = True
A quicker way to highlight some text is the built-in Find method:
rtb1.Find "Client", 0 rtb1.SelUnderline = True rtb1.SelFontSize = 11
When used as a function, Find returns the search string's starting position:
Dim nPos1 As Integer, nPos2 As Integer nPos1 = rtb1.Find("retire", 0) nPos2 = rtb1.Find("options", 20) + Len("options") rtb1.SelStart = nPos1 rtb1.SelLength = nPos2 - nPos1 rtb1.SelBullet = True rtb1.SelBold = False rtb1.SelIndent = 200
Rich Text boxes also support embedded OLE objects, such as bitmaps:
Dim obj as OLEObject Set obj = rtb1.OLEObjects.Add (, , "C:\graph.bmp","Paint.Picture")_
Another way to present lists of information is to use the ListBox control. This control enables you to add items to a list; the user can then scroll through them. While list boxes are used primarily for presenting choices to the user and allowing him to pick one or more items, they can also be used for simple reports. Listing 15.1 shows how a list box might be used to display a list of students and grades.
'This code assumes the students and grades 'have already been stored in variable arrays Dim I As Integer Dim inPadSpaces As Integer Const NUMSTUDENTS = 10 Const COLWIDTH = 20 lstGrades.Font.Name = "Courier New" `Non-proportional font lstGrades.Clear For I = 1 To NUMSTUDENTS inPadSpaces = COLWIDTH - Len(Student(I)) If inPadSpaces < 0 Then nPadSpaces = 1 lstGrades.AddItem Student(I) & Space(inPadSpaces) & CStr(Grade(I)) Next I
Figure 15.3 shows what a list box would look like after executing the code in Listing 15.1.
NOTE: Although you cannot tell from looking at it, the student names in Figure 15.3 were not added in alphabetical order. Setting a list box's Sorted property to True at design time keeps your list sorted as you add items to it.
FIG. 15.3
Tabular reports can be created in a list box.
The list box has the added benefit of knowing if the user has selected an item. The items of a list box are stored in its List array, and the selected item's array index is stored in the ListIndex property. You can determine which item is selected by placing some code in the list box's Click event:
Private Sub lstGrades_Click() Dim stStudent As String Const COLWIDTH = 20 stStudent = lstGrades.List(lstGrades.ListIndex) stStudent = left$(stStudent,COLWIDTH) Msgbox "You clicked on " & stStudent End Sub
Instead of just using the MsgBox statement, your example could be expanded to display more information about the selected student. Note that in the preceding code you pull the student name directly from the list. The ListBox control also has a property called ItemData that can be used to store an integer value that is not displayed--for example, student ID number.
See "Working with Lists," Chapter 9
The list box concludes the discussion of simple reports with custom controls. However, it is important to note that if you do any serious on-screen reporting, you will probably rely on a grid control more than any of the controls discussed in this chapter. There are a number of third-party grid controls available. In a later chapter, we discuss the Flex Grid, which is included with Visual Basic.
See "Using the MSFlexGrid control," Chapter 11
For many tasks, it is convenient to display information on the screen; however, sometimes there is just no substitute for the printed page. Printed reports are simply more convenient to carry with you to read on the plane, in a meeting, or during the commercials in your favorite TV program. The reports you create can be simple, containing plain text and some columns of numbers; or the reports can be very elaborate, containing font and color effects, tables, and even graphs. You can create any type and complexity of report in Visual Basic using the techniques in this chapter. The key is in the layout and testing of the report. Unfortunately, Visual Basic does not ship with a visual report designer for general-purpose printing. Therefore, you must work with the old-fashioned method of "code and test." After you get a little experience, however, most printing tasks become relatively easy.
NOTE: Visual Basic ships with Crystal Reports, which is a visual report designer mainly used for database reports. This designer and its associated control are covered in Chapter 29, "Using the Visual Basic Data Control."
The primary means of printing text is the Print method. An object's Print method is used just like any other method. For example, place the following line of code in a form's Click event:
Form1.Print "Hello, World!"
Every time you click the form, a new line of text appears. While we will primarily discuss printing information to paper using the Printer object, the Print method works with the following four objects in Visual Basic:
The code statements you use to create your printout work the same way no matter which of these output objects you specify. In fact, you can use a class to create a generic print routine that will work with any output object.
In its simplest form, the Print method specifies the object where you want to print, the Print method itself, and the information you want to have printed. For example, the following statement prints a string of text to the printer:
Printer.Print "This prints a single line of text."
Used in this way, the Print method prints a single piece of information and then advances to the next line of the printer. The information you print is not limited to text. You can print text, numbers, or dates by using the Print method. Also, as you might expect, you can specify the information to be printed using either literals or variables. The following lines show several print examples:
Dim stVariable As String, inVariable As Integer stVariable = "This is text information" inVariable = 500 Printer.Print "Print a single string" Printer.Print stVariable Printer.Print 25 Printer.Print inVariable
The Print method would be of limited usefulness if you could only print a single item at a time. In fact, you can send multiple pieces of information to the printer (or other object) using the Print method. To print more than one item, simply place multiple items in the print list, and separate each item with a comma or a semicolon. If you separate two items with a comma, the second item is printed in the next print zone. This usually places some space between the items, as each print zone is 14 characters wide. If you separate the items with a semicolon, the second item is printed immediately after the first item, with no intervening spaces.
The following code sample (see Listing 15.2) shows how separators make a difference in where information is printed. The output from this code is shown in Figure 15.4.
Dim s1 As String Dim s2 As String s1 = "String 1" s2 = "String 2" `Print s1 and s2 on the same line with no spaces picTest.Print s1; s2 `Print a blank line picTest.Print `Print s1 and s2 separated by some spaces picTest.Print s1; picTest.Print " "; s2 `Print a blank line, then s1 and s2 in separate print zones picTest.Print vbCrLf & s1, s2
FIG. 15.4
The separators between items in a print statement determine the amount of
space between them.
You can, of course, include a lot more than two or three items in the Print method's expression list. These items can be a mix of text and numbers, as long as each is separated by a comma or semicolon. You can even mix separators within the list.
One other item of note: The Print method typically starts a new line each time it is invoked. You can change this behavior by including a comma or semicolon after the last item in the expression list. This indicates to the next print statement that it should continue on the same line. Using a comma starts the next item in the next print zone, and using a semicolon starts the next item immediately after the preceding one.
CAUTION: Because the Print method does not automatically handle word wrapping, printing a lot of items or several large items can result in printing some information off the edge of the page. See the later sections "Using TextHeight and TextWidth" and "Using Word Wrapping in Your Printouts" to learn about preventing this.
Specifying only a list of information to be printed leaves much to be desired in controlling the placement and appearance of any reports you are creating. Fortunately, you can position text by embedding spaces and tabs, just like the earlier examples with the TextBox control. Two special functions that are used with the Print method are the Spc and Tab functions.
The Spc function places a specified number of spaces in the printout. This is used to create a specific amount of space between two items in the expression list. You use the Spc function by placing it in the expression list of the Print method as shown in the following line of code:
Printer.Print "First Field"; Spc(10); "Second Field"
When using the Spc function, you should always use a semicolon as the separator. Otherwise, the spaces created by the Spc function will not start immediately after the preceding item, but will start in the next print zone. This will most likely give you more space than you want.
`Not a good way to use the Spc Function Print "First Field", Spc(10), "Second Field"
The Spc function is most useful when you deal with information of a known length (such as five characters, ten characters, and so on) and with a fixed font. However, if you are trying to create columns in a report, the Tab function is usually the better choice. The Tab function causes subsequently printed characters to start at a specific location. You use the Tab function in a manner similar to the Spc function, but instead of specifying the number of spaces, you specify the character position where you want the printing to start. The following line of code causes the second item to be printed in column 30 of the printout:
Printer.Print "First Field"; Tab(30); "Second Field"
Figure 15.5 shows the effects of using the Spc and Tab functions to create columns in a report. Notice that the report using the Tab function produces more consistent results than the Spc function.
FIG. 15.5
The Spc function inserts a specified number of spaces, while the
Tab function moves to a specific position.
CAUTION: If the position specified by the Tab function is further to the left on the page than the end of the last printed item, the Tab function causes the printout to move to that character position on the next line on the page.
In addition to using the Spc and Tab functions to handle the spacing of your reports, there are other functions that are extremely useful in creating reports for your programs. The String function works like the Spc function, except that you can specify any character you want to fill the spaces. The Format function lets you apply special formatting to strings, numbers, and dates to make them more readable for your users.
Using the String Function You have probably seen the Table of Contents of a book where a series of dots (a dot leader) separates the title of a chapter from the page number where it starts. If you want to do this in your reports, use the String function. The String function requires two arguments--the character to use and the number of times to repeat the character. For example, the following line of code would place a series of 20 periods on the printout after the first data item:
Printer.Print "Chapter 1"; String(20, "."); "15"
In the String function, you can either specify the literal character to use or the ASCII code of the character. The following code has the same effect as the preceding line:
Printer.Print "Chapter 1"; String(20, 46); "15"
Figure 15.6 shows an example of dot leaders embedded by using the String function.
FIG. 15.6
Use the String function to embed characters in your printout.
Another use of the String function would be in printing checks, where you want to be sure that the amount line of the check is filled to avoid tampering. In this case, the typical character to use is the asterisk (*).
Using the Format Function There are several types of information that require special handling. Two, in particular, are numbers and dates. When you tell the Print method to print a number, it prints it using the least number of digits possible. There are two problems with this. First, users might be accustomed to seeing numbers in a particular format, such as two decimal places for currency numbers. Second, if all your numbers are not the same size, it makes it difficult to line them up in columns. Similar problems apply to printed dates. For example, you may want only two digits in the year or to print the full name of the month instead of an abbreviation. The Format function makes it easy for you to apply custom formatting to any text that you want to print. You can choose from some of the built-in formats or create your own by specifying format strings.
Formatting Numbers The most common use of the Format function is to place numbers in a particular format to make them easier for the users to read. To use the Format function, you specify the input value and the format as shown in the following line of code:
Printer.Print Format(crGrossSales, "Currency")
For working with numbers, there are several named formats that you can use. Table 15.1 shows the named formats for numbers that are available with the Format function. Figure 15.7 shows the various format types for a group of numbers. In all cases, you must enclose the name of the format in double quotes.
Named Format | Description |
General Number | Displays the umber with no special formatting. |
Currency | Displays the number with a thousands separator, and two digits to the right of the decimal. |
Fixed | Displays at least one digit to the left and two digits to the right of the decimal. |
Standard | Displays the number with the thousands separator, and at least one digit to the left and two digits to the right of the decimal. |
Percent | Multiplies the number by 100 and displays the number followed by the percent (%) sign. |
Scientific | Displays the number in standard scientific notation. |
Yes/No | Displays Yes for a non-zero value and No for zero. |
True/False | Displays True for a non-zero value and False for zero. |
On/Off | Displays On for a non-zero value and Off for zero. |
If the named formats in Visual Basic don't meet your needs, you can define your own formats. (See Table 15.2 for the codes needed to define formats.) You specify a format by creating a "template" string indicating where the digits of the number will be placed, if thousands and decimal separators will be used, and any special characters that you want printed. For example, the following line of code prints a number with four decimal places and a thousands separator:
Printer.Print Format(TotalDistance, "##,##0.0000")
FIG. 15.7
Numbers can be displayed in many ways with the Format function.
Symbol | Purpose | Meaning |
0 | Digit placeholder | Displays the digit or displays 0 if there is no digit in that location. |
# | Digit placeholder | Displays the digit or displays nothing if there is no digit in that location. This causes leading and trailing zeros to be omitted. |
. | Decimal Separator | Indicates where the decimal point will be displayed. |
, | Thousands Separator | Indicates where the separators will be displayed. |
% | Percentage Indicator | Indicates where a percent sign will be displayed. Also causes the number to be multiplied by 100. |
E-, E+, e-, e+ | Scientific Notation | Using E- or e- displays a minus sign next to negative exponents, but displays no sign for positive exponents. Using E+ or e+ displays a sign for any exponent. |
Formatting Dates Another form of data that is often a chore to print is dates. If you specify the Print method with a date, it is displayed in the default format for your system--typically something like 2/18/98. If you want to display the date in another manner (for example, February 18, 1998), you need to use the Format function. Table 15.3 lists some predefined date and time formats (see Figure 15.8). If they do not suit your needs, you can create a custom format. The codes for creating user-defined date and time formats are listed in Visual Basic's Help system.
TIP: To include the current date and/or time on your report, you can use the Now function:Form1.Print Format(Now,"mm/dd/yyyy")
Named Format | Description |
General Date | Shows the date and time if the expression contains both portions. Otherwise, displays either the date or the time. |
Long Date | Prints the day of the week, the day of the month, the month, and the year. |
Medium Date | Prints the day of the month, a three letter abbreviation for the month, and the year. |
Short Date | Prints the day, month, and year as 3/5/97. |
Long Time | Prints hours, minutes, and seconds along with the A.M./P.M. indication. |
Medium Time | Prints hours and minutes along with A.M. or P.M. |
Short Time | Prints hours and minutes in military time. |
FIG. 15.8
By Using named formats, you can enhance the appearance of date information.
TIP: User-defined formats can be useful for making decisions in your program. The expressionFormat(stMyDate,"w")
returns a number representing the day of the week. You could use the result of the expression to skip printing reports on the weekend, for example.
The Print method is fine for displaying text, but used by itself is not enough to make your reports visually pleasing. If you have used a Windows word processor, you are probably already aware of several ways to alter the appearance of printed text. For example, you can make report headings larger, bold-faced, or in a different font altogether. You may also wish to change the color of certain information to draw the reader's attention to it. In addition, you can add lines, boxes, and other graphical elements to separate different sections of the report.
All of these options are available in Visual Basic. When combined with the Print method they can turn your otherwise dull printouts into sharp-looking reports. Although there are custom reporting tools available, a careful programmer can create professional-looking output using the functions described in this section.
The first step in making reports more exciting is to use different font effects to highlight information. The Print method always uses the object's current font and font characteristics when it prints information to the printer or the screen. Therefore, to use a different font or font attribute, you must make the change to the Font object before you issue the Print method. For example, place the following code in a command button:
Private Sub Command1_Click() Form1.Font.Bold = True Form1.Print "This is one font style," Form1.Font.Bold = False Form1.Font.Size = 14 Form1.Print "and this is another." End Sub
Note how the Font properties act differently here than with controls such as labels or text boxes. When used with the Print method, Font properties act in a "toggle" mode. One way to think of this is that the Print method draws text on the form based on the current Font object settings, whatever they might be. A text box, on the other hand, applies any changes to the Font object to all of the text in its Text property.
The three main output objects--the printer, the form, and the picture box--all allow you to use the various attributes of the Font object, and the attributes are controlled the same way for each object.
We cover fonts in detail in Chapter 14, "Working with Text, Fonts, and Color," but the following list shows you the available font attributes that you can use to control the appearance of text in your printouts:
See "Controlling the Appearance of Your Text," Chapter 14
These properties are changed using assignment statements in your code. For forms and picture boxes, you can change the initial font settings using the Properties dialog box while you are in design mode. For the Printer, the initial font settings are determined by the Windows Print Manager.
As an example of using different font attributes in your program, consider a report that lists gross sales per salesperson for a company. As the program is printing out the columns of names and sales figures, you could use a bold font for the salespeople who made more than a specified amount in sales and use an italic font to highlight those who were below a specified minimum. This would make the information stand out and make the report more useful. The code in Listing 15.3 shows how this would work. The results of the printout are shown in Figure 15.9.
Dim I As Integer Dim GrossSales(1 To 10) As Currency Dim SalesPerson(1 To 10) As String 'Note: the code for filling arrays has been omitted picOutput.Font.Name = "Times New Roman" picOutput.Font.Size = 14 picOutput.Font.Bold = False picOutput.Font.Italic = False For I = 1 To 10 If GrossSales(I) > 150000 Then picOutput.Font.Bold = True If GrossSales(I) < 50000 Then picOutput.Font.Italic = True picOutput.Print SalesPerson(I); Tab(40); picOutput.Print Format(GrossSales(I), "$##0,000.00") picOutput.Font.Bold = False picOutput.Font.Italic = False Next I
Note that you are not limited to specifying a font or attribute for an entire line. You can change fonts in the middle of a line as well. To do this, use the Print method to print part of the line, followed by a semicolon. Then change the font attributes and use the Print method a second time to print the next part of the line. For example, you could modify Listing 15.3 to highlight only the number portion and not the salesperson's name, as in the following code lines:
For I = 1 To 10 picOutput.Print SalesPerson(I); Tab(40); If GrossSales(I) > 150000 Then picOutput.Font.Bold = True If GrossSales(I) < 50000 Then picOutput.Font.Italic = True PicOutput.Print Format(GrossSales(I), "$##0,000.00") picOutput.Font.Bold = False picOutput.Font.Italic = False Next I
FIG. 15.9
Font attributes are an effective way to make your data come alive.
Using fonts is one way to add emphasis to various parts of a report. Color is another way. If you are printing to a form or picture box, or if you are working with a color printer, you can change the color of the text that is being printed. To change the color of the text, you specify a value for the ForeColor property of the Printer or screen object to which you are printing. Values for the ForeColor property can be intrinsic constants like vbBlue, or numeric values. Unlike TextBox or Label controls, changing the ForeColor property affects only the text that is printed after the property change. Any text already printed remains in its original color.
If you are working with a color printer, you need to change one other property--the ColorMode property. This property determines whether the printer prints in color or monochrome. There are only two possible settings of the ColorMode property, both represented by Visual Basic constants--monochrome printing (vbPRCMMonochrome) and color (vbPRCMColor). A monochrome printer ignores the setting of the ColorMode property.
To illustrate the use of color in your printouts, let's look once again at the sales figures illustrated in Listing 15.3. This time, instead of using bold and italic font properties, we will change the text color to green for the top salespeople and red for the poor performers. This change is shown in Listing 15.4.
Dim I As Integer Dim CurColor As Long picOutput.Font.Name = "Times New Roman" picOutput.Font.Size = 14 CurColor = picOutput.ForeColor For I = 1 To 10 picOutput.Print SalesPerson(I); Tab(40); If GrossSales(I) > 150000 Then picOutput.ForeColor = vbGreen If GrossSales(I) < 50000 Then picOutput.ForeColor = vbRed picOutput.Print Format(GrossSales(I), "$##0,000.00") picOutput.ForeColor = CurColor Next I
We do not show a figure with the color highlights because it would not show up well in black and white. However, you can load the PrintDemo.Vbp project from the companion CD-ROM and see how the color highlighting would work.
When you are printing on a form or picture box, you can also set the BackColor property to provide a background for your text. However, you need to set the property before you start printing any text on the screen. If you try to set the BackColor property after you have started printing, you will wipe out all the text that has already been printed.
CAUTION: The BackColor property is not supported by the Printer object; you will get an error if you try to set it. In the chapter entitled "Working With Graphics," you learn how to use the PaintPicture method, which could be used to move a section of a picture box (including background color) to the printer.
See "Adding a Splash of Color," Chapter 14
This chapter's primary focus is printing text. However, you can also include graphics in your reports. These graphics can be simple lines that set off various areas of the report, charts that complement the text that is in the report, or even graphics images such as bitmaps or JPEG and GIF pictures.
There are several graphics methods to draw on an object. For example, the following statement would draw a diagonal red line on your form:
frmTest.Line (0,0)-(200,200),vbred
The following are the three main methods used in printing graphics on a form or the printer:
NOTE: These drawing functions are discussed in detail later in the book. There is a section about each of them in "Doing Graphics," found on the CD-ROM accompanying this book.
So far, we have only looked at printing information in the print zones established by the Print method itself. For many situations, you will want even more control over the placement of text and graphical objects on the screen and the printed page.
Naturally, there are properties that allow you to set the absolute position of a piece of information anywhere in your print area. Using these properties allows you great flexibility in the layout of your reports. However, with the added flexibility comes added work. You have to determine the size of the object you are printing on and the size of the elements you want to print. Then you need to make sure all the pieces fit properly on the page or screen. If you have ever arranged furniture in a room, you have some idea of the process.
Visual Basic has several functions that help you determine the size of your space and the various pieces with which you are working. Printable objects also have properties to help you specify exact placement text.
In most instances, you probably think of the printed page as a sheet of 8.5 x 11 inch paper. However, Visual Basic doesn't typically work with dimensions in terms of inches. Instead, Visual Basic works with units of measure called twips. (Recall from Chapter 2 that there are 1440 twips in an inch.) This makes measurement of spacing a little more difficult, but much more accurate. Also, when you are determining the available space on a printed page, you must consider whether the printer is working in portrait or landscape mode, and whether the paper is some size other than the standard 8.5 x 11. (For example, many legal papers are 8.5 x 14 inches.)
See "Accessing Functions with the Toolbars," Chapter 2
If you are working with the Printer object, the dimensions of the printable space are controlled primarily by the Windows Print Manager and the printer itself. (We look at how to make changes to the printer settings in the section "Controlling the Printer" later in this chapter.) For forms and picture boxes, the printable area is controlled by the initial design of the object and any resizing that has been done by the user. Because the user can resize the form (and in some cases, other objects), you cannot assume that the initial dimensions that you set will be the ones available when your printing process starts.
The best way to determine the available space in an object is to use the ScaleHeight and ScaleWidth properties of the object. These properties determine the interior dimensions of the object to which you will be printing. These properties are illustrated for a form and picture box in Figure 15.10. (Also see the "What Is the Difference Between ScaleHeight and Height?" sidebar.)
FIG. 15.10
You can determine the interior dimensions of an object with its ScaleHeight
and ScaleWidth properties.
What Is the Difference Between ScaleHeight and Height?
You might be wondering why we just don't use the Height and Width properties of the object to determine its size. The reason is that the Height and Width properties specify the external dimensions of an object. For example, on a form, the Height property would include the size of the title bar, the borders on the form, and any menu bar that you might place on the form. For some forms, the Height property can be as much as 690 twips larger than the ScaleHeight property, or almost half an inch larger. You can see how this could cause problems when determining the printable area of a form. The relation of the Width and ScaleWidth properties is the same. Width specifies the external dimensions of the object while ScaleWidth specifies the internal dimensions.
To use the ScaleHeight and ScaleWidth properties in your program, you need to retrieve their values. The easiest way to do this is to store the values of the properties in a pair of variables just before your report generation routine. This is shown in the following two lines of code:
inPicWid = picOutput.ScaleWidth inPicHgt = picOutput.ScaleHeight
After you have established the dimensions of the object, you can use them to establish relative positions on the object. For example, the following code sample starts printing some text in the middle of the object:
picOutput.CurrentX = inPicWid *.5 picOutput.CurrentY = inPicHgt *.5 picOutput.Print "Hello!"
Note the use of the CurrentX and CurrentY properties, used to set coordinates on the picture box before printing.
Now that you can determine the size of an object's printable area, you need to determine the size of the text you are placing on that object. The Print method is very simple-minded. It does not check to see whether the text is wider than the area where it is to be printed. Therefore, if the text is too wide, it simply disappears off the right edge of the print area, as shown in Figure 15.11.
See "Using Word Wrapping in Your Printouts," Chapter 15
FIG. 15.11
Word wrapping would be useful here.
Each of the objects that support the Print method also has two other methods that allow you to determine the size of the text to be printed. These methods are the TextHeight and TextWidth methods. As you can probably guess, the TextHeight method tells you the vertical dimensions (in twips) of a piece of text, and the TextWidth method tells you how much of an area the text will cover horizontally. The following lines of code demonstrate the use of the two methods:
Dim sgHeight As Single Dim sgWidth As Single Dim stUserName As String stUserName = "STEVE BAKER" sgHeight = Printer.TextHeight(stUsername) sgWidth = Printer.TextWidth(stUsername)
When using the TextHeight and TextWidth methods, you must supply a string in the form of a literal string, a string variable, or a string function. If you try to use a number or numeric variable, you get an error. Therefore, if you need to print a number, use the Str, CStr, or Format functions to convert the number to a string. You should also remember that literal strings must be enclosed within quotation marks.
See "Working with Strings and Numbers," Chapter 14
When determining the size of a piece of text, the TextHeight and TextWidth methods take into account the font used by the target of the output, as well as the font attributes such as size, bold, and italic. One use of the value returned is to adjust the font size to be sure that a piece of text fits in a specified area or to make sure the maximum possible font size is used. Listing 15.5 shows how you would check the size of the text and then reduce the font if necessary to make it fit in the available space. The results are shown in Figure 15.12.
Private Sub CmdSizetext_Click() Const MINIMUM_SIZE = 8 Dim stInput As String Dim inWidth As Integer Dim inHeight As Integer Dim inFontSize As Integer Dim blTooBig As Boolean picOutput.Cls stInput = InputBox$("Enter some text") If Len(stInput) = 0 Then Exit Sub inFontSize = Val(InputBox$("Enter initial font size", , "12")) lblInitial = "Initial Size: " & inFontSize inWidth = picOutput.ScaleWidth inHeight = picOutput.ScaleHeight picOutput.Font.Size = inFontSize blTooBig = True Do While blTooBig And inFontSize > MINIMUM_SIZE If picOutput.TextWidth(stInput) < inWidth And_ picOutput.TextHeight(stInput) < inHeight Then blTooBig = False Else inFontSize = inFontSize - 1 picOutput.Font.Size = inFontSize End If Loop picOutput.Print stInput lblActual = "Actual size: " & inFontSize End Sub
FIG. 15.12
The text had to be resized because it would not have fit at the requested
font size.
In our examples so far, we have controlled the position of printed text by adding spaces or tabs. However, there are two properties that can set the position of a piece of text within the print area. These properties are the CurrentX and CurrentY properties. Setting these properties is like positioning your drawing pencil on the form. For text, the CurrentX and CurrentY properties define the upper-left corner of the print position. When the Print method is issued, the text is printed down and to the right of this position. In other words, if the text you are about to print had a box around it, the coordinates (CurrentX, CurrentY) would represent the upper-left corner of the box, as measured from the upper-left corner of the screen.
See "Controlling Form Size," Chapter 4
The primary use of these two properties is to set the current position before printing the next piece of text in your report. If you do not modify the values of these properties, each time the Print method is invoked, the printout will start at the far left of the next available line (unless the previous Print method ended with a semicolon or comma). You can use the CurrentX and CurrentY properties to create indented areas on your report, or to handle centering and right-justifying the text. To see how the CurrentX and CurrentY properties are used, take a look at Listing 15.6 and its resulting output in Figure 15.13.
Private Sub cmd_Center_Click() Dim stTest As String Dim inWidth As Integer Dim inHeight As Integer stTest = "This text is centered" With picOutput inWidth = .ScaleWidth inHeight = .ScaleHeight .Font.Name = "Times New Roman" .Font.Size = 14 .Font.Bold = True .CurrentX = (inWidth - .TextWidth(stTest)) / 2 .CurrentY = (inHeight - .TextHeight(stTest)) / 2 End With picOutput.Print stTest End Sub
FIG. 15.13
Center text by using CurrentX and CurrentY.
You look at more ways to handle text positioning later in the chapter in "Exploring Printer Functions You Can Create."
In our discussions so far, we have assumed that the printer was set up and ready to print, and that it would just print whatever we sent to it. For the most part, this is correct. However, there are a number of properties and methods that are used to set up the printer and then control it while your report is being created. Some of the things you can do include the following:
This section shows you how to set up the printer and how to control it.
Although the default settings of the printer are usually sufficient for most jobs, you do have quite a bit of control over the way the printer is set up. As with most everything else in Visual Basic, you control the printer by setting properties. These properties are part of the Printer object and can be set with simple assignment statements. Table 15.4 summarizes these properties and the effects that they have on your printouts. Keep in mind that some of the properties listed in the table (such as Duplex) do not apply to every printer.
Property Name | Description |
Copies | Tells the printer how many copies of each page to make. |
DeviceName | Returns the name of the printer--for example, HP DeskJet 660C. |
DriverName | Returns the name of the printer driver--for example, HPFDJC04. |
Duplex | Determines whether the printout will be on one side of a page or both sides. If the printout is on both sides of the page, this property also determines whether the second side assumes a horizontal or vertical flip of the page. |
FontTransparent | Determines whether background text and graphics will show through text printed on the page. |
Orientation | Determines whether the page is in portrait or landscape mode. |
Page | Tells your program the current page number. |
PaperBin | Determines which paper bin of a printer will be used. This property is also used to tell the printer to wait for manual insertion of each page to be printed. This is very useful for handling pre-printed forms. |
PaperSize | Sets the size of paper to be used for the printout. This property can be set to one of a number of default paper sizes. The property can also be set to allow a user-defined paper size, in which case you must define the Height and Width properties of the page. |
Port | Returns the name of the printer port. Can be a local or mapped port like LPT1: or a network path like \\ myserver\myprinter. |
PrintQuality | Sets the printer resolution to draft, low, medium, or high quality. |
Zoom | Sets a percentage by which the size of the printout is scaled up or down. Setting the Zoom property to 50 would cause the report to be printed half-size. |
You might be wondering how you can give the user choices of how to control the printer. Fortunately, this is a relatively easy task. Most of the properties of the printer can be set using the Printer Setup dialog box of the CommonDialog control. The properties of the CommonDialog control's Print dialog box match the properties of the Printer object. The common dialog box provides an easy way for the user to select various printer properties. The Print dialog box is shown in Figure 15.14.
See "Using Built-In Dialog Boxes," Chapter 6
FIG. 15.14
The Print dialog box lets your users select and set up a printer, as well
as select options such as number of copies.
As you are sending information to the printer, at some point you will print more information than will fit on a single sheet of paper. For most printers, this is not a problem as they will automatically print multiple pages as needed. However, if you are including header information on your reports, such as the report name, date, or page number, this header information will not be automatically printed at the top of the next page. This is something that you have to control from your program.
Unfortunately, the Printer object does not have any events associated with it. Therefore, it cannot tell you when you have reached the end of a page or when a new page has started. The only way for you to determine this is by keeping up with the value of the CurrentY property of the printer. When the printer moves to a new page, the values of the CurrentX and CurrentY properties are reset to 0. However, you want to be able to determine when a page break is about to occur and handle the transition to the new page yourself.
To actually force the printer to start a new page is very easy. You simply issue the NewPage method as shown in the following line of code:
Printer.NewPage
The trick in creating proper page breaks in your report is to know when the current page is full. This is accomplished using a combination of the CurrentY and ScaleHeight properties and the TextHeight method of the printer. Take a look at Listing 15.7 to see how this is accomplished.
If Printer.CurrentY + Printer.TextHeight(stOutput) > _ Printer.ScaleHeight Then Printer.NewPage PrintHeader `(PrintHeader is programmer-defined) End If Printer.Print stOutput
This code sums up the value of the CurrentY property and the height of the next line to be printed. If the sum of these numbers exceeds the ScaleHeight of the printer, the code forces a page break and then calls the PrintHeader to print the headers at the top of the next page. This code could easily be modified to handle printing a footer at the bottom of the current page before moving to the next page. This is shown in Listing 15.8.
inPageHt = Printer.ScaleHeight - inFooterHt If Printer.CurrentY + Printer.TextHeight(stOutput) > inPageHt Then PrintFooter Printer.NewPage PrintHeader End If Printer.Print stOutput
Of course, you are not limited to starting new pages only when the current page is full. You might also want to start a new page when a condition of the report changes. For example, if you are printing employee summary information, you might want to start a new page for each employee. Again, you start a new page by issuing the NewPage method.
As you are sending information to the printer, what you are really doing is sending information to the buffer of the Windows Print Manager. The information is not actually sent to the printer until you tell Windows to do so. Your printout is automatically sent to the printer when you shut down your application, but this does not provide sufficient control to be useful. In fact, while the Print Manager is waiting to print your report, it might be holding up printouts from other programs.
To tell Windows to send the report to the printer, you use the printer's EndDoc method. This method has no additional arguments, and simply tells Windows that your printout is finished. You run the EndDoc method by specifying the Printer object and the method name as shown in the following line:
Printer.EndDoc
Finally, you will from time to time need to abort a printout before it is finished or prevent it from going to the printer at all. This need might arise for several reasons, including user decisions or runtime errors in the program. In any case, the method to use for aborting a printout is the KillDoc method, which is shown in the following code line:
Printer.KillDoc
One way to implement a cancel button for a printing operation is to use a form-level Boolean variable. Create a Cancel button whose Click event procedure sets the variable to True:
Private Sub cmdCancel_Click() blCancel = True End Sub
While printing, check the variable with an If statement to see if you need to use the Killdoc method.
Dim inCounter As Integer blCancel = False For inCounter = 1 To 1000 frmStatus.Caption = "Printing Line " & inCounter Printer.Print "This is line number " & inCounter DoEvents If blCancel = True Then Printer.KillDoc Exit For End If Next inCounter If blCancel = False Then Printer.EndDoc
In the preceding example, the DoEvents statement is used to temporarily give control back to the Windows event handler. The reason we need to do this is to make sure that the system is handling other events, specifically cmdCancel's Click event.
Typically, when this method is invoked, the Print Manager is handling the printout in the background, and the method kills the entire printout. However, there are several print-spooling options available, so using the KillDoc method does not guarantee that no information will be sent to the printer. Even if some pages have already been printed, however, the KillDoc method can still terminate the remainder of the printout, and the printer driver will reset the printer.
While the bulk of this chapter has been aimed at creating reports on the printer, you have probably gathered that most of the methods and techniques demonstrated will also work for printing information to a form or a picture box. In fact, all the figures in the chapter have used a form or picture box to represent the printer, because it is easier to show you screen shots than to create a printer page and scan it back in for a figure.
Printing to a form is basically the same as printing to the printer. You can print text, create graphics, control the fonts of the printout, handle text centering, and anything else that you can do with the printer. The only things that we have covered for the printer that are not applicable to forms and picture boxes are the printer setup properties and the NewPage, EndDoc, and KillDoc methods covered in the previous section, "Controlling the Printer."
The key difference between printing to the printer and printing to a form is that a form has a limited amount of space and cannot create multiple pages. Although this does not prevent you from creating long reports on the screen, it does force you to use different techniques to handle more than a single page of information.
If you will be printing multi-page reports to a form or a picture box, you need to do two things. First, you need functions to allow the user to navigate within the pages of data you are printing. Second, you need to clear the object before you print (display) the next page.
For the sake of this example, our data will be a string array filled by the following code (this probably should occur during the form Load event):
Const NUM_RECORDS = 100 Dim stData(1 To NUM_RECORDS) As String Dim inCount As Integer For inCount = 1 To NUM_RECORDS stData(inCount) = "This is line " & inCount & " of a 100 line report." Next inCount
Before starting the printout, you need to establish how much information will fit on a page (the variables should have been declared in the General Declarations section of the form):
`Calculate Line height of a line of text inLineHeight = picOutput.TextHeight("X") `Leave 2 lines for a footer inPageHeight = picOutput.ScaleHeight - inLineHeight * 2 'Determine lines per page inLinesPerPage = inPageHeight / inLineHeight
With this information, you can write a procedure to print a given page:
Sub DisplayPage(inPage As Integer) Dim inStartRecord As Integer Dim inLastRecord As Integer Dim inCounter As Integer If inPage <= 1 Then inStartRecord = 1 Else inStartRecord = 1 + (inLinesPerPage * inPage) - inLinesPerPage End If If inStartRecord > NUM_RECORDS Then inStartRecord = NUM_RECORDS inLastRecord = inLinesPerPage * inPage If inLastRecord > NUM_RECORDS Then inLastRecord = NUM_RECORDS picOutput.Cls inCounter = inStartRecord While inCounter <= inLastRecord picOutput.Print stData(inCounter) inCounter = inCounter + 1 Wend picOutput.CurrentY = picOutput.ScaleHeight - inLineHeight * 2 picOutput.Print "Footer Line 1" picOutput.Print "Footer Line 2" End Sub
The output of the sample code is seen in Figure 15.15. It is left as an exercise to the reader to write code for the Previous and Next buttons, which simply change a counter variable and call the DisplayPage procedure.
The earlier sample also showed you the form's Cls method (see the picOutput.Cls line), which is used to clear the form before printing the next page of information. It clears the form (or picture box) and resets the CurrentX and CurrentY properties to 0. This is the form's equivalent of the NewPage method.
FIG. 15.15
This sample program uses the dimensions of the picture box to determine where
a page begins and ends.
In addition to the reporting techniques we've discussed, you can also print the entire viewable area of the form to a printer. The viewable area is all parts of the form displayed on the screen, excluding the border, the title bar, and the menu. Printing the entire form is a very simple way to generate a report from whatever is on the form. This is accomplished with the form's PrintForm method. To invoke this method, you simply specify the form to be printed as shown in the following line of code:
frmPrintPage.PrintForm
CAUTION: For information printed to the form to show up on the printed page, the AutoRedraw property of the form must be set to True.
If you omit the name of the form, the current form is assumed. Figure 15.16 shows how a form would appear on the screen and how the printed form would look.
CAUTION: On rare occasions, a video driver conflict will not allow the PrintForm method to work. On one occasion we had the CEO's laptop disassembled to the circuit-board level before figuring this out. Based upon this personal experience, I would suggest that you should use this method of printing information sparingly.
At this point, you have seen most of the properties and methods that are used to create printouts on the screen and the printer. This section shows you how to use those methods to create procedures that handle a number of text effects for you. The procedures presented in this section are designed to be as generic as possible, to give them the widest possible range of usefulness. For example, while it would be fairly easy to create a routine to center a piece of text horizontally on a printed page, the routine presented here allows you to center the text within any region on either a printed page or screen object (form or picture box). This allows you to use the procedures almost anywhere in your code.
FIG. 15.16
The form on the left shows what you see on-screen, and the one on the right
shows which parts of a form are omitted by the PrintForm method.
One of the most commonly used techniques is to align the text on the page. If you use word processors, you are probably familiar with the concept of text justification. The three main types of justification are left-justified, right-justified, and centered. These all refer to the horizontal position of the text within the line. In addition, we will look at aligning text vertically with the top or bottom of the page and at centering the text vertically in the page.
Moving to the Left Left-justifying text is the simplest way to align text. If left alone, the Print method will start at the left edge of the output object and print from left to right. The routine shown in Listing 15.9 shows the function for left-justifying text and the routine that calls the function. The call to the procedure specifies the output object, the starting CurrentX and CurrentY properties for the printout, the size of the print region, and the text to be printed.
Dim txStr As String Dim objWid As Integer Dim objHgt As Integer txStr = Text1.Text objWid = Picture1.ScaleWidth objHgt = Picture1.ScaleHeight Picture1.Cls LeftJustify Picture1, 5, 5, objWid, objHgt, txStr Private Sub LeftJustify(objOut As Object, LMarg, TMarg, RgWid, RgHgt _ As Integer, InptStr As String) objOut.CurrentX = LMarg objOut.CurrentY = TMarg objOut.Print InptStr End Sub
This same routine could be used to align text at the top of the specified region.
Moving to the Right Right-justifying text is a little trickier than handling left-justified text. To align text with the right edge of a region, you must know the size of the text and the size of the region. As with the procedure for left-justifying text, the size and position of the region are passed to the procedure to right-justify the text. Therefore, the key task involved is to determine the size of the text to be printed. As you know, this can be accomplished with the TextWidth method. Listing 15.10 shows how the right-justification is accomplished. The results of the procedure are displayed in Figure 15.17.
Private Sub RightJustify(objOut As Object, LMarg, TMarg, RgWid, RgHgt _ As Integer, InptStr As String) Dim txMarg As Integer txMarg = RgWid - objOut.TextWidth(InptStr) - 10 If txMarg < 0 Then txMarg = 0 objOut.CurrentX = LMarg + txMarg objOut.CurrentY = TMarg objOut.Print InptStr End Sub
FIG. 15.17
A sample program demonstrates a technique for right-justification of text.
Text can be aligned along the bottom of the object as well. This is handled by the routine in Listing 15.11, which uses the TextHeight method to determine the position of the text.
Private Sub BottomAlign(objOut As Object, LMarg, TMarg, RgWid, RgHgt _ As Integer, InptStr As String) Dim txMarg As Integer txMarg = RgHgt - objOut.TextHeight(InptStr) - 10 If txMarg < 0 Then txMarg = 0 objOut.CurrentX = LMarg objOut.CurrentY = TMarg + txMarg objOut.Print InptStr End Sub
Staying in the Middle The final alignment function is centering. Centering is accomplished by determining the blank space available on the line and placing an equal amount of the space on both sides of the text to be printed. This is again accomplished using the CurrentX property and the TextWidth method. Listing 15.12 shows the procedure for centering text horizontally on the page. A similar method can be used to center the text vertically on the page, or to center the text in both directions. Figure 15.18 shows the results of the centering operation.
FIG. 15.18
Center text on the page either horizontally, vertically, or both.
Only horizontal centering is shown in the listing, but all three routines are included in the sample project TextFunc.Vbp. You can load this project from the accompanying CD-ROM.
Private Sub CenterText(objOut As Object, LMarg, TMarg, RgWid, RgHgt _ As Integer, InptStr As String) Dim txMarg As Integer txMarg = (RgWid - objOut.TextWidth(InptStr)) / 2 If txMarg < 0 Then txMarg = 0 objOut.CurrentX = LMarg + txMarg objOut.CurrentY = TMarg objOut.Print InptStr End Sub
One of the most useful functions that you can create is word wrapping. Word wrapping breaks up a line of text (usually at a space) and places additional text on the following lines of the printout. This prevents the information in the report from being printed off the edge of the page. To handle its task, the word wrapping function performs the following steps:
2. Adds the word to a variable containing the line to be printed
3. Determines whether the text in the variable will fit on the current line
4. Repeats Steps 1 through 3 until the maximum number of words are included for the line
5. Prints the line of text
6. Removes the printed text from the input string
7. Repeats these steps until the entire input string has been printed
The procedure to handle word wrapping is shown in Listing 15.13. Figure 15.19 shows the input text in the text box and the word wrapped text in the picture box
Private Sub WordWrap(objOut As Object, LMarg, TMarg, RgWid, RgHgt _ As Integer, InptStr As String) Dim StrtPos As Integer Dim EndPos As Integer Dim TxtLen As Integer Dim PrntLn As String Dim PrntIn As String PrntIn = InptStr objOut.CurrentY = TMarg Do EndPos = 0 TxtLen = 0 PrntLn = "" Do StrtPos = EndPos + 1 EndPos = InStr(StrtPos, PrntIn, " ") PrntLn = Left(PrntIn, EndPos) TxtLen = objOut.TextWidth(PrntLn) Loop Until TxtLen > RgWid - 10 Or EndPos = 0 If EndPos = 0 Then PrntLn = PrntIn PrntIn = "" Else PrntLn = Left(PrntIn, StrtPos - 1) PrntIn = LTrim(Mid(PrntIn, StrtPos)) End If objOut.CurrentX = LMarg objOut.Print PrntLn Loop While Len(PrntIn) > 0 End Sub
FIG. 15.19
Word wrapping makes your report look more professional.
As with the other procedures, the WordWrap procedure allows you to specify the starting position and print region size for the output. This gives you much greater flexibility in what you can accomplish with the procedure. By varying the starting position and region size, you can handle left, right, and double indents for your paragraphs. The results of these techniques are shown in Figures 15.20 through 15.22. The actual code is contained in the sample project.
FIG. 15.20
Left Indent is handled by changing the starting position of the word wrapping.
FIG. 15.21
Right Indent is handled by changing the print region width for the word wrapping.
FIG. 15.22
Double Indent is handled by changing both the starting position and the region
width.
The final technique we want to show you is how to create a table. The table uses several of the functions that we just created. Specifically, it uses the CenterText function to center the table headers within each column. It also uses the WordWrap function to handle word wrapping within a cell. Finally, the table uses the graphics methods to draw the lines of the table. The example presented in Listing 15.14 shows how you would print a table of book titles, ISBN numbers, and comments from the Biblio database. The table is shown in Figure 15.23.
Dim txStr As String Dim LineY As Integer Dim I As Integer Dim objWid As Integer Dim objHgt As Integer Dim ColLft(1 To 3) As Integer, ColWid(1 To 3) As_ Integer Printer.Font.Name = "Times New Roman" Printer.Font.Size = 14 Printer.Orientation = vbPRORLandscape objWid = Printer.ScaleWidth - 20 objHgt = Printer.ScaleHeight - 10 ColLft(1) = 10 ColWid(1) = objWid / 3 ColLft(2) = ColLft(1) + ColWid(1) ColWid(2) = objWid / 3 ColLft(3) = ColLft(2) + ColWid(2) ColWid(3) = objWid - ColWid(1) - ColWid(2) LineY = 10 Printer.Line (ColLft(1), LineY)-(ColLft(1) + objWid, LineY) CenterText Printer, ColLft(1), LineY + 5, ColWid(1), objHgt, "Title" CenterText Printer, ColLft(2), LineY + 5, ColWid(2), objHgt, "ISBN" CenterText Printer, ColLft(3), LineY + 5, ColWid(3), objHgt, "Comments" Printer.Font.Size = 10 For I = 1 To 2 LineY = Printer.CurrentY + 10 Printer.Line (ColLft(1), LineY)-(ColLft(1) + objWid, LineY) txStr = Data1.Recordset!Title & "" LeftJustify Printer, ColLft(1), LineY + 5, ColWid(1), objHgt, txStr t xStr = Data1.Recordset!ISBN & "" LeftJustify Printer, ColLft(2), LineY + 5, ColWid(2), objHgt, txStr txStr = Data1.Recordset!Comments & "" WordWrap Printer, ColLft(3), LineY + 5, ColWid(3), objHgt, txStr Data1.Recordset.MoveNext ext I LineY = Printer.CurrentY + 10 Printer.Line (ColLft(1), LineY)-(ColLft(1) + objWid, LineY) Printer.Line (ColLft(1), 10)-(ColLft(1), LineY) Printer.Line (ColLft(2), 10)-(ColLft(2), LineY) Printer.Line (ColLft(3), 10)-(ColLft(3), LineY) Printer.Line (ColLft(1) + objWid, 10)-(ColLft(1) + objWid, LineY) Printer.EndDoc
FIG. 15.23
You can create tables using text functions.
In this chapter, you have seen how you can display reports on the screen and print them on paper. You also saw that while the Print method is fairly simple, you can use code to create a number of text effects in your printouts. You even saw how graphics could be used to enhance your reports. To learn more about some of the topics covered in this chapter, refer to the following:
© Copyright, Macmillan Computer Publishing. All rights reserved.