Create Table in Code

Top  Previous  Next

Very often you will have to create a table, for example a calculation.

 

This can be done best using the TableAdd procedure. This procedure requires only a few parameters, such as row cont and column count but can also work with a callback procedure which is executed for each created cell.

 

Since the callback procedure receives information about the current column and row number it is easy to apply special properties to certain cells or preset the contents of the created cell.

 

Note: You can also use the Rows[r].Cols[c] arrays as described in the second part of this chapter but then you have to take care that you work with the correct row index. Using this arrays is probably also a little slower.

 

Please see reference for supported WPAT_ codes.

 

a) Use TableAdd() with a callback function

 

This code will append a new table to the end of the text:

 

WPRichText1.TableAdd(7,7,

    [wptblActivateBorders,wptblAppendTableAtEnd],nil, InvoiceDemoCell);

 

 

This is a screen shot of the created table:

clip0102

 

The callback procedure InvoiceDemoCell is implemented like this

 

procedure TWPTableCalc.InvoiceDemoCell(RowNr, ColNr: Integer; par: TParagraph);

const prods : array[1..5] of string =

( 'Cool', 'Master', 'Hummer', 'High Performace', 'Better' );

begin

// Set the widths of the rows

case ColNr of

      1 : par.ASet(WPAT_COLWIDTH_PC, 500);  // % * 100 !

      2 : par.ASet(WPAT_COLWIDTH_PC, 2500);

      else

      begin

         par.ASet(WPAT_COLWIDTH_PC, 1400);

         par.ASet(WPAT_Alignment, Integer(paralRight));

      end;

end;

 

// Set the text and the cell names and commands

 

if RowNr=1 then // Header Row ------------------------------

begin

    case ColNr of

      1 : ;

      2 : par.SetText('Product');

      3 : par.SetText('Price');

      4 : par.SetText('Amount');

      5 : par.SetText('net');

      6 : par.SetText('+VAT');

      7 : par.SetText('total');

    end;

    par.ASetColor(WPAT_FGColor, $A0A0A0);

    par.ASet(WPAT_ParProtected,1);

    par.ASet(WPAT_Alignment, Integer(paralCenter));

end else

if RowNr=7 then // Footer Row ------------------------------

begin

    par.ADel(WPAT_BorderWidth); // Delete the border width for ALL linese

    par.ASet(WPAT_BorderWidthT, 40); // ANd set the top line to 40 twips

    par.ASetAdd( WPAT_BorderFlags, WPBRD_DRAW_Top);  // Add a flag!

    // par.ParentRow.ASet(WPAT_BoxMinHeight, WPCentimeterToTwips(1.5));

    par.ASet(WPAT_SpaceBefore, WPCentimeterToTwips(0.3));

    par.ASet(WPAT_SpaceAfter, WPCentimeterToTwips(0.3));

    par.ASet(WPAT_ParProtected,1);

    case ColNr of

      1 : ;

      2 : ;

      3 : ;

      4 : ;

      5 : begin

            par.ASetStringProp(WPAT_PAR_COMMAND, 'PAR_NET');

          end;

      6 : begin

             par.ASetStringProp(WPAT_PAR_COMMAND, 'PAR_VAT');

          end;

      7 : begin

             par.ASetStringProp(WPAT_PAR_COMMAND, 'PAR_TOTAL');

             par.ASetCharStyle(true, WPSTY_BOLD);

          end;

    end;

 

end else // Data Rows ------------------------------

begin

   case ColNr of

      1 : begin

             par.SetText(IntToStr(RowNr-1));

             par.ASet(WPAT_ParProtected,1);

          end;

      2 : par.SetText(prods[RowNr-1]);

      3 : par.SetText(IntToStr(Random(1000)+1));

      4 : par.SetText(IntToStr(Random(3)+1));

      5 : begin

            par.ASetStringProp(WPAT_PAR_COMMAND, 'left(2)*left(1)');

            par.ASetStringProp(WPAT_PAR_NAME, 'PAR_NET');

            par.ASet(WPAT_ParProtected,1);

          end;

      6 : begin

             par.ASetStringProp(WPAT_PAR_COMMAND, 'left(1)*0.16');

             par.ASetStringProp(WPAT_PAR_NAME, 'PAR_VAT');

             par.ASet(WPAT_ParProtected,1);

          end;

      7 : begin

             par.ASetStringProp(WPAT_PAR_COMMAND, 'left(2)+left(1)');

             par.ASetStringProp(WPAT_PAR_NAME, 'PAR_TOTAL');

             par.ASet(WPAT_ParProtected,1);

          end;

    end;

end;

end;

 

Note: The commands

             par.ASetStringProp(WPAT_PAR_COMMAND, 'left(2)+left(1)');

             par.ASetStringProp(WPAT_PAR_NAME, 'PAR_TOTAL');

are only usable with WPTools Bundle. They are used to add calculation to a table.

 

 

b) Use TableAdd() and the Rows[] and Cols[] arrays

 

This example appends 2 rows to the current table (a new table is created if necessary) and loads an image in the second cell of the first row.

 

Screen shot of the created table. (Only the first row is visible.)

clip0101

 

procedure TForm1.CreateTableWithImageClick(Sender: TObject);

var tbl: TParagraph;

obj: TWPTextObj;

img: TWPOImage;

imagefilename: string;

rowoffset : Integer;

begin

// Select the image from file or use a local image

imagefilename := '';

if SelectImageFile.Checked then

begin

   if OpenPictureDialog1.Execute then

     imagefilename := OpenPictureDialog1.FileName

   else exit;

end;

 

// Create the image object

img := TWPOImage.Create(WPRichText1); // uses WPObj_Image

try

   if imagefilename = '' then img.Picture.Assign(Image2.Picture)

   else img.LoadFromFile(imagefilename);

except

   img.Free; // We cannot load this image

   raise;

end;

 

// This code is required if we do *not* use the wptblAppendTableAtEnd option.

// since than an existing table is enlarged

tbl := WPRichText1.Table;

if tbl<>nil then

begin

    rowoffset := tbl.RowCount;

    WPRichText1.ActiveParagraph := tbl.LastChild.ColFirst;

end

else rowoffset := 0;

 

// Create the table and after that modify the cells

//  makes sure a new table is created at the end!

tbl := WPRichText1.TableAdd(2, 1, [wptblActivateBorders], nil, nil);

 

// Set text of first column

tbl.Rows[rowoffset+0].Cols[0].SetText(imagefilename);

 

// Create the TWPTextObj (which is the reference to image)

obj := tbl.Rows[rowoffset+0].Cols[1].AppendNewObject(wpobjImage, false, false, 0);

obj.ObjRef := img;

obj.Frame := [wpframeFine];

 

// Set the size of the image

obj.Width := img.ContentsWidth * 2;

obj.Height := img.ContentsHeight * 2;

 

// Empty row, no borders - move cursor to first cell

WPRichText1.ActiveParagraph := tbl.ColFirst;

tbl := WPRichText1.TableAdd(2, 1, [], nil, nil);

WPRichText1.ActiveParagraph := tbl.ColFirst;

 

// Format and display changed text

WPRichText1.Refresh;

end;

 

c) Create a table with a header and footer row which are repeated on each page

clip0118

 

This feature is controlled by the flags paprIsFooter and paprIsHeader in the property TParagraph.par. The property must be set in the row paragraph which is the parent paragraph of a cell. The API TableAdd does this for you.

 

We suggest to use this feature with the flag wpfDontBreakTableRows in FormatOptions.

In any case please set the property wpDisableSpeedReformat.

 

Example code:

 

procedure TForm1.CreateTableCellCallBackHF(RowNr, ColNr: Integer; par: TParagraph);

begin

if RowNr = -1 then // THIS CELL IS IN THE HEADER

begin

   par.ASetColor(WPAT_BGColor, clBtnFace);

   if ColNr = 1 then par.ASet(WPAT_COLWIDTH, WPCentimeterToTwips(1.5))

   else par.SetText('HEADER');

end

else if RowNr = -2 then // THIS CELL IS IN THE FOOTER

begin

   par.ASetColor(WPAT_BGColor, clBtnFace);

   if ColNr = 1 then par.ASet(WPAT_COLWIDTH, WPCentimeterToTwips(1.5))

   else par.SetText('FOOTER');

end else

begin

   if (RowNr and 1) = 0 then par.ASetColor(WPAT_BGColor, clYellow);

   if ColNr = 1 then

   begin

     par.ASetColor(WPAT_BGColor, clBtnFace);

     par.ASet(WPAT_COLWIDTH, WPCentimeterToTwips(1.5));

     par.SetText(IntToStr(RowNr));

   end else

   begin

     par.SetText(IntToStr(FCellNr));

     inc(FCellNr);

   end;

end;

end;

 

procedure TForm1.CreateTableWithHeaderFooterClick(Sender: TObject);

begin

WPRichText1.Clear;

FRowCount := 200; // count of rows, excluding header and footer!

WPRichText1.FormatOptions := [wpDisableSpeedReformat, wpfDontBreakTableRows];

WPRichText1.TableAdd(

   4, FRowCount,

   [wptblActivateBorders,wptblCreateHeaderRow,wptblCreateFooterRow], nil,

   CreateTableCellCallBackHF);

WPRichText1.Refresh;

end;