Lazarus

Programming => General => Topic started by: PasCoder on October 15, 2022, 03:52:14 pm

Title: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 15, 2022, 03:52:14 pm
Dear Collegues;
I hope you're all fine.

I need to print a StringGrid with all its Contents (Rows and Columns). The data may seem to be more than one page.
Please, can anybody help me with such a code?

Thanks
Title: Re: How Do I Print a StringGrid with all its Contents?
Post by: wp on October 15, 2022, 04:50:38 pm
This is a very elemental article: https://www.swissdelphicenter.ch/en/showcode.php?id=769. You may have to adjust some constants in the code.

Of course this example can be extended to take care of real column widths/row heights, individual cell formatting (StringGrid.OnPrepareCanvas), etc. The more features are needed, the more complex code is required...
Title: Re: How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 15, 2022, 05:45:24 pm
Thank you for the code.  This is the code that you've directed me to.

Code: Pascal  [Select][+][-]
  1. procedure PrintGrid(sGrid: TStringGrid; sTitle: string);
  2. var
  3.   X1, X2: Integer;
  4.   Y1, Y2: Integer;
  5.   TmpI: Integer;
  6.   F: Integer;
  7.   TR: TRect;
  8. begin
  9.   Printer.Title := sTitle;
  10.   Printer.BeginDoc;
  11.   Printer.Canvas.Pen.Color  := 0;
  12.   Printer.Canvas.Font.Name  := 'Times New Roman';
  13.   Printer.Canvas.Font.Size  := 12;
  14.   Printer.Canvas.Font.Style := [fsBold, fsUnderline];
  15.   Printer.Canvas.TextOut(0, 100, Printer.Title);
  16.   for F := 1 to sGrid.ColCount - 1 do
  17.   begin
  18.     X1 := 0;
  19.     for TmpI := 1 to (F - 1) do
  20.       X1 := X1 + 5 * (sGrid.ColWidths[TmpI]);
  21.     Y1 := 300;
  22.     X2 := 0;
  23.     for TmpI := 1 to F do
  24.       X2 := X2 + 5 * (sGrid.ColWidths[TmpI]);
  25.     Y2 := 450;
  26.     TR := Rect(X1, Y1, X2 - 30, Y2);
  27.     Printer.Canvas.Font.Style := [fsBold];
  28.     Printer.Canvas.Font.Size := 7;
  29.     Printer.Canvas.TextRect(TR, X1 + 50, 350, sGrid.Cells[F, 0]);
  30.     Printer.Canvas.Font.Style := [];
  31.     for TmpI := 1 to sGrid.RowCount - 1 do
  32.     begin
  33.       Y1 := 150 * TmpI + 300;
  34.       Y2 := 150 * (TmpI + 1) + 300;
  35.       TR := Rect(X1, Y1, X2 - 30, Y2);
  36.       Printer.Canvas.TextRect(TR, X1 + 50, Y1 + 50, sGrid.Cells[F, TmpI]);
  37.     end;
  38.   end;
  39.   Printer.EndDoc;
  40. end;

I've tested the code and it has an error as shown in the attached image. I need further help Please.
Thanks
Title: Re: How Do I Print a StringGrid with all its Contents?
Post by: wp on October 15, 2022, 06:17:34 pm
The code that I linked is working in my simple project. It it does not compile for you probably have an issue with the order of units. I assume that you have the windows unit in the uses clause after the classes unit. Move it to the front because it defines a Rect identifier which overrides the Rect function in classes. Or qualify the Rect by typing a Classes. in front of it:
Code: Pascal  [Select][+][-]
  1.       TR := Classes.Rect(X1, Y1, X2 - 30, Y2);

BTW, I modified this example quite a lot and am appending a version with scaled column widths and row heights, as well as page breaks and numbers.
Title: Re: How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 15, 2022, 08:31:22 pm
Thank you very much. This is what I exactly needed. I've tested it and it works fine.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 15, 2022, 09:03:24 pm
The new attached version is a bit more advanced: it also prints the grid lines depending on whether the grid options goHorzLine, goVertLine, goFixedHorzLine and/or goFixedVertLine are included. Moreover, the font size is calculated from the real size of the grid's font.

What is missing is horizontal wrapping in case the grid is wider than a page. Maybe you can add this yourself?
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 15, 2022, 09:21:04 pm
For sure this is very fantastic. However, I'm yearning to Print the StringGrid with alternating colours or with other colour as I may have set them in rows and cells. I thought that this second version would be able to print in that format. Is it possible to achieve?

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 15, 2022, 11:01:06 pm
The attached v3 uses the FixedColor and AlternateColor of the grid to paint the cell background. I also tried to implement individual cell colors as defined by the OnPrepareCanvas event of the grid but this causes problems since the grid canvas cannot be accessed outside the grid's drawing cycle in a reliable way. Therefore the entire procedure should be rewritten as a more complex class which provides a similar event like the grid or even an OnDrawCell event for completely unlimited custom drawing. I think this is is more than I want to do now...

Note also that if you are a dark mode fan v3 will not make you very happy...
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 16, 2022, 04:46:02 pm
Hello wp, I hope that you're fine and doing well.

When I compile your example project, it compiles well but when I copy your Print Procedure into my Project it brings up an error shown in the attached image below. Please, can you help me resolve it? What I'm I missing?

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: jamie on October 16, 2022, 05:40:49 pm
I bet uhave the windows unit in the list?
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 16, 2022, 05:44:38 pm
GetFontData is in unit Graphics. Since it is usually added by default, you probably already have it in your uses clause. But - again - GetFontData exists also in the Windows unit. So, if you have unit Windows in your uses clause move it to the very front of the unit list. I'd even prefer to remove the Windows unit altogether since it is not needed in most cases at all; if there are compilation issues use LCLIntf and LCLType instead.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 16, 2022, 09:12:12 pm
Dear Jamie and wp, Thank for the your tireless help that you offer to me and to other people on this forum. Personally I say thank you.

As you suggested, I removed the "Windows" and the execution continued a little bit down and met another error that stopped the compilation of the unit as shown in the attached image. I'm I missing anything in this unit? Please, support me again.

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 16, 2022, 10:50:20 pm
The procedure that I uploded is written for instances of TStringGrid. But your grid seems to be a TKGrid which does not descend from TStringGrid. You must adapt the procedure to the properties of TKGrid. At first you must remove the grids unit and replace it by KGrids. Then try to compile and fix the compilation errors. Since I don't know TKGrid very well, I cannot help you with this task. But why don't you use the built-in printing capabilities of TKGrid? Study the KGrid demo.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 17, 2022, 12:59:53 am
Hey!
I've been able to make it work in my Project but still the code has three weaknesses;
1. Print Orientation - It only prints in Portrait form. I need an option to print in Landscape.
2. Cell wrapping/auto size to contents is not considered. Some of the contents are not printed since contents are fitting on the page.
3. Column Names are not printed!

Please, can these three issues be fixed?

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: J-G on October 17, 2022, 09:35:45 am
I've been able to make it work in my Project but still the code has three weaknesses;
1. Print Orientation - It only prints in Portrait form. I need an option to print in Landscape.

I might be able to provide a pointer to this (but not points 2 or 3). I had a similar issue about a month ago where even though I knew about 'Printer.Orientation' I had used it in an inapropriate place. It must be used BEFORE 'BeginDoc'.

Here's a snippet of my code :
Code: Pascal  [Select][+][-]
  1.   with Printer do
  2.    try
  3.      Orientation := poPortrait;
  4.      Title := F_Name+' - '+IntToStr(PrintCount)+'.PDF';
  5.  
  6.      BeginDoc;

In the [Printers] Unit (Line 35) you'll find :
Code: Pascal  [Select][+][-]
  1.   TPrinterOrientation = (poPortrait,poLandscape,poReverseLandscape,poReversePortrait);
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 17, 2022, 10:02:01 am
Dear J-G
Thank you for your help. I've fixed the page orientation issue. But the two challanges mentioned are not yet fixed. I still need more help.

Thank you
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 17, 2022, 05:20:27 pm
A new version in the attachment, v4.

Now I redid everything as a component, TGridPrinter, which gives a lot more flexibility in adding features:
To use the component, you must first create it (of course), then assign the grid to be printed to the Grid property, and then call the Print method. BUT: The grid is very elemental, and the type defined does not know the Cells property of the TStringGrid. Therefore you MUST provide a handler for the OnGetCellText event in which the text to be displayed in a given cell is passed over to the printer. This may sound complicated but the big advantage is that the GridPrinter can be used by all descendants of TCustomGrid.

Code: Pascal  [Select][+][-]
  1. uses
  2.   GridPrn;
  3. ...
  4. var
  5.   FGridPrinter: TGridPrinter;
  6. begin
  7.   FGridPrinter := TGridPrinter.Create(self);
  8.   FGridPrinter.Grid := StringGrid1;
  9.   FGridPrinter.OnGetCellText := @PrinterGetCellText;
  10. ...
  11.   FGridPrinter.Print;
  12. ...
  13.   FGridPrinter.Free;
  14. end;
  15.  
  16. procedure TForm1.PrinterGetCellText(Sender: TObject; AGrid: TCustomGrid;
  17.   ACol, ARow: Integer; var AText: String);
  18. begin
  19.   if AGrid is TStringGrid then
  20.     AText := TStringGrid(AGrid).Cells[ACol, ARow];
  21. end;

I am attaching the unit gridprn as well as my test project.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 18, 2022, 12:27:41 am
Dear WP, This is superb!!!! Thank you very much.

I've compiled your example and it works well. Now I'm trying to integrate into my Project.
However, I have a little challange with the OnPrepareCanvas . I have a column with a PickList as its editor. This PickList has names of different colors such that when a user picks up a color, that entire row is painted with that color. But it seems I'm failing to adapt it to the code you've provided. Please, look at my code and guide me;

Code: Pascal  [Select][+][-]
  1. if (Sender as TStringGrid).Cells[4, aRow] = 'AntiqueWhite' then begin
  2.   (Sender as TStringGrid).Canvas.Brush.Color := TColor($FAEBD7);
  3.   end else if (Sender as TStringGrid).Cells[4, aRow] = 'Aqua' then begin
  4.   (Sender as TStringGrid).Canvas.Brush.Color := TColor($00FFFF);
  5.   end else if (Sender as TStringGrid).Cells[4, aRow] = 'Aquamarine' then begin
  6.   (Sender as TStringGrid).Canvas.Brush.Color := TColor($7FFFD4);
  7.   end else if (Sender as TStringGrid).Cells[4, aRow] = 'Azure' then begin
  8.   (Sender as TStringGrid).Canvas.Brush.Color := TColor($F0FFFF);
  9.   end else if (Sender as TStringGrid).Cells[4, aRow] = 'Beige' then begin
  10.   (Sender as TStringGrid).Canvas.Brush.Color := TColor($F5F5DC);
  11.   end

The compilation is fine but when it comes to printing, it throws an error on those color names (strings) in the fourth column cells. I've also attached an image to show this runtime error.

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 18, 2022, 01:17:24 am
I did not test it, but I guess the problem is that the Sender of the TGridPrinter's OnPrepareCanvas is the GridPrinter, rather than the StringGrid. Therefore the cast of Sender to TStringGrid must fail.

Since you are reading cell content here you should call the function GetCellText of the GridPrinter. However, this function is in the protected section of the class and thus not accessible from the outside. You should move the line "function GetCellText(ACol, ARow: Integer): String; virtual;" from the protected to the public section.

Code: Pascal  [Select][+][-]
  1. type
  2.   TGridPrinter = class(TComponent)
  3.   private
  4.     ...
  5.   protected
  6.     // function GetCellText(ACol, ARow: Integer): String; virtual;  // <--- remove here
  7.     ...
  8.   public
  9.     constructor Create(AOwner: TComponent); override;
  10.     destructor Destroy; override;
  11.     function GetCellText(ACol, ARow: Integer): String; virtual;   // <--- and insert here
  12.     ...
  13.   end;
   
And then you can modify the OnPrepareCanvas as follows so that is can be used by both TStringGrid and TGridPrinter:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.StringGrid1PrepareCanvas(Sender: TObject; aCol, aRow: Integer;
  2.   aState: TGridDrawState);
  3. var
  4.   lCanvas: TCanvas;
  5. begin
  6.   // Use the correct canvas
  7.   if Sender is TStringGrid then
  8.     lCanvas := TStringGrid(Sender).Canvas
  9.   else if Sender is TGridPrinter then
  10.     lCanvas := Printer.Canvas
  11.   else
  12.     exit;
  13.  
  14.   // Get the text from the cell at col=4 and row=ARow
  15.   if Sender is TStringGrid then
  16.     s := TStringGrid(Sender).Cells[4, ARow]
  17.   else if Sender is TGridPrinter then
  18.     s := TGridPrinter(Sender).GetCellText(4, ARow);
  19.  
  20.   // Set the canvas brush color as defined by the cell text
  21.   if s = 'AntiqueWhite' then
  22.     lCanvas.Brush.Color := TColor($FAEBD7)
  23.   else if s = 'Aqua' then
  24.     lCanvas.Brush.Color := TColor($00FFFF)
  25.   else if s = 'Aquamarine' then
  26.     lCanvas.Brush.Color := TColor($7FFFD4)
  27.   else if s = 'Azure' then
  28.     lCanvas.Brush.Color := TColor($F0FFFF)
  29.   else if s = 'Beige' then
  30.     lCanvas.Brush.Color := TColor($F5F5DC);
  31. end;
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 18, 2022, 10:13:29 am
Dear wp, I can't thank you enough for your support. I'm learning a lot from your code.
I've fixed the OnPrepareCanvas as per your advice and the Project compiles well without any error.
However, when I print, the page is almost empty! It only shows the Column Headers only!
I've attached the Image to show the output. What else should I do?

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 18, 2022, 11:03:16 am
Is there a handler for OnGetCellText?

Besides that, I wonder why the border lines are not drawn correctly? Can you show me the code related to printing?
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 18, 2022, 01:12:13 pm
Apart from the one that you provided below, I've not provided any other. So, I used the one in your Project


Code: Pascal  [Select][+][-]
  1. procedure TFormAKJV.PrinterGetCellText(Sender: TObject; AGrid: TCustomGrid;
  2.   ACol, ARow: Integer; var AText: String);
  3. begin
  4.   if AGrid is TStringGrid then
  5.     AText := TStringGrid(AGrid).Cells[ACol, ARow];
  6. end;

Below is the Print Button Event

Code: Pascal  [Select][+][-]
  1. procedure TFormAKJV.Button1Click(Sender: TObject);
  2. begin
  3.   if PrintDialog1.Execute then
  4.     FGridPrinter.Print;
  5. end;

Also, in the PrepareCanvas I have this code for wordWrap. Does it also have a problew?

Code: Pascal  [Select][+][-]
  1. var
  2.     lCanvas: TCanvas;
  3.     s: String;
  4.     ts: TTextStyle;
  5.   begin
  6.     ts := ChapterStringGrid.Canvas.TextStyle;
  7.     ts.SingleLine := False;
  8.     ts.Wordbreak := True;
  9.     ChapterStringGrid.Canvas.TextStyle := ts;

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 18, 2022, 01:17:05 pm
What is type of grid that you are connecting to the TGridPrinter? In an earlier note I got the impression that it might be a TKGrid which should not work at all here.

The attached v5 works for TStringGrids "out of the box", i.e. a handler for OnGetCellText is not needed any more. (It is still needed for TDBGrid). The test project was extended to contain a cell with a color name which is interpreted in the OnPrepareCanvas event as background color of this cell (in a bit simpler way than what I explained earlier).
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 19, 2022, 12:23:37 am
v6 creates a print preview as a bitmap which can be displayed easily in a TImage embedded in a TScrollbox and enhanced by a toolbar with print and page navigation buttons as well as zoom factor combobox and zooming by mouse-wheel.

I moved development to my github repository now: https://github.com/wp-xyz/LazSamples/tree/master/grids/gridprinter.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: bonmario on October 19, 2022, 11:32:59 am
v6 creates a print preview as a bitmap which can be displayed easily in a TImage embedded in a TScrollbox and enhanced by a toolbar with print and page navigation buttons as well as zoom factor combobox and zooming by mouse-wheel.

I moved development to my github repository now: https://github.com/wp-xyz/LazSamples/tree/master/grids/gridprinter.

Hi you did a great job !!!
I think I have found a problem: if Grid has "FixedCols = 0", both preview and print are wrong!

Maybe there is also a problem when the columns have the width equal to 0 (I use this trick to hide some "service" columns), but this I am still checking

Thanks, Mario
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 19, 2022, 12:32:35 pm
I think I have found a problem: if Grid has "FixedCols = 0", both preview and print are wrong!

Maybe there is also a problem when the columns have the width equal to 0 (I use this trick to hide some "service" columns), but this I am still checking
"FixedCol = 0" issue fixed in last commit.

I don't see a problem with ColWidth = 0.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: bonmario on October 19, 2022, 01:14:53 pm
Thank you !!!
You're right, there's no problem, I was wrong.

P.S. Am I or I can't find it, or is there no property that allows you to change the margins?

Thanks again, Mario
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 19, 2022, 01:26:50 pm
You're right - forgotten to publish. Done now.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: bonmario on October 19, 2022, 02:32:03 pm
Perfect, thank you again !!!
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on October 21, 2022, 07:40:32 pm
You're right - forgotten to publish. Done now.

Dear wp,
I want to say thank you for such a superb support especially to me. I've pulled the final version from GitHub and it has worked fine.

Can you support me a little more with row auto Height adjustment to fit the cell content when wordwrap is enabled. I've also attached an image.

Thanks
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on October 21, 2022, 08:09:38 pm
Apart from small rounding errors the print-out and preview should match the grid on the form. Therefore you should see the too-narrow row heights already in the grid on the form? If not, you should post a sample project so that I can find out why form and print/preview do not match.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: bonmario on November 14, 2022, 03:37:11 pm
Sorry, I can't find them anymore, or at this link https://github.com/wp-xyz/LazSamples/tree/master/grids/gridprinter there are no more sources?

Thanks, Mario
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: paweld on November 14, 2022, 03:56:42 pm
now in CCR repository: https://sourceforge.net/p/lazarus-ccr/svn/HEAD/tree/components/gridprinter/
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on November 14, 2022, 04:57:14 pm
Sorry, I moved it to CCR as paweld noted already - that's where it should have been from the start... There is even a release version available for OPM (but this was a bit too early because I had some more ideas which might break the interface). I'll prepare a new release when I'm finished with what's still on my mind. There is also a (yet incomplete) wiki documentation at https://wiki.freepascal.org/GridPrinter.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: bonmario on November 14, 2022, 05:40:03 pm
Ok, thanks !!!
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on November 14, 2022, 09:06:14 pm
Dear WP,
Thank you very much for the work. I've been following this thread and I'm glad that you've made Printing Components for the TStringGrid. This answers well my original question. However, I need some kind of help.

1. I've dragged the two components and linked them together but the cells with strings in multiple lines are all in one line in the preview!
2. The colors that I painted for each row are also not recognized.

I've attached the images also, below is the code for the PrepareCanvas

Code: Pascal  [Select][+][-]
  1. procedure TFormAKJV.ChapterStringGridPrepareCanvas(Sender: TObject; aCol, aRow: integer; aState: TGridDrawState);
  2.   var
  3.     lCanvas: TCanvas;
  4.     s: String;
  5.     ts: TTextStyle;
  6.   begin
  7.     ts := ChapterStringGrid.Canvas.TextStyle;
  8.     ts.SingleLine := False;
  9.     ts.Wordbreak := True;
  10.     ChapterStringGrid.Canvas.TextStyle := ts;
  11.  
  12.   if Sender is TStringGrid then
  13.     lCanvas := TStringGrid(Sender).Canvas
  14.   else if Sender = ChapterGridPrinter then
  15.     lCanvas := ChapterGridPrinter.Canvas
  16.   else
  17.     exit;
  18.  
  19.   if Sender is TStringGrid then
  20.     s := TStringGrid(Sender).Cells[4, ARow]
  21.   else if Sender = ChapterGridPrinter then
  22.     s := ChapterGridPrinter.GetCellText(4, ARow);
  23.  
  24.   if s = 'AntiqueWhite' then begin
  25.       lCanvas.Brush.Color := TColor($FAEBD7);
  26.       end else if s = 'Aqua' then begin
  27.       lCanvas.Brush.Color := TColor($00FFFF);
  28.       end else if s = 'Aquamarine' then begin
  29.       lCanvas.Brush.Color := TColor($7FFFD4);
  30.       end else if s = 'Azure' then begin
  31.       lCanvas.Brush.Color := TColor($F0FFFF);
  32.       end else if s = 'Beige' then begin
  33.       lCanvas.Brush.Color := TColor($F5F5DC);
  34.       end

Thanks

Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on November 14, 2022, 10:00:03 pm
You apply the TextStyle to the Canvas of the ChapterStringGrid only. Move the evaluation of the Sender to the top of the event handler and apply the TextStyle to lCanvas.

Additionally a simplification for cell text extraction: Since grid and printer access the same cells it is enough to read the the cell text from the grid directly; there is no need to distinguish the Sender here - sorry, one of my previous sample codes was a bit too complicated here.

Code: Pascal  [Select][+][-]
  1. procedure TFormAKJV.ChapterStringGridPrepareCanvas(Sender: TObject; aCol, aRow: integer; aState: TGridDrawState);
  2. var
  3.   lCanvas: TCanvas;
  4.   s: String;
  5.   ts: TTextStyle;
  6. begin
  7.   if Sender is TStringGrid then
  8.     lCanvas := TStringGrid(Sender).Canvas
  9.   else if Sender = ChapterGridPrinter then
  10.     lCanvas := ChapterGridPrinter.Canvas
  11.   else
  12.     exit;
  13.  
  14.   ts := lCanvas.TextStyle;
  15.   ts.SingleLine := False;
  16.   ts.Wordbreak := True;
  17.   lCanvas.TextStyle := ts;
  18.  
  19.   s := ChapterStringGrid.Cells[4, ARow];
  20.  
  21.   if s = 'AntiqueWhite' then begin
  22.       lCanvas.Brush.Color := TColor($FAEBD7);
  23.       end else if s = 'Aqua' then begin
  24.       lCanvas.Brush.Color := TColor($00FFFF);
  25.       end else if s = 'Aquamarine' then begin
  26.       lCanvas.Brush.Color := TColor($7FFFD4);
  27.       end else if s = 'Azure' then begin
  28.       lCanvas.Brush.Color := TColor($F0FFFF);
  29.       end else if s = 'Beige' then begin
  30.       lCanvas.Brush.Color := TColor($F5F5DC);
  31.       end;
  32. end;
  33.  
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: Sheepdog on November 15, 2022, 09:27:09 am
For what it is worth... mostly for someone drawn to this thread with an interest in "getting started" with string grids, I suspect, I have a webpage with some notes on that... https://sheepdogguides.com/lut/lt4Nc.htm
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on December 06, 2022, 08:48:44 am
You apply the TextStyle to the Canvas of the ChapterStringGrid only. Move the evaluation of the Sender to the top of the event handler and apply the TextStyle to lCanvas.

Additionally a simplification for cell text extraction: Since grid and printer access the same cells it is enough to read the the cell text from the grid directly; there is no need to distinguish the Sender here - sorry, one of my previous sample codes was a bit too complicated here.

Code: Pascal  [Select][+][-]
  1. procedure TFormAKJV.ChapterStringGridPrepareCanvas(Sender: TObject; aCol, aRow: integer; aState: TGridDrawState);
  2. var
  3.   lCanvas: TCanvas;
  4.   s: String;
  5.   ts: TTextStyle;
  6. begin
  7.   if Sender is TStringGrid then
  8.     lCanvas := TStringGrid(Sender).Canvas
  9.   else if Sender = ChapterGridPrinter then
  10.     lCanvas := ChapterGridPrinter.Canvas
  11.   else
  12.     exit;
  13.  
  14.   ts := lCanvas.TextStyle;
  15.   ts.SingleLine := False;
  16.   ts.Wordbreak := True;
  17.   lCanvas.TextStyle := ts;
  18.  
  19.   s := ChapterStringGrid.Cells[4, ARow];
  20.  
  21.   if s = 'AntiqueWhite' then begin
  22.       lCanvas.Brush.Color := TColor($FAEBD7);
  23.       end else if s = 'Aqua' then begin
  24.       lCanvas.Brush.Color := TColor($00FFFF);
  25.       end else if s = 'Aquamarine' then begin
  26.       lCanvas.Brush.Color := TColor($7FFFD4);
  27.       end else if s = 'Azure' then begin
  28.       lCanvas.Brush.Color := TColor($F0FFFF);
  29.       end else if s = 'Beige' then begin
  30.       lCanvas.Brush.Color := TColor($F5F5DC);
  31.       end;
  32. end;
  33.  

Dear wp,
I followed your advice but it seems there is still an issue to sort out.
1. The component does not print/preview wordwrapped cells. Actually, its like it dose not recognize that the cells' contents have been wordwrapped. Check on the first four cells in the Billing Address Column.
2. The set row colours are also not priviewed and printed!

I've attached a sample project for you to review. Please, help me sort these issues out for me.

Thank you
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: wp on December 06, 2022, 10:55:39 pm
Wordwrap requires the following conditions:
- Canvas.TextStyle.WordWrap must be true, of course.
- Canvas.TextStyle.SingleLine must be false
- Canvas.TextStyle.EndEllipsis must be false. BUT: The grid Option goCellEllipsis when active sets this to true. This is happening in your grid. Therefore wordwrap is not working. --> Remove it from the Options, and the wordwrap will work.

The other issue is that the row colors in your grid do not appear in the preview. This is because you do not assign the StringGrid1PrepareCanvas event handler to GridPrinter1.OnPrepareCanvas: Select the GridPrinter1 component in the form, find the OnPrepareCanvas event and select StringGrid1PrepareCanvas from the dropdown list.
Title: Re: [SOLVED] How Do I Print a StringGrid with all its Contents?
Post by: PasCoder on December 09, 2022, 04:10:35 pm
Wordwrap requires the following conditions:
- Canvas.TextStyle.WordWrap must be true, of course.
- Canvas.TextStyle.SingleLine must be false
- Canvas.TextStyle.EndEllipsis must be false. BUT: The grid Option goCellEllipsis when active sets this to true. This is happening in your grid. Therefore wordwrap is not working. --> Remove it from the Options, and the wordwrap will work.

The other issue is that the row colors in your grid do not appear in the preview. This is because you do not assign the StringGrid1PrepareCanvas event handler to GridPrinter1.OnPrepareCanvas: Select the GridPrinter1 component in the form, find the OnPrepareCanvas event and select StringGrid1PrepareCanvas from the dropdown list.

Dear wp,
Thank you very much. It has now worked as expected!
TinyPortal © 2005-2018