Recent

Author Topic: [SOLVED] GridPrinter with fpspreadsheet  (Read 2013 times)

rca

  • Full Member
  • ***
  • Posts: 121
[SOLVED] GridPrinter with fpspreadsheet
« on: July 24, 2025, 04:33:07 pm »
I am using GridPrinter (r9793) with fpspreadsheet.
Windows 11 64 Bit
Lazarus 4 and FPC fixes 3.2

I am attaching a simple example "testgprint.zip" based on "fpspreadsheet_demo".

In Preview everything looks excellent. (Image attached)

But when printing in PDF it presents some details: (Image attached)
* Fixed's font is very small and is not legible.
* The grid lines are almost not visible.
* The text inside each cell is not aligned vertically in the center.
* Float numbers are printed as integers.


I appreciate the help you can give me.
« Last Edit: July 25, 2025, 02:57:53 am by rca »

wp

  • Hero Member
  • *****
  • Posts: 13412
Re: GridPrinter with fpspreadsheet
« Reply #1 on: July 25, 2025, 12:38:46 am »
I found some bugs in the TsWorksheetGrid and the GridPrinter. Please update your fpspreadsheet and your gridprinter packages from ccr: Use svn or download the zipped snapshots from https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/fpspreadsheet/ and https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/gridprinter/, respectively.

With these changes, your test project needs to be updated at a few places - see corrected version in attachment

rca

  • Full Member
  • ***
  • Posts: 121
Re: GridPrinter with fpspreadsheet
« Reply #2 on: July 25, 2025, 01:57:09 am »
@wp
Thank you for your work and dedication.

I have already downloaded the latest versions of the components and the example that you have modified.

Now when printing in PDF, it looks great (Image attached).
However, it still shows the values as an integer and should be a float.

Thanks for the help

wp

  • Hero Member
  • *****
  • Posts: 13412
Re: GridPrinter with fpspreadsheet
« Reply #3 on: July 25, 2025, 02:40:37 am »
Ah, since the worksheet grid displays numbers such that they are rounded to fit into a cell we must make sure that the column widths are scaled during printing to the higher printer resolution:

Add an array FOldColWidths (array of integer) to the declarations of the main form:
Code: Pascal  [Select][+][-]
  1.   TForm1 = class(TForm)
  2.   [...]
  3.   private
  4.     FGridCanvas: TCanvas;
  5.     FOldZoomFactor: Double;
  6.     FOldPadding: Integer;
  7.     FOldGridOptions: TGridOptions;
  8.     FOldColWidths: Array of Integer;
  9.   [...]
  10.  
Then modify the BeforePrint and AfterPrinter event handlers as follows:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.GridPrinter1AfterPrint(Sender: TObject);
  2. var
  3.   i: Integer;
  4. begin
  5.   // Restore the worksheetgrid's Canvas.
  6.   sWorksheetGrid1.Canvas := FGridCanvas;
  7.  
  8.   // Restore the orignal value of the CellPadding of the grid
  9.   varCellPadding := FOldPadding;
  10.  
  11.   // Restore drawing of the grid lines in the worksheet grid
  12.   sWorksheetGrid1.Options := FOldGridOptions;
  13.  
  14.   // Restore the original grid column widths
  15.   for i := 0 to High(FOldColWidths) do
  16.     sWorksheetGrid1.ColWidths[i] := FOldColWidths[i];
  17.  
  18.   // Restore the worksheetgrid's ZoomFactor
  19.   sWorksheetGrid1.ZoomFactor := FOldZoomFactor;
  20. end;
  21.  
  22. procedure TForm1.GridPrinter1BeforePrint(Sender: TObject);
  23. var
  24.   i: Integer;
  25. begin
  26.   // We want to draw on the printer/preview canvas. Therefore, we assign the
  27.   // grid's canvas to that of the GridPrinter. In order to restore the grid
  28.   // canvas after printing, we store its old canvas.
  29.   FGridCanvas := sWorksheetGrid1.Canvas;
  30.   sWorksheetGrid1.Canvas := GridPrinter1.Canvas;
  31.  
  32.   // Since the cells are drawn by the grid we must make sure that the correctly
  33.   // scaled value of the CellPadding is used during printing.
  34.   FOldPadding := varCellPadding;
  35.   varCellPadding := GridPrinter1.Padding;
  36.  
  37.   // The TsWorksheetGrid paints the grid lines in the DrawCell method. To
  38.   // avoid duplicate drawing (which, BTW, is offset by 1 pixel) we turn off
  39.   // painting of the grid lines in the worksheet grid so that the grid printer
  40.   // can take control. This is needed for correct scaling of the grid line width.
  41.   FOldGridOptions := sWorksheetGrid1.Options;
  42.   sWorksheetGrid1.Options := sWorksheetGrid1.Options - [
  43.     goHorzLine, goVertLine, goFixedHorzLine, goFixedVertLine
  44.   ];
  45.  
  46.   // Since the worksheet grid can reformat numeric cell values to fit into the
  47.   // cell widths we must scale the column widths to the printer resolution:
  48.   SetLength(FOldColWidths, sWorksheetGrid1.ColCount);
  49.   for i := 0 to High(FOldColWidths) do
  50.   begin
  51.     FOldColWidths[i] := sWorksheetGrid1.ColWidths[i];
  52.     sWorksheetGrid1.ColWidths[i] := GridPrinter1.ScaleX(FOldColWidths[i]);
  53.   end;
  54.  
  55.   // Store the worksheetgrid's ZoomFactor. We may have to change it
  56.   FOldZoomFactor := sWorksheetGrid1.ZoomFactor;
  57.   sWorksheetGrid1.ZoomFactor := GridPrinter1.PrintScaleFactor;
  58. end;

rca

  • Full Member
  • ***
  • Posts: 121
Re: GridPrinter with fpspreadsheet
« Reply #4 on: July 25, 2025, 02:57:22 am »
I made the suggested changes and it works like a charm. (Image attached)

Thank you so much for your explanation and help!

wp

  • Hero Member
  • *****
  • Posts: 13412
Re: [SOLVED] GridPrinter with fpspreadsheet
« Reply #5 on: July 25, 2025, 11:46:12 am »
I added an adapter unit to the fpspreadsheet sample project which greatly simplifies printing of fpSpreadsheet grids: Just create an instance of TFPSpreadsheetGridPrinterAdapter and assign the instance of the GridPrinter to its GridPrinter property - this automatically creates the required event handlers. Likewise an adapter unit was added to simplify printing of DBGrids.

Code: Pascal  [Select][+][-]
  1. uses
  2.   ..., FPSpreadsheetPrintAdapter, ...;
  3.  
  4. type
  5.   TMainForm = class(TForm)
  6.     [...]
  7.   private
  8.     FAdapter: TFPSpreadsheetGridPrinterAdapter;
  9.   [...]
  10.   end;
  11.  
  12. procedure TMainForm.FormCreate(Sender: TObject);
  13. begin
  14.   // Use a TFPSpreadsheetGridPrinterAdapter to do all the adjustments needed
  15.   // for FPSpreadsheet grids.
  16.   FAdapter := TFPSpreadsheetGridPrinterAdapter.Create(self);
  17.   FAdapter.GridPrinter := GridPrinter1;
  18.  
  19.   [...]
  20. end;

See updated sample project in the examples/fpspreadsheet folder.
« Last Edit: July 25, 2025, 12:31:11 pm by wp »

rca

  • Full Member
  • ***
  • Posts: 121
Re: [SOLVED] GridPrinter with fpspreadsheet
« Reply #6 on: July 25, 2025, 06:10:55 pm »
I installed the new version of Grid Printer by adding "fpspreadsheetprintadapter.pas",
the adapter unit from the fpspreadsheet sample project, with the necessary changes
(it simplifies the code), and it works like a charm.

Thanks so much, @wp. Excellent work!.

 

TinyPortal © 2005-2018