Subject Re: Can render problem
From Mervyn Bick <invalid@invalid.invalid>
Date Sat, 28 Nov 2015 12:23:32 +0200
Newsgroups dbase.getting-started

On 11/28/2015 12:45 AM, Charlie wrote:
> Hi...  I used can render totaling two fields. (thanks Mervyn).. Here is the code:
>
>
>             function TEXT1_canRender()
>        this.text = this.parent.textqty1.text() * this.parent.textcost1.text()
>        return true
>
>     function TEXT2_canRender()
>        this.text = this.parent.textqty1.text() * this.parent.textsell1.text()
>        return true
>
> They work fine.  But now I am trying to total the two made up fields and don't exactly know how.  I tried the following for the first:
>
>
> function TEXT11_canRender()
>        sum this.parent.text1.text() = this.text

SUM, as a command, is pure XDML and it also requires a TO so that it
knows where to place the result.  It is used with tables opened in
workareas and it does not work with objects at all.

>        return true
>
> But dbase doesn't like this in that it is asking me to name the file.  Is there a way of totaling each made up field?  I don't think it is listed in the report total fields.
>
> Thanks...
>


When you place a text object on a report to display a field from a table
dBASE uses a codeblock to fetch the value from the record.  To be able
to access the value displayed so that you can use it in a calculation
you need to evaluate the codeblock by using the CALL operator ie a pair
of parentheses.  To display your calculated value you need to assign it
to the text property of a text object.  That is what is happening in

    this.text = this.parent.textqty1.text() * this.parent.textcost1.text()


You have assigned the result from TEXTQTY1.TEXT times the value from
TEXTCOST1.TEXT to the text property of the text object.

The thing to remember here is that you have placed actual values, not
codeblocks, in the text properties of oRef.TEXT1 and oRef.TEXT2 so, to
use these values, you don't need to use the CALL operator to access
them.  I am, however, not sure if the values are stored in the text
property as character or numeric and I can't check this for myself at
the moment.  (They should be numeric but if you get an error based on
this assumption you will need to deal with it.)

If you want to display the sum of the two calculated values on the
detailband next to the two calculated values using oRef.TEXT11 the
following canRender event handler will do the job.

    function TEXT11_canRender()
       this.text = this.parent.TEXT1.text + this.parent.TEXT2.text
       return true


I can't try this at the moment so you may need to use


    this.text = val(this.parent.TEXT1.text) + val(this.parent.TEXT2.text)


If you want to display the sum of the calculated values on a group's
footerband things get a little more complicated.

agSum() is the "built-in" method to display totals in reports. The
problem is that agSum() method needs a codeblock as an argument.
Crafting a codeblock that will sum the value from a field is fairly
straightforward.  (An example is in the Help file.)

Crafting a codeblock that returns agSum(fieldA)*agSum(fieldB) +
agSum(fieldC)*agSum(fieldD) should be possible but it's going to be a
MONSTER.  I don't know if there is a limit on the length of a codeblock
but this would probably be a serious contender. :-)

So, to plan B which is DIY.  All it needs is three simple event handlers.

As an aside.  agSUM() makes it easy to display totals of values in
fields in reports but rounding errors can creep in where the display is
to two decimal places but the values "behind the scenes" are kept to
more than two decimal places.   This problem can be dealt with if you
DIY so it is important to learn the technique which, when you think
about it, is actually very simple.

To keep a running total as each record is rendered you need somewhere to
store the value.  Where to store running totals depends on the actual
report.  In this case a good place to store the value is in a
user-defined property of the group.  You could use a user-defined
property of the form but this would mean an extra two parents to deal
with each time.  Streamsource1 is the parent of group1 (and the
detailband) and the form is the parent of streamsource1.

The value in the user-defined property needs to be set to zero before
you render the first detailband.   A good place to do this is in the
group's headerband onRender event handler as this is triggered before
the first detailband renders.  (The headerband's preRender event handler
would work just as well.)

    function HEADERBAND_onRender
       this.parent.nTotal = 0 // initialise group1.nTotal
       return

Now we need to sum the values from TEXT1 and TEXT2 to the running total.
  The actual values for TEXT1 and TEXT2 were calculated in the canRender
event handlers for the text objects

The detailband and group1 both have streamsource1 as their parent.  Both
TEXT1 and TEXT2 are on the detailband so we use this in the detailband's
onRender event handler to save the values.


    function DETAILBAND_onRender
       //add the value in text1.text to the running total
       this.parent.group1.nTotal += this.text1.text
      //add the value in text2.text to the running total
       this.parent.group1.nTotal += this.text2.text
       return


You may need to use val(this.text1.text) and val(this.text2.text) but
try it without val() first.


After all the records for the group have been dealt with the group1
footerband will render.  If TEXT11 is on the group1.footerband to
display the total you would use its canRender event handler to give it
the total to display.  The text control's parent is the footerband and
the footerband's parent is group1

    function TEXT11_canRender
       // fetch running total for display
       this.text = this.parent.parent.nTotal
       return true



Mervyn.