| Subject |
Re: Calculated Field Question |
| From |
Mervyn Bick <invalid@invalid.invalid> |
| Date |
Mon, 28 Nov 2022 16:51:59 +0200 |
| Newsgroups |
dbase.getting-started |
On 2022/11/28 06:29, Norman Snowden wrote:
> I am trying to transfer and use the values of calculated fields ftpmt and stpmt which are generated in pushbutton1 for use in pushbutto2. The values check out OK at the end of pushbutton1, but at the beginning of pushbutton2 the values should be 997.95 and 0 but are an extraneous 5.11 and an inverted 997.95. The ftpmt and stpmt entryfields are included in the Table and data linked.
>
> The calculated fields are not shown as rows in the Table and apparently cannot be saved as I tried. They are shown on the Form as non enabled entryfields.
>
> I even tried Using m->ftpmt and m->stpmt stored as public variables temftpmt and temstprt in pushbotton1 to be retrieved for pushbutton2. This did not work, the results printed out a 0 0.
https://assets.amuniversal.com/d9b7baf032dd013bcb91005056a9545d
I'm afraid the crystal ball is a bit cloudy this morning. :-) While I
think I know what the problem is I'm having to make some assumptions.
Normally "calculated field" means a field in a rowset that is not
actually in the table. The field for the rowset is created in the
query's SELECT command or by adding a field to the fields array and then
using the field's beforeGetValue event handler to populate it. A value
is calculated from values in fields actually in the table as each record
is added to the rowset in memory. Such calculated fields are read-only
and one can't save changed values to them.
Reading between the lines (or between the clouds in the crystal ball or
simply from the fact that trying to write to read-only fields would give
an error :-) ) I assume you actually have blank fields ftpmt and stpmt
in your table and want to save values that have been calculated in your
form to these fields. If this is the case we can move on.
The notation m->ftpmt is used in XDML to distinguish between a memory
variable ftpmt and a field ftpmt in the workarea. Using workareas and
queries in the same form can be done but as it can lead to problems it
should really be avoided. I'm assuming you have not used workareas in
this form and the m->ftpmt is just "force of habit" coding. If I'm
wrong this will need to be looked at.
Now that you are using OODML you need to rethink some programming
techniques.
Memory variables have their place but you should try and limit their use
to within the function where they are used i.e declare them as LOCAL at
the top of the function. This is NOT written on tablets of stone but you
should never have problems if you stick to it except where you need to
use the & macro operator to access the contents of a variable or if you
need to check the type of a variable. Have a look at the entries for
LOCAL and PRIVATE in the help file. If you don't specifically declare
them as LOCAL they are created as PRIVATE by default.
Global variables were best avoided when programming using XDML. They
should be avoided like the plague with OODML. Just because dBASE still
makes them available doesn't mean you should use them. If you ever need
to make values available to other forms in your application rather use
user-defined properties of the _app object.
To make a calculated value accessible throughout a form save the value
to a user-defined properties of an object. Usually one would use a
user-defined property of the form but you could just as easily use the
object on the form which triggered the function that created the value.
Where you save the value affects how you retrieve the value as you need
to specify which object the property belongs to.
In this specific case you have already saved the value to the rowset and
also made an explicit save() to the table so you don't need to keep the
value elsewhere.
You code needs to look something like this.
function PUSHBUTTON1_onClick
local ftpmt, stpmt
//code to place values in ftpmt and stpmt
form.lqactsch1.rowset.fields["ftpmt"].value = ftpmt
form.lqactsch1.rowset.fields["stpmt"].value = stpmt
form.lqactsch1.rowset.SAVE()
form.ftpmt = ftpmt //assign to user-defined property of form
//if the values are only going to be saved to the table later
form.stpmt = stpmt
//alternatively assign to user-defined property of pushbutton1
this.ftpmt = ftpmt
this.stpmt = stpmt
return
function PUHBUTTON2_onClick
local ftmpt, stpmt
Clear
? form.lqactsch1.rowset.fields["ftpmt"].value
? form.lqactsch1.rowset.fields["ftpmt"].value
ftpmt = form.lqactsch1.rowset.fields["stpmt"].value
stpmt = form.lqactsch1.rowset.fields["stpmt"].value
//alternatively, if values were save to properties of form
ftpmt = form.ftpmt
stpmt = form.stpmt
//alternatively if values were saved properties of pushbutton1
ftpmt = form.pushbutton1.ftpmt
stpmt = from.pushbutton1.ftpmt
//code to process ftpmt and stpmt
return
The problem with event driven code is that the programmer has no control
over what the user does. Your code needs to take into account that the
user may click pushbutton2 before pushbutton1 in which case there won't
be values in the two fields.
function PUHBUTTON2_onClick
local ftmpt, stpmt
Clear
? form.lqactsch1.rowset.fields["ftpmt"].value
? form.lqactsch1.rowset.fields["stpmt"].value
if form.lqactsch1.rowset.fields["ftpmt"].value <> 0 and ;
form.lqactsch1.rowset.fields["stpmt"].value <> 0
//Assumes both values would not normally be 0
ftpmt = form.lqactsch1.rowset.fields["ftpmt"].value
stpmt = form.lqactsch1.rowset.fields["stpmt"].value
//code to process ftpmt and stpmt
else
msgbox('ftpmt and stpmt have not been calculated yet')
endif
return
Mervyn
|
|