Sign in Join
Wiki copytemporary

GridPrinter

About

TGridPrinter is a component to simplify printing of string grids or other descendants of TCustomGrid. It is bundled together with a ready-made print preview dialog, TGridPrintPreviewDialog, as well as standard actions to trigger printing or to show the preview dialog without writing a single line of code.

Author: Werner Pamler.

License: Modified LGPL-2 (with linking exception, like Lazarus LCL).

Download and Installation

Release version

The package is made available for installation by the Online-Package-Manager. Additionally, a zip file with the most recent release version can be found at Lazarus CCR at SourceForge; unzip the file into any folder; load the file gridprinterpkg.lpk into Lazarus and click Use > Install.

Development version

The current development version is hosted at Lazarus CCR. Use SVN to check it out, or download the zipped snapshot from this page. Install by loading the gridprinterpkg.lpk package file into Lazarus and clicking Use > Install.

Getting Started

How can I print a StringGrid?

Nothing easier when you have the GridPrinter package...

pascal
procedure TForm1.PrintButtonClick(Sender: TObject);
begin
  GridPrinter1.Print;
end;

How can I see a preview of the printout before the printer starts to waste paper?

pascal
procedure TForm1.PrintPreviewButtonClick(Sender: TObject);
begin
  GridPrintPreviewDialog1.Execute;
end;

I have several printers and want to make sure that the print-out goes to the right one

TGridPrinter has a property ShowPrintDialog which controls whether a print dialog should be displayed before printing starts. The kind of dialog is determined by the following options:

Can individual cell formatting by the OnPrepareCanvas event be applied to the printout?

Yes. The TGridPrinter fires an OnPrepareCanvas event, too. Both even can share the same event handler. You only should be careful to use the correct Canvas when handling the event: When the Sender of the event is the grid, you must refer to the grid's Canvas, and when the Sender is the GridPrinter you must use that Canvas exposed by the GridPrinter; during printing this is the printer's Canvas, and when the preview is painted it is the Canvas of a temporary TBitmap.

Let's assume that your OnPrepareCanvas handler is supposed to paint the column title in bold type face. This could be done by the following code. The procedure must be assigned to the OnPrepareCanvas of both grid and GridPrinter.

pascal
procedure TForm1.PrepareCanvasHandler(Sender: TObject; ACol, ARow: Integer; AState: TGridDrawState);
var
  lCanvas: TCanvas;
begin
  if Sender = StringGrid1 then
    lCanvas := StringGrid1.Canvas
  else
  if Sender = GridPrinter1 then
    lCanvas := GridPrinter1.Canvas
  else
    raise Exception.Create('Unknown sender of OnPrepareCanvas.');

  if ARow < StringGrid1.FixedRows then
    lCanvas.Font.Style := [fsBold];
end;

Can I print a DBGrid?

Yes, but it requires a bit more work than just connecting it to the Grid property of the GridPrinter. A DBGrid displays data from a TDataset, but it keeps only a small number of records. But you usually want to print the entire dataset, rather than just the section loaded into the DBGrid.

At first we must tell the GridPrinter how many rows it will have to print. This can be done by providing a handler for the event OnGetRowCount in which we pass the dataset's RecordCount value to the provided parameter. Note that the title row must be included here. Note also that the RecordCount property often is only correct after the dataset pointer has been moved to the last record and back to the first record.

pascal
procedure TForm1.GridPrinter1GetRowCount(Sender: TObject; AGrid: TCustomGrid;
  var ARowCount: Integer);
var
  dbGrid: TDBGrid;
begin
  dbGrid := AGrid as TDBGrid;
  dbGrid.Datasource.Dataset.Last;
  dbGrid.Datasource.Dataset.First;
  ARowCount := dbGrid.Datasource.Dataset.RecordCount + 1;  // we must 1 for the header row
end;

In order to provide the cell texts for the GridPrinter we must write a handler for the OnGetCellText event which is fired whenever the GridPrinter needs any cell text. We will return to this in a minute. We must first clarify the process flow. The easiest way to get the cell texts is by iterating over the entire dataset. Provide a handler for the OnBeforePrint event which moves the dataset to its first record:

pascal
procedure TForm1.GridPrinter1BeforePrint(Sender: TObject);
begin
  DBGrid1.DataSource.Dataset.First;
end;

Another event, OnNewLine fires when the GridPrinter has finished printing a line and wants to proceed with the next one. This means we must advance the dataset to its next record. However, if a printed line extends over several pages we must be able to return to this record for completing its printout on the next page. Generally this must be handled by setting bookmarks - please see the example dbgrid2 in the GridPrinter installation folder for details. For some flat-file databases such as dBase, BufDataset etc. there is a simpler way by using the RecNo property of the dataset. This is a running number for each record starting at 1 with the first record. So, in the OnNewLine event we simply set the dataset's RecNo to the row parameter passed to the event:

pascal
procedure TForm1.GridPrinter1NewLine(Sender: TObject; AGrid: TCustomGrid;
  ARow: Integer);
var
  dbGrid: TDBGrid;
begin
  dbGrid := AGrid as TDBGrid;
  BufDataset1.RecNo := ARow;  // RecNo starts at 1. ARow starts at 1, too, since we display the header row   
end;

Then, within each row, the GridPrinter proceeds from grid column to grid column. In order to extract the cell text, we determine the column col from the ACol parameter of the OnGetCellTextevent and thus have access to the dataset field in that column (col.Field). Finally, we can query the cell text by calling the field's AsString method. Special handling is required for the very first row (ARow = 0) which corresponds to the grid titles:

pascal
procedure TForm1.GridPrinter1GetCellText(Sender: TObject; AGrid: TCustomGrid;
  ACol, ARow: Integer; var AText: String);
var
  dbGrid: TDBGrid;
  col: TColumn;
  colOffs: Integer;
begin
  AText := '';

  dbGrid := AGrid as TDBGrid;

  if (dgIndicator in dbGrid.Options) then
    colOffs := 1
  else
    colOffs := 0;

  if ACol < colOffs then
    exit;

  col := dbGrid.Columns[ACol - colOffs];

  if (ARow = 0) then
    AText := col.FieldName
  else
    AText := col.Field.AsString;
end;

As already mentioned, there are DBGrid sample projects in the GridPrinter installation to demonstrate the steps for DBGrid printing.

How can I print a page number?

You can print a page number at the top or bottom of every page by activating the header or footer of the GridPrinter. For this you select the Header (or Footer property and switch is Visible property to true. Then you enter the header (or footer) text in the property Text. In order to print the page number use for it the symbol $PAGE which is replaced by the number of the currently printed page. Note that the header/footer text consists of a left-aligned, centered and right-aligned part separated by a '|' character. So, if you want the page number to be centered the Text should be '|$PAGE|', and if you want to include the total page count you could use '|$PAGE of $PAGECOUNT|'. Learn about the other symbols in the documentation section below.

Documentation

TGridPrinter

Public methods

Public properties

Published properties and events

Properties

Events

TGridPrnHeaderFooter

This is the class of the header and footer lines which can be printed at the top and bottom of each page.

Published properties

Public properties

TGridPrnMargins

This class collects the parameters for the page margins:

Published properties

TGridPrintPreviewDialog

In unit GridPrnPreviewDlg.

Public methods

Published properties

TGridPrintPreviewFormParams

Functionality of the preview form

The preview dialog contains a toolbar with a variety of buttons. By means of the Options of the GridPrintPreviewDialog it is possible to hide those buttons which are not needed.

Here is a description of what the buttons can be used for:

The icons displayed on these buttons are taken from the Lazarus general-purpose image collection provided by Roland Hahn.

GridPrinter Actions

Unit GridPrnActions implements two standard actions for further simplification of usage

TGridPrinterAction

When its property GridPrinter is linked to a TGridPrinter instance and the action is linked to the Action property of a control a click on the control executes the Print method of the GridPrinter without any additional code.

TGridPrintPreviewAction

When its property PreviewDialog is linked to a TGridPrintPreviewDialog instance and the action is linked to the Action property of a control a click on the control runs the Execute method of the GridPrintPreviewDialog without any additional code.


From the Free Pascal wiki, page "GridPrinter", as it stood on 2022-12-14 after a change by Wp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.