Company logo

FOXSTUFF

Advice, tips, techniques and downloads for Visual Foxpro developers.

Home | Contact

Printing and reporting Q & A

A few things you might not have known about the printing and reporting features in Visual FoxPro

I know that I can use REPORT FORM ... PROMPT to let users select a particular printer for a report. But is there any way to make the selected printer the default for the rest of the session?

The easiest way to do this is with the following command: 

SET PRINTER TO NAME GETPRINTER() 

This will bring up the standard Printer dialog. The user will select a printer, which will then become the default. If the user cancels the dialog without making a selection, the default printer will remain unchanged.

If I change the default printer as described above, will it affect any other Windows applications that the user might be running?

No. SET TO PRINTER TO NAME affects the Visual FoxPro default printer, not the Windows default printer. If you want to make the Visual FoxPro default printer the same as the Windows default printer, do this: 

SET PRINTER TO DEFAULT

What is the difference between GETPRINTER() and SYS(1037)? They both appear to bring up a printer dialog.

There's quite a big difference. GETPRINTER() invokes a simple Printer dialog, in which the user can select a printer and nothing else. SYS(1037) opens the full Page Setup dialog. Here, the user can select the printer, the paper size, the paper source and the orientation.

There's another important difference. GETPRINTER() simply returns the name of the printer which the user selects (or an empty string if the user cancels) - it doesn't actually change the selected printer. SYS(1037) doesn't return anything, but it does bring about the changes that the user makes. For example, if the user selects a particular laser printer and sets the paper source to manual feed, then those choices will affect all subsequent reports (unless overridden in the report designer or by using the PROMPT clause).

In one of my reports, I want to let users choose between the upper and lower paper tray. But I don't want them to be able to change the paper size or orientation. Is that possible?

In VFP 8.0 and below, the only option is to modify the report file (the FRX file) at run time. You'll find details of how do this in a separate Foxstuff article, Controlling report settings at run time.

VFP 9.0 gives you more control over the printer environment. In general, any settings that you make from the Page Setup dialogue will be saved with the report (provided you select the Printer Environment option from the Report menu before you save the report). The user will not be able to override those settings, even if you display the SYS(1037) dialogue before you run the report.

To reach the Page Setup dialogue in VFP 9.0's report designer, select Page Setup from the File menu, then press the Page Setup button on the first page of the resulting dialogue. 

OK, I've followed the advice in the anser to the previous question. But it doesn't answer my next query. How can I select the upper tray for the first page of the report and the lower tray for the remaining pages?

Your best bet is to create two versions of the report. Use the Page Setup dialog within the report designer to establish the paper source: upper tray in one version, lower tray in the other. Then issue REPORT FORM twice, using the RANGE clause to select the page numbers: 

REPORT FORM MyReport_Ver1 RANGE 1,1 NOCONSOLE 
REPORT FORM MyReport_Ver2 RANGE 2 NOCONSOLE 

This will print page 1 of MyReport_Ver1 and page 2 to the last page of MyReport_Ver2.

I want to display a report in the Preview window, but still open the Print dialog when the user clicks on the Printer button in the toolbar. Is this possible?

Yes. Here's how:

REPORT FORM MyReport TO PRINTER PROMPT PREVIEW

How can I programmatically maximise the Preview window?

Like this: 

KEYBOARD "{ctrl+f10}" 
REPORT FORM MyReport PREVIEW

This will insert Ctrl-F10 into the keyboard buffer just before the Preview window opens. This in turn maximises the window.

I have an application which runs as a top-level form, with the main VFP window invisible. Unfortunately, this also means that my report's Preview windows are invisible. Is there a fix?

In VFP 5.0, the only solution is to restore the VFP window immediately before the preview and hide it again afterwards. Your code will look something like this: 

_SCREEN.Visible = .T. 
REPORT FORM MyReport PREVIEW 
_SCREEN.Visible = .F.

In VFP 6.0 and above, you can display the report preview inside a normal form. This can itself be a top-level form, so the main VFP window does not have to be visible. To achieve this, create a form called (say) frmPreview. Set its ShowWindow property to 2 (As Top-Level Form). Then launch the form, for example, with DO FORM. Finally, run your preview like this: 

REPORT FORM MyReport PREVIEW IN WINDOW frmPreview

I am using the REPORT FORM command with a FOR clause to print a subset of a table. Most of the time, this works fine. But when the user previews the report and then presses the Print button in the Preview toolbar, the entire table is printed.

This is a bug in VFP 5.0. Specifically, the Print button does not respect the FOR clause in a command like this one:

REPORT FORM customers PREVIEW FOR country = "UK" 

The solution is to use a filter instead: 

SET FILTER TO country = "UK" 
REPORT FORM customers PREVIEW 
SET FILTER TO 

The bug was fixed in VFP 5.0a.

I would like to use the report designer to generate invoices. Some of these will extend over multiple pages. How can I arrange for the invoice total always to appear at the very bottom of the last page? If I place the total in the summary band, it gets printed just below the last line of detail. If I place it in the page footer band, it is printed on every page.

Place the total in the page footer band, below any other fields or labels that are already there. In the report expression dialog, click on the Print When button, then type this expression in the Print Only When Expression Is True box:

RECNO()=RECCOUNT() 

This will cause the totals to be printed only after the last record in the file has been processed. (This assumes that you are using a single table or cursor as the input to the report, and that it is not indexed.)

What would happen if a user runs my application on a computer that has no printer driver installed?

One or more run-time errors will be generated whenever the application tries to perform a printer-related task. The errors will typically be "Printer not ready", "Error loading printer driver", or both. They will occur when the application tries to print a report, and also when you execute SET PRINTER, GETPRINTER() and several similar commands and functions. You can, however, successfully preview a report.

To prevent these run-time errors, test the value returned from APRINTERS() before performing a printer-related task. If this value is zero, it means that no printer drivers are installed.

In view of the previous answer, is it possible to disable or remove the Print button in the Report Preview toolbar?

To remove a button from any of VFP's built-in toolbars, open the toolbar in the development environment, hold down the Alt key, and drag the button off the toolbar. This setting is saved in the resource files (FOXUSER.DBF and FOXUSER.FPT), so you would have to copy these files to the user's system in order to propagate the setting.

I would like to include page numbers in my report, in the form, "page x of y", where y is the total page count. Is this possible?

In VFP 8.0 and above, you simply use the _pagetotal system variable to determine the total page count, as in the following example:

"Page " + TRANSFORM(_pageno) + " of " + TRANSFORM(_pagetotal)

Keep in mind that the use of _pagetotal forces VFP to make two passes of the report. On the first pass, nothing is printed; VFP simply calculates the page count. The second pass does the actual printing. If performance is an issue, you should consider foregoing the use of "page x of y".

In VFP 7.0 and earlier, printing "page x of y" is more complicated. The only way to do it is to run the two passes explicitly, calculating the page count in your code: 

nTotalPages = 0 
REPORT FORM MyReport NOCONSOLE 
nTotalPages = _pageno 
REPORT FROM MyReport TO PRINT NOCONSOLE

The first pass won't actually print anything (because there is no TO PRINT clause), but it will place the total page count in _pageno. To print "page x of y", the report should contain an expression such as the following: 

"Page " + TRANSFORM(_pageno) + " of " + TRANSFORM(nTotalPages)

I am using the Microsoft Web Browser control to display HTML pages. How can I print these pages?

The Web Browser control does not have a Print method. You can, however, use its ExecWB method to print the current document. In general, this method will execute any command which is normally available in the browser's user interface.

Your code will look something like this: 

THISFORM.WebBrowser.ExecWB(6,1) 

The first parameter, 6, tells the method that you want to print. With the second parameter set to 1, the browser will display a Print dialog (like the one in Internet Explorer). To inhibit this dialog, set the second parameter to 2.

Mike Lewis Consultants Ltd. June 2000. Revised January 2006.

More Visual FoxPro articles | Crystal Reports articles | Recommended books | Visual FoxPro consultancy | Contact us

FoxStuff is maintained by Mike Lewis Consultants Ltd. as a service to the VFP community. Feel free to download and use any code or components, and to pass around copies of the articles (but please do not remove our copyright notices or disclaimers).

The information given on this site has been carefully checked and is believed to be correct, but no legal liability can be accepted for its use. Do not use code, components or techniques unless you are satisfied that they will work correctly in your applications.

© Copyright Mike Lewis Consultants Ltd.