Calculation in Text and Tables

<< Click to Display Table of Contents >>

Navigation:  Programming > WPReporter >

Calculation in Text and Tables

When you have licensed WPReporter you can use powerful calculation commands in WPTools. To use the calculation names and formulas add the component TWPFormulaInterface to the application.

 

The calculation tool uses names and formulas.  Names can be assigned to paragraphs or cells only.

Formulas can be assigned to paragraphs (or cells) and also special TWPTextObj objects. When the text is calculated the paragraph text or the displayed text of the TWPTextObj will show the floating point result of the calculation.

 

If a formula is just a name (assigned to one or many other paragraphs) the result is the sum of the numbers found in all the paragraph which use this name. This feature makes it easy to sum up values.

 

Please see the demo TableCalc. This demo includes code to create a simple invoice. It also shows how to activate the optional display of paragraph names and formulas.

 

Which this option activated you will see an output like this:

 

clip0060

 

You can see that the cells in each column use a different name (highlighted in red). The formula (in blue) uses a relative function left(N) which returns the value of the Nth cell to the left .

The total row uses a formula (in blue) just the name used by the cells which should be summed up.

 

Please note that this way to calculate is optimized for invoices and similar: The numbers will be always summed as displayed (rounded), not using possible additional decimal values.

 

The text object which also displays the total is created as simple as:

 

 obj := par.AppendNewObject(wpobjTextObject,false, false);

 obj.Name := 'CALC'; // fixed name

 obj.Source := 'PAR_TOTAL'; // display the sum of all par with this name

 obj.Params := '???'; // initial display text

 

Note: the objects name is 'CALC' which is obligatory.

 

If you need to create sub totals in header or footer texts You can use a TWPTextObject with the name PAINT_CALC.

The 'Source' should be a + sign followed by the name of all paragraphs which should be summed up. Other formulas are not possible since the calculation is not performed by the WPEval unit. This simple calculation is the default action done for the OnTextObjectPaintCalc of the TWPFormulaInterface. Please also see below.

 

Using HTML syntax such a footer can be created like this:

 

 WPRichText1.HeaderFooter.Get(wpIsFooter,wpraNotOnLastPage).RtfText.AsString :=

  '<html><div align=right style="border-top-width:0.5pt">Subtotal: <TEXTOBJ name="PAINT_CALC" source="+PAR_TOTAL">???</TEXTOBJ></div></html>';

 

This functions are created by the unit WPTblCalc and can be used in formulas:

 

left(N, N2, ...Nn) : sum up the cells to the left

right(N, N2, ...Nn) : sum up the cells to the right

previous(N, N2, ...Nn) : sum up the cells in the same column but previous rows

prior(N, N2, ...Nn) : synonym for previous()

average(name) - calculate the average of all paragraphs with the give name

valcount(name) - count the paragraphs with the give name

 

 

The event TWPFormulaInterface.OnTextObjectPaintCalc makes it possible to calculate the contents of fields at paint time. This is very useful for fields in header or footer texts or repeated table header or footer rows. These fields are not physically duplicated, they are just painted on several pages. So their contents must be calculated at paint time.

 

headerfooterrow

 

The event OnTextObjectPaintCalc provides several parameters which make it possible to evaluate the text on the current page (the page they are painted upon).

 

Please see the TableCalc demo. There we sum up all values which are in a certain mail merge field placed on a certain page. A total sum is simply retrieved from a value which is added to each row. We are searching for the last occurrence of this value and use it. So if the page break changes and the last row becomes the first row of the next page we use the new last value instead.

 

Please note that if a result objects is reused for different pages, i.e. it resides in a header or footer, it must be wide enough to hold the largest possible value. Right alignment is not possible in this case!

 

If you need aligned calculated text you can paint it yourself, similar to this example:

 

procedure TForm1.OnPaintSum(Sender: TWPTextObj; OutCanvas: TCanvas; xres, yres: Integer; x, Y, w, h, BASE: Integer);

begin

if Sender.NameIs('anyname') then

begin

    OutCanvas.TextOut(X+w-OutCanvas.TextWidth(Sender.Params),Y+base,Sender.Params);

end;

end;

 

procedure TForm1.WPRichText1TextObjGetTextEx(RefCanvas: TCanvas;

 TXTObject: TWPTextObj; var PrintString: WideString; var WidthInPix,

 HeightInPix: Integer; var PaintObject: TWPTextObj; Xres, YRes: Integer);

var i : Integer;

   aPage : TWPVirtPage;

   aLineData : TWPVirtPageImageLineRef;

   sum : Double;

begin

if TXTObject.NameIs('anyname') then

begin

    PrintString := '                ';

    PaintObject := TXTObject;

    TXTObject.Params := '--.--';

    if WPRichText1.Memo._MeasureObjectCurrPage<>nil then

    try

       aPage := WPRichText1.Memo._MeasureObjectCurrPage;

       sum := 0;

      for i := 0 to aPage.LineCount-1 do

      begin

 

        if aPage.GetLine(i,aLineData) and (aLineData.Par.CharCount>0) then

        begin

          if (aLineData.LineNr=0) and (aLineData.Par.WPATName='VAL') then

               sum := sum + StrToFloat( aLineData.Par.GetAllText(false,false) );

        end;

      end;

       TXTObject.Params := FloatToStr(sum);

    except

    end;

    PaintObject.OnPaint := OnPaintSum;

end

end;