Discussion:
PUBLIC Vs. LOCAL Variables
(too old to reply)
Bruce R. Roland
2008-12-04 23:12:14 UTC
Permalink
Hello All!

Hoping someone can give me some insight as to why two variables I use won't work if they are declared local but will if declared Public.

We had some discussion on the use of Public variables vs. Local over the past week or two here in the newsgroup. From that discussion I concluded that the variables I am using in most of my programs could, in fact, and should be, in fact, declared as local rather than public. Thus, I changed the declaration of these variables from public to local.

With the exception of two of my declared variables all of them work as local rather than public variables which is what I expected of all of them after the discussion on public vs. local.

The two I had to leave as public in order for the code to work should from everything I see work if declared as local - but as said they don't.

The code for the form in which these are used is laid out below. The two variables in question are only used in the form in which they are declared - nowhere else in my code.

The only thing I can reasonably come up with for this problem is that these two are used outside the CLASS even though used on the form containing the class.

Anyone have anything that may help me understand this?

Notes:

Originally only "DisplaynhtpInvoice" was declared local - all others were declared as Public.

The obvious two variables to which I refer here as giving me a problem - if it actually is a problem - are the two declared Public in the sample code below.

Thanks.

Bruce

***********************************************************
Code sample
***********************************************************

LOCAL DisplaynhtpInvoice,;
ofields,;
nID_Ref,;
cExpn_Field_Ref,;
cInvoice_Field_Ref,;
cTotal_Field_Ref,;
oInvoice_Object_Ref,;
oTotal_Object_Ref,;
cInvoice_Value,;
cExpn_Value,;
cTotal_Value,;
nCalculated_Invoice,;
nCalculated_Expenses,;
nCalculated_Wages,;
nCalculated_Total

PUBLIC cEnabled_Ref,;
cPicture_Ref

cEnabled_Ref := "_Data.ENABLED"
cPicture_Ref := "_Data.PICTURE"

DisplaynhtpInvoice = NEW DisplaynhtpInvoice()

IF (Modal)
DisplaynhtpInvoice.MDI = false
DisplaynhtpInvoice.READMODAL()
ELSE
DisplaynhtpInvoice.MAXIMIZE := false
DisplaynhtpInvoice.MINIMIZE := false
DisplaynhtpInvoice.OPEN()
ENDIF

CLASS DisplaynhtpInvoice OF Form_TemplateFORM FROM Aims.prg

//////////////////////////////////////////////////////////////////////////////////
///// Class object definitions are here//////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

FUNCTION fSet_Params_Setup

oFields = FORM.qNhtp_Invoice.ROWSET.FIELDS
oParentTree = "FORM."

cInvoice_Field_Ref := "Invoice_No_" + n

oInvoice_Object_Ref := oParentTree + "deoInvoice_No_"
oTotal_Object_REF := oParentTree + "deoTotal_Charges_"

oTotal_Object_Ref += n + cEnabled_Ref
oInvoice_Object_Ref += n + cPicture_Ref


FUNCTION fSet_Params_Onedit

FOR n = 1 TO 14

FORM.Fset_Params_Setup()

&oTotal_Object_Ref := false

&oInvoice_object_Ref := "AA-####"

NEXT

// Ensure save() fires even when no changes occur during
// edit - (ENABLED parameters reset upon the rowset being
// saved when exiting from the edit mode (rowset ONSAVE()
// is called). If no changes made MODIFIED is false and no
// save occurs, hence no reset of ENABLED parameters. By
// setting MODIFIED to true a save is forced even if no
// changes occur ensuring ENABLED parameters are reset).

FORM.qNhtp_Invoice.ROWSET.MODIFIED = true


FUNCTION fSet_Params

FOR n = 1 TO 14

FORM.Fset_Params_Setup()

&oTotal_Object_Ref := true

IF oFields[cInvoice_Field_Ref].VALUE == "" or oFields[cInvoice_Field_Ref].VALUE = NULL
&oInvoice_Object_Ref := NULL
ENDIF
NEXT

ENDCLASS

***********************************************************
End Code sample
***********************************************************
Bruce R. Roland
2008-12-05 02:33:26 UTC
Permalink
Bruce R. Roland Wrote:

Hello All again!

A follow-up to this post. It seems that as I went back after shutting DBase down and tried running this form again that it failed this time for all the variables when they were declared as local. After doing some testing I determined that since I had run the form with the variables declared as public first - when I then changed the code to make them local DBase ignored this change since they were already in memory as public. When I had shut down DBase this obviously released the variables from memory and so starting DBase up again and running the form put them into memory as local instead of public - since I had changed my code - and so all the variables became undefined.

Lesson learned - issue an explicit release for the variables when testing and closing a form.

Question still remains then as to why declaring these variables will not work when declared local.

Any one can help me understand this and what is going on?

Thanks.

Bruce
Rick Miller
2008-12-05 03:54:52 UTC
Permalink
Post by Bruce R. Roland
Question still remains then as to why declaring these variables will not work when declared local.
Any one can help me understand this and what is going on?
Thanks.
Bruce
/*
Hi Bruce,

if i understand this correctly,
The local variables declared and assigned
are not inside of the form class.
This would make the Local variables as shown
not in scope (available) to any code within
the form class.

When the ":=" assignment operator is used
without error, it means the variable being
assigned a value has already been created,
assigned a value, and in scope.
A declared variable with the same name that
has not been assigned a value is _NOT_
the variable being assigned a value.
else
me not understand.
skip the rest of this message.
endif

See help Private in the OLH.
The scope (availability) of a variable is important.

--------------------------------------------------
Here is a try at why some of the code may work.

1. There are Private or Public variables
of the same name (as the Local variables)
created prior to calling this code sample.

2. There are Private or Public variables
of the same name (as the Local variables)
created in a class function that calls to
fSet_Params_Onedit.

3. The "&" macro operator will only work
with a Private or Public variable
and there must be no Local variable in the
line that the "&" macro operator is used.

4. A variable is created Private (by default)
if it is assigned a value and a previously
created variable by the same name is not
in scope.

--------------------------------------------------
There is some sample code below to demonstrate:
1. how Local variables declared outside a
class can be used in a class.

2. how the Local variable cEnabled_Ref
(as Your code sample appears to show)
is not in scope (available)
to the class in the open method.

--------------------------------------------------
A couple ways to use outside variables in an object are:
a) assign them to an object as an object.
ie: oParams = new asscocArray()
oParams["param1"] = cParam1
oParams["param2"] = cParam2
oForm = new form()
oForm.params = oParams
the form.params object is in scope
for the duration of the form.
b) assign them to the object as a property.
ie: oForm = new form()
oForm.Param1 = cParam1
oForm.Param2 = cParam2
the form.Param1, form.Param2 properties
are in scope for the duration of the form.
c) pass them to the object's function.
ie: oForm = new form()
oForm.open(cParam1, cParam2)
the parameters are in scope for the duration
of the open method ONLY.
d) pass them to the object as a parameter.
ie: class formClass(param1, param2) of form
oForm = new formClass(cParam1, cParam2)
the param1 and param2 variables are in scope
for the duration of instantiation code ONLY.

Hope it helps,
Rick Miller
*/
Local cButton, cParam1, cParam2, cText,;
oForm, oParams
Local cEnabled_Ref
cEnabled_Ref = "_Data.ENABLED"
cText = "Hello"
cParam1 = cText + " Parameter"
cButton = "Close"
cParam2 = cButton + " Parameter"
oParams = new assocArray()
oParams["param1"] = cText + " AssocArray"
oParams["param2"] = cButton + " AssocArray"

oForm = new formClass(cText, cButton)
oForm.params = oParams
oForm.open(cParam1, cParam2)

class formClass(param1, param2) of form
with (this)
metric = 6
endwith

this.text1 = new text(this)
with (this.text1)
left = 20
top = 12
width = 156
text = "Not Defined"
endwith

this.button1 = new pushbutton(this)
with (this.button1)
onClick = {; this.form.close()}
left = 20
top = 32
width = 156
text = "Close"
endwith

try
msgbox("cText = " + param1 + chr(13) +;
"cButton = " + param2,;
"Message from instantiation", 64)
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry

function onOpen
try
msgbox("this.params[param1] = " +;
this.params["param1"] + chr(13) +;
"this.params[param2] = " +;
this.params["param2"],;
"Message from onOpen method", 64)
this.text1.text := this.params["param1"]
this.button1.text := this.params["param2"]
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return

function open(param1, param2)
try
msgbox("cParam1 = " + param1 + chr(13) +;
"cParam2 = " + param2,;
"Message from open method", 64)
this.text1.text := cEnabled_Ref
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return form::open()

endclass
Bruce R. Roland
2008-12-05 13:16:33 UTC
Permalink
Rick

Unfortunately time is against me this morning so I will need additional time to review your response. but I will try to digest this and get back to you if I have further questions RE what you say this afternoon or tonight.

Thanks

Bruce
Post by Rick Miller
Post by Bruce R. Roland
Question still remains then as to why declaring these variables will not work when declared local.
Any one can help me understand this and what is going on?
Thanks.
Bruce
/*
Hi Bruce,
if i understand this correctly,
The local variables declared and assigned
are not inside of the form class.
This would make the Local variables as shown
not in scope (available) to any code within
the form class.
When the ":=" assignment operator is used
without error, it means the variable being
assigned a value has already been created,
assigned a value, and in scope.
A declared variable with the same name that
has not been assigned a value is _NOT_
the variable being assigned a value.
else
me not understand.
skip the rest of this message.
endif
See help Private in the OLH.
The scope (availability) of a variable is important.
--------------------------------------------------
Here is a try at why some of the code may work.
1. There are Private or Public variables
of the same name (as the Local variables)
created prior to calling this code sample.
2. There are Private or Public variables
of the same name (as the Local variables)
created in a class function that calls to
fSet_Params_Onedit.
3. The "&" macro operator will only work
with a Private or Public variable
and there must be no Local variable in the
line that the "&" macro operator is used.
4. A variable is created Private (by default)
if it is assigned a value and a previously
created variable by the same name is not
in scope.
--------------------------------------------------
1. how Local variables declared outside a
class can be used in a class.
2. how the Local variable cEnabled_Ref
(as Your code sample appears to show)
is not in scope (available)
to the class in the open method.
--------------------------------------------------
a) assign them to an object as an object.
ie: oParams = new asscocArray()
oParams["param1"] = cParam1
oParams["param2"] = cParam2
oForm = new form()
oForm.params = oParams
the form.params object is in scope
for the duration of the form.
b) assign them to the object as a property.
ie: oForm = new form()
oForm.Param1 = cParam1
oForm.Param2 = cParam2
the form.Param1, form.Param2 properties
are in scope for the duration of the form.
c) pass them to the object's function.
ie: oForm = new form()
oForm.open(cParam1, cParam2)
the parameters are in scope for the duration
of the open method ONLY.
d) pass them to the object as a parameter.
ie: class formClass(param1, param2) of form
oForm = new formClass(cParam1, cParam2)
the param1 and param2 variables are in scope
for the duration of instantiation code ONLY.
Hope it helps,
Rick Miller
*/
Local cButton, cParam1, cParam2, cText,;
oForm, oParams
Local cEnabled_Ref
cEnabled_Ref = "_Data.ENABLED"
cText = "Hello"
cParam1 = cText + " Parameter"
cButton = "Close"
cParam2 = cButton + " Parameter"
oParams = new assocArray()
oParams["param1"] = cText + " AssocArray"
oParams["param2"] = cButton + " AssocArray"
oForm = new formClass(cText, cButton)
oForm.params = oParams
oForm.open(cParam1, cParam2)
class formClass(param1, param2) of form
with (this)
metric = 6
endwith
this.text1 = new text(this)
with (this.text1)
left = 20
top = 12
width = 156
text = "Not Defined"
endwith
this.button1 = new pushbutton(this)
with (this.button1)
onClick = {; this.form.close()}
left = 20
top = 32
width = 156
text = "Close"
endwith
try
msgbox("cText = " + param1 + chr(13) +;
"cButton = " + param2,;
"Message from instantiation", 64)
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
function onOpen
try
msgbox("this.params[param1] = " +;
this.params["param1"] + chr(13) +;
"this.params[param2] = " +;
this.params["param2"],;
"Message from onOpen method", 64)
this.text1.text := this.params["param1"]
this.button1.text := this.params["param2"]
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return
function open(param1, param2)
try
msgbox("cParam1 = " + param1 + chr(13) +;
"cParam2 = " + param2,;
"Message from open method", 64)
this.text1.text := cEnabled_Ref
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return form::open()
endclass
Bruce R. Roland
2008-12-05 21:38:43 UTC
Permalink
Rick
Post by Rick Miller
if i understand this correctly,
The local variables declared and assigned
are not inside of the form class.
This would make the Local variables as shown
not in scope (available) to any code within
the form class.
This is true with respect to making the variables local as I was trying to do (which obviously did not work and gave me the variable undefined error when the code got to the variables in the functions.
Post by Rick Miller
When the ":=" assignment operator is used
without error, it means the variable being
assigned a value has already been created,
assigned a value, and in scope.
This seems that it may be some of the problem as I declare the variables but do not assign values until the functions they are used in. This was done primarily because when originally writting the code and creating these variables in the functions I got the variable undefined error which was probably due to exactly what you are saying - i.e., I used the := assignment operator which made Dbase look for an already created variable to reassign the value for which did not exist and hence the error. The solution was obviously to create the variable in advance which is why I have the variables all declared public in the first place.
Post by Rick Miller
A declared variable with the same name that
has not been assigned a value is _NOT_
the variable being assigned a value.
Seems from what youy are saying this may be true but then I am confused since I had to make the declaration in order to prevent the variable undefined error so it would seem that since the error went away by doing this that the declared variable (even though it has no assigned value) would be the same variable that the variable in the function is assigning a value to (gee - I hope this makes sense the way I explained it).
Post by Rick Miller
else
me not understand.
skip the rest of this message.
endif
See help Private in the OLH.
The scope (availability) of a variable is important.
Been there and done that. I think I do have the scope and endurance of the Public, Private, and local variables pretty well down. The problem is not understanding how they work but maybe where they work (i.e. I know a Public is available to the entire app, Private to the creating routine and all sub routines, and Local to the routine in which it was created only.

The problem I think I am having is understanding maybe what represents each. I.e. A form program in my thoughts would constitute a single "routine" and so anything (variable) created there would be available to anything in that program (the form class, the functions/methods of the form class, etc.) However, this must not be the case as when I declare them as local at the beginning of the form - they are not available to the class or functions of the class in the form.

Tghus, as I said - it seems not to be my understanding of PUBLIC, Private or local so much as my understanding of what constitutes the "routine" that these are available o ( I don't know if this makes sense).
Post by Rick Miller
--------------------------------------------------
Here is a try at why some of the code may work.
1. There are Private or Public variables
of the same name (as the Local variables)
created prior to calling this code sample.
No! the variables are only used in this sample code - nowhere else!
Post by Rick Miller
2. There are Private or Public variables
of the same name (as the Local variables)
created in a class function that calls to
fSet_Params_Onedit.
Again no! the only CLASS that calls these three function is the class in the form.
Post by Rick Miller
3. The "&" macro operator will only work
with a Private or Public variable
and there must be no Local variable in the
line that the "&" macro operator is used.
This I wouild say is correct as the code does run when the variables are declared Public - the code does not run if the variables are declared Private though.
Post by Rick Miller
4. A variable is created Private (by default)
if it is assigned a value and a previously
created variable by the same name is not
in scope.
I am not sure about this as there were no previously created variables of the same name and the variable would not work until I created it Public.
Post by Rick Miller
--------------------------------------------------
1. how Local variables declared outside a
class can be used in a class.
2. how the Local variable cEnabled_Ref
(as Your code sample appears to show)
is not in scope (available)
to the class in the open method.
Sorry! you really lost me from here on down as I don't really understand it all.

Bruce
Post by Rick Miller
--------------------------------------------------
a) assign them to an object as an object.
ie: oParams = new asscocArray()
oParams["param1"] = cParam1
oParams["param2"] = cParam2
oForm = new form()
oForm.params = oParams
the form.params object is in scope
for the duration of the form.
b) assign them to the object as a property.
ie: oForm = new form()
oForm.Param1 = cParam1
oForm.Param2 = cParam2
the form.Param1, form.Param2 properties
are in scope for the duration of the form.
c) pass them to the object's function.
ie: oForm = new form()
oForm.open(cParam1, cParam2)
the parameters are in scope for the duration
of the open method ONLY.
d) pass them to the object as a parameter.
ie: class formClass(param1, param2) of form
oForm = new formClass(cParam1, cParam2)
the param1 and param2 variables are in scope
for the duration of instantiation code ONLY.
Hope it helps,
Rick Miller
*/
Local cButton, cParam1, cParam2, cText,;
oForm, oParams
Local cEnabled_Ref
cEnabled_Ref = "_Data.ENABLED"
cText = "Hello"
cParam1 = cText + " Parameter"
cButton = "Close"
cParam2 = cButton + " Parameter"
oParams = new assocArray()
oParams["param1"] = cText + " AssocArray"
oParams["param2"] = cButton + " AssocArray"
oForm = new formClass(cText, cButton)
oForm.params = oParams
oForm.open(cParam1, cParam2)
class formClass(param1, param2) of form
with (this)
metric = 6
endwith
this.text1 = new text(this)
with (this.text1)
left = 20
top = 12
width = 156
text = "Not Defined"
endwith
this.button1 = new pushbutton(this)
with (this.button1)
onClick = {; this.form.close()}
left = 20
top = 32
width = 156
text = "Close"
endwith
try
msgbox("cText = " + param1 + chr(13) +;
"cButton = " + param2,;
"Message from instantiation", 64)
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
function onOpen
try
msgbox("this.params[param1] = " +;
this.params["param1"] + chr(13) +;
"this.params[param2] = " +;
this.params["param2"],;
"Message from onOpen method", 64)
this.text1.text := this.params["param1"]
this.button1.text := this.params["param2"]
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return
function open(param1, param2)
try
msgbox("cParam1 = " + param1 + chr(13) +;
"cParam2 = " + param2,;
"Message from open method", 64)
this.text1.text := cEnabled_Ref
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return form::open()
endclass
Rick Miller
2008-12-07 03:09:43 UTC
Permalink
Bruce there are a couple in line comments,
Post by Bruce R. Roland
Rick
Post by Rick Miller
if i understand this correctly,
The local variables declared and assigned
are not inside of the form class.
This would make the Local variables as shown
not in scope (available) to any code within
the form class.
This is true with respect to making the variables local as I was trying to do (which obviously did not work and gave me the variable undefined error when the code got to the variables in the functions.
Post by Rick Miller
When the ":=" assignment operator is used
without error, it means the variable being
assigned a value has already been created,
assigned a value, and in scope.
This seems that it may be some of the problem as I declare the variables but do not assign values until the functions they are used in. This was done primarily because when originally writting the code and creating these variables in the functions I got the variable undefined error which was probably due to exactly what you are saying - i.e., I used the := assignment operator which made Dbase look for an already created variable to reassign the value for which did not exist and hence the error. The solution was obviously to create the variable in advance which is why I have the variables all declared public in the first place.
Post by Rick Miller
A declared variable with the same name that
has not been assigned a value is _NOT_
the variable being assigned a value.
Seems from what youy are saying this may be true but then I am confused since I had to make the declaration in order to prevent the variable undefined error so it would seem that since the error went away by doing this that the declared variable (even though it has no assigned value) would be the same variable that the variable in the function is assigning a value to (gee - I hope this makes sense the way I explained it).
Post by Rick Miller
else
me not understand.
skip the rest of this message.
endif
See help Private in the OLH.
The scope (availability) of a variable is important.
Been there and done that. I think I do have the scope and endurance of the Public, Private, and local variables pretty well down. The problem is not understanding how they work but maybe where they work (i.e. I know a Public is available to the entire app, Private to the creating routine and all sub routines, and Local to the routine in which it was created only.
The problem I think I am having is understanding maybe what represents each. I.e. A form program in my thoughts would constitute a single "routine" and so anything (variable) created there would be available to anything in that program (the form class, the functions/methods of the form class, etc.) However, this must not be the case as when I declare them as local at the beginning of the form - they are not available to the class or functions of the class in the form.
----

Yes this seems to be the problem.

The beginning of the form starts with the
line containing class whateverForm of form
not the first line in the file.

Using what You said, each of the 3 below
might be considered a separate routine
within the file.

#1 The top area of the file above the class line
includes the header and bootstrap code.

#2 The constructor code of a form is the
area from the class line to the first
function line.

#3 Each function within the class.
This is the area from a function line
to either the next function line, return
line, or the endclass line.

Creating an object in #1 with a line having
new () does _NOT_ make #2 or #3 a sub-routine of #1.
Post by Bruce R. Roland
Tghus, as I said - it seems not to be my understanding of PUBLIC, Private or local so much as my understanding of what constitutes the "routine" that these are available o ( I don't know if this makes sense).
----

Yes, the scope of variables that are Public, Private,
and Local seem to be understood.

A line like
oForm = new form()
in a routine does _NOT_ make all portions of the
file from class to endclass a sub-routine.
Post by Bruce R. Roland
Sorry! you really lost me from here on down as I don't really understand it all.
----

Did not mean to confuse with the sample code.

The sample code was meant to display:
1) the variable cEnabled_Ref from #1 is
not in scope in #3 with the line
this.text1.text := cEnabled_Ref
2) a way to use a variable from #1 in #2 by:
passing the variables as parameters with the line
oForm = new formClass(cText, cButton)
3) a way to use an object from #1 in #2 and #3 by:
copying an object (oParams) to a new child object
(form.params) of the form with the line
oForm.params = oParams
4) a way to use a variable from #1 in #3 by:
passing the variables as parameters with the line
oForm.open(cParam1, cParam2)
Post by Bruce R. Roland
Bruce
Post by Rick Miller
--------------------------------------------------
a) assign them to an object as an object.
ie: oParams = new asscocArray()
oParams["param1"] = cParam1
oParams["param2"] = cParam2
oForm = new form()
oForm.params = oParams
the form.params object is in scope
for the duration of the form.
b) assign them to the object as a property.
ie: oForm = new form()
oForm.Param1 = cParam1
oForm.Param2 = cParam2
the form.Param1, form.Param2 properties
are in scope for the duration of the form.
c) pass them to the object's function.
ie: oForm = new form()
oForm.open(cParam1, cParam2)
the parameters are in scope for the duration
of the open method ONLY.
d) pass them to the object as a parameter.
ie: class formClass(param1, param2) of form
oForm = new formClass(cParam1, cParam2)
the param1 and param2 variables are in scope
for the duration of instantiation code ONLY.
*/
Local cButton, cParam1, cParam2, cText,;
oForm, oParams
Local cEnabled_Ref
cEnabled_Ref = "_Data.ENABLED"
cText = "Hello"
cParam1 = cText + " Parameter"
cButton = "Close"
cParam2 = cButton + " Parameter"
oParams = new assocArray()
oParams["param1"] = cText + " AssocArray"
oParams["param2"] = cButton + " AssocArray"
oForm = new formClass(cText, cButton)
oForm.params = oParams
oForm.open(cParam1, cParam2)
class formClass(param1, param2) of form
with (this)
metric = 6
endwith
this.text1 = new text(this)
with (this.text1)
left = 20
top = 12
width = 156
text = "Not Defined"
endwith
this.button1 = new pushbutton(this)
with (this.button1)
onClick = {; this.form.close()}
left = 20
top = 32
width = 156
text = "Close"
endwith
try
msgbox("cText = " + param1 + chr(13) +;
"cButton = " + param2,;
"Message from instantiation", 64)
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
function onOpen
try
msgbox("this.params[param1] = " +;
this.params["param1"] + chr(13) +;
"this.params[param2] = " +;
this.params["param2"],;
"Message from onOpen method", 64)
this.text1.text := this.params["param1"]
this.button1.text := this.params["param2"]
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return
function open(param1, param2)
try
msgbox("cParam1 = " + param1 + chr(13) +;
"cParam2 = " + param2,;
"Message from open method", 64)
this.text1.text := cEnabled_Ref
catch(exception e)
msgbox(e.message + chr(13) +;
"At line " + e.lineNo,;
"Error Message", 16)
endtry
return form::open()
endclass
----

Hope something here was usefull,
Rick Miller
Bruce R. Roland
2008-12-07 20:54:22 UTC
Permalink
Rick
Post by Rick Miller
Yes this seems to be the problem.
The beginning of the form starts with the
line containing class whateverForm of form
not the first line in the file.
Using what You said, each of the 3 below
might be considered a separate routine
within the file.
#1 The top area of the file above the class line
includes the header and bootstrap code.
#2 The constructor code of a form is the
area from the class line to the first
function line.
#3 Each function within the class.
This is the area from a function line
to either the next function line, return
line, or the endclass line.
Creating an object in #1 with a line having
new () does _NOT_ make #2 or #3 a sub-routine of #1.
This is different from DOS in that if it was in the file in DOS it was a part of the program - end of story. Not so in OOP as you pointed out each file has the three components which are not subject to each other as an old DOS man might think. Your explanation helps.
Post by Rick Miller
Did not mean to confuse with the sample code.
1) the variable cEnabled_Ref from #1 is
not in scope in #3 with the line
this.text1.text := cEnabled_Ref
passing the variables as parameters with the line
oForm = new formClass(cText, cButton)
copying an object (oParams) to a new child object
(form.params) of the form with the line
oForm.params = oParams
passing the variables as parameters with the line
oForm.open(cParam1, cParam2)
After sitting a little while longer and viewing what you posted it did begin to make more sense - I think it will just be a matter of time to be able to piece it all together better - but I am seeing what you were trying to get across better.

I have never used arrays in my code before but I am seeing a little on what they do and the use they may be. I am reviewing some of the materials from the DB bulletin and the knowledge base and we'll see how these help - but for now I think I just need to bide some time till I get a little more under my belt.

Thnks

Bruce
Rainald
2008-12-05 05:30:02 UTC
Permalink
Post by Bruce R. Roland
A follow-up to this post. It seems that as I went back after
shutting DBase down and tried running this form again that it
failed this time for all the variables when they were declared as
local.
This does not take wonder.
Once a routine finishes, all PRIVATEs are gone.
And all LOCALs too (which is the main thing about them: They exist just
as long as the routine which created them).

In so far I'd suggest to read in the "Language Reference" under the
keywords "PUBLIC", "PRIVATE" and "LOCAL".
When done and questions remain, pls ask them.
Post by Bruce R. Roland
After doing some testing I determined that since I had run
the form with the variables declared as public first - when I then
changed the code to make them local DBase ignored this change since
they were already in memory as public.
Why wonder?
That's just the way PUBLICs work:
They are "globally" available which just means: Everywhere.
Post by Bruce R. Roland
When I had shut down DBase
this obviously released the variables from memory
Right!
Post by Bruce R. Roland
and so starting
DBase up again and running the form put them into memory as local
instead of public - since I had changed my code - and so all the
variables became undefined.
That's just the way it works.
The variables (MemVars) could not be seen by the system as they were
just no existing anymore (gone Nirvana).
Post by Bruce R. Roland
Lesson learned - issue an explicit release for the variables when
testing and closing a form.
Only needed when PUBLICs are used!
And that's exactly why Geoff and Me had raised this topic in your
original thread!

No PRIVATE or LOCAL variable which was created inside a FORM will
survive when a FORM is closed.
Post by Bruce R. Roland
Question still remains then as to why declaring these variables
will not work when declared local.
Very easy:
Any variable declared as LOCAL will only be available (in scope) in the
routine where it was created.
A variable declared as PRIVATE will also be in scope (be seen) in any
routine (procedure/function/program) called from the routine which
created it.
*Both* will not be seen on any level *above* (and therefore not in any
routine called from elsewhere).

And that is what it's all about.
PUBLICs (global variables) are seen *everywhere*.
And this causes the worst troubles thinkable.

HTH
Rainald
Bruce R. Roland
2008-12-05 13:12:35 UTC
Permalink
Rainald
Post by Rainald
This does not take wonder.
Once a routine finishes, all PRIVATEs are gone.
And all LOCALs too (which is the main thing about them: They exist just
as long as the routine which created them).
I do understand his.
Post by Rainald
In so far I'd suggest to read in the "Language Reference" under the
keywords "PUBLIC", "PRIVATE" and "LOCAL".
When done and questions remain, pls ask them.
I had read this and understand the way in which the LR says they are to work. I guess what seems odd to me is that when I declared the variables as public it placed them in memory (expected) but when I ended my code they did not release from DBase itself - i.e., when I started my code again the variables were still in memory as ppublic and so even though I had changed my code to declare the variables as local DBase still saaw them as public which threw me off.

Naturally, the solution is to release the variables when I end my code running (in my Form.close() Function I would think) but as of yet I still have not got this release working in my code yet and will have to try working on this yet.

For now simply issuing a release all in the command window before running my code will work.
Post by Rainald
Post by Bruce R. Roland
When I had shut down DBase
this obviously released the variables from memory
The variables (MemVars) could not be seen by the system as they were
just no existing anymore (gone Nirvana).
This I understood as well.
Post by Rainald
No PRIVATE or LOCAL variable which was created inside a FORM will
survive when a FORM is closed.
Any variable declared as LOCAL will only be available (in scope) in the
routine where it was created.
A variable declared as PRIVATE will also be in scope (be seen) in any
routine (procedure/function/program) called from the routine which
created it.
This is confusing to me not from understanding what it is but from the results I am getting when using Private. It seems from your statement above that a variable declared as private should be seen by the routine creating it (in this case a form - program) but that didn't seem to work for me as when I declared these variables as private I would have thought they would be available to the form and all of its functions. Yet I got the variable undefined error when the code got to the functions where I actually use the variable. Thus, it seems like I am still not getting the correct use or place for declaring these variables.
Post by Rainald
*Both* will not be seen on any level *above* (and therefore not in any
routine called from elsewhere).
And that is what it's all about.
PUBLICs (global variables) are seen *everywhere*.
And this causes the worst troubles thinkable.
And this is exactly why I am so interested in getting either local or private to work.

Bruce
Geoff Wass [dBVIPS]
2008-12-06 05:19:39 UTC
Permalink
Post by Rainald
Rainald
Post by Rainald
This does not take wonder.
Once a routine finishes, all PRIVATEs are gone.
And all LOCALs too (which is the main thing about them: They exist just
as long as the routine which created them).
I do understand his.
Post by Rainald
In so far I'd suggest to read in the "Language Reference" under the
keywords "PUBLIC", "PRIVATE" and "LOCAL".
When done and questions remain, pls ask them.
I had read this and understand the way in which the LR says they are to work. I guess what seems odd to me is that when I declared the variables as public it placed them in memory (expected) but when I ended my code they did not
release from DBase itself - i.e., when I started my code again the variables were still in memory as ppublic and so even though I had changed my code to declare the variables as local DBase still saaw them as public which threw me
off.
Post by Rainald
Naturally, the solution is to release the variables when I end my code running (in my Form.close() Function I would think) but as of yet I still have not got this release working in my code yet and will have to try working on
this yet.
Post by Rainald
For now simply issuing a release all in the command window before running my code will work.
Post by Rainald
Post by Bruce R. Roland
When I had shut down DBase
this obviously released the variables from memory
The variables (MemVars) could not be seen by the system as they were
just no existing anymore (gone Nirvana).
This I understood as well.
Post by Rainald
No PRIVATE or LOCAL variable which was created inside a FORM will
survive when a FORM is closed.
Any variable declared as LOCAL will only be available (in scope) in the
routine where it was created.
A variable declared as PRIVATE will also be in scope (be seen) in any
routine (procedure/function/program) called from the routine which
created it.
This is confusing to me not from understanding what it is but from the results I am getting when using Private. It seems from your statement above that a variable declared as private should be seen by the routine creating it (in
this case a form - program) but that didn't seem to work for me as when I declared these variables as private I would have thought they would be available to the form and all of its functions. Yet I got the variable undefined
error when the code got to the functions where I actually use the variable. Thus, it seems like I am still not getting the correct use or place for declaring these variables.
Post by Rainald
Post by Rainald
*Both* will not be seen on any level *above* (and therefore not in any
routine called from elsewhere).
And that is what it's all about.
PUBLICs (global variables) are seen *everywhere*.
And this causes the worst troubles thinkable.
And this is exactly why I am so interested in getting either local or private to work.
Bruce
Bruce,

With PRIVATE variables, they are in scope (accessible, visible, useable,
whatever you want to say) in the function where they created AND in any
function it calls (and any function those functions call and so forth).
So, PRIVATES can be available to a lot of functions, but not necessarily
all.

There is one exception. If one of the functions declares a PRIVATE
variable with the SAME name, the new variable will take precedence and
break the chain of visibility of the first one. If a function is called
from the one which creates the second variable, that function will
"see" the second version of the variable, not the one created higher up.

It is not often that you should use PRIVATE variables like this, if
ever. It can be confusing code to look at, especially when you come back
to it months later wanting to fix it.
--
Geoff Wass [dBVIPS]
Montréal, Québec, Canada

.|.|.| dBASE info at http://geocities.com/geoff_wass |.|.|.
.|.|.| ---------------------------------------------------------- |.|.|.
.|.|.| IT Consultant http://Geoff_Wass.com |.|.|.
Bruce R. Roland
2008-12-07 20:39:55 UTC
Permalink
Geoff
Post by Geoff Wass [dBVIPS]
With PRIVATE variables, they are in scope (accessible, visible, useable,
whatever you want to say) in the function where they created AND in any
function it calls (and any function those functions call and so forth).
So, PRIVATES can be available to a lot of functions, but not necessarily
all.
This is not so diffwerent from what it was in DBase for DOS that I can see - so I have not had too much problems with this as far as understanding the "higharchy" of variables. My problem is in making the change to OOP getting the hang of using variables in an "encapsulated" way. That is to say, In DOS you could declare a variable pretty much anywhere and it would be available to just about anything - within the rules of Public, Privale, etc.

As you probably noted from my posted code this is what I was doing now as well. However, as was pointed out this makes messy encapsulation and has the potential for problems.

The one drawback I see to the encapsulation of variables at this time is that variables must be declared in the function which uses them and so if used in multiple functions must be declared multiple times. This obviously adds duplicate lines of code in several spots which is something which would be nice to avoid since it would reduce the amount of file space used - which in the DOS days was important though it is not such an issue anymore.

The only way around this in OOP would be to declare the variables in the application but if they are used only by some of the programs and not all then having them clutter up the application is not a good idea and would be confusing at best - (What is this variable for anyway?)

So I guess you just have to do what you have to do and have the extra lines which in DOS could have been consolidated better I believe.
Post by Geoff Wass [dBVIPS]
There is one exception. If one of the functions declares a PRIVATE
variable with the SAME name, the new variable will take precedence and
break the chain of visibility of the first one. If a function is called
from the one which creates the second variable, that function will
"see" the second version of the variable, not the one created higher up.
This again was basically the same in DOS except that I don't recall that you could have two variables with the same name - I thought that declaring the new one simply overwrote the old one - but that's neither here notr there in OOP.
Post by Geoff Wass [dBVIPS]
It is not often that you should use PRIVATE variables like this, if
ever. It can be confusing code to look at, especially when you come back
to it months later wanting to fix it.
This makes obvious sense since you may well be looking at the original value given to the name rather than the superceded value which would make anyone's head spin until they figured it out.

Bruce
Michael Nuwer
2008-12-07 21:03:02 UTC
Permalink
Post by Bruce R. Roland
The one drawback I see to the encapsulation of variables at this time is that variables must be declared in the function which uses them and so if used in multiple functions must be declared multiple times. This obviously adds duplicate lines of code in several spots which is something which would be nice to avoid since it would reduce the amount of file space used - which in the DOS days was important though it is not such an issue anymore.
Bruce,

In the case where you want data available for multiple methods (aka functions),
use object properties. In the example below, the form object contains three
functions, each of which are fired by pushbuttons. Each of the functions shares a
custom form-property. I named it "myFormProperty" and attached it to the form when
the form is opened. Properties are alot like variables and, in OOP, should be used
as much as possible in place of variables.


** END HEADER -- do not remove this line
//
// Generated on 12/07/2008
//
parameter bModal
local f
f = new PropertyDemoForm()
if (bModal)
f.mdi = false // ensure not MDI
f.readModal()
else
f.open()
endif

class PropertyDemoForm of FORM
with (this)
onOpen = class::FORM_ONOPEN
height = 12.0
left = 66.7143
top = 0.7273
width = 28.5714
text = ""
endwith

this.PUSHBUTTON1 = new PUSHBUTTON(this)
with (this.PUSHBUTTON1)
onClick = class::PUSHBUTTON1_ONCLICK
height = 1.0909
left = 7.0
top = 4.0
width = 15.2857
text = "Click One"
endwith

this.PUSHBUTTON2 = new PUSHBUTTON(this)
with (this.PUSHBUTTON2)
onClick = class::PUSHBUTTON2_ONCLICK
height = 1.0909
left = 7.0
top = 5.5
width = 15.2857
text = "Click Two"
endwith

this.PUSHBUTTON3 = new PUSHBUTTON(this)
with (this.PUSHBUTTON3)
onClick = class::PUSHBUTTON3_ONCLICK
height = 1.0909
left = 7.0
top = 7.0
width = 15.2857
text = "Click Three"
endwith

this.ENTRYFIELD1 = new ENTRYFIELD(this)
with (this.ENTRYFIELD1)
height = 1.0
left = 7.0
top = 1.5
width = 14.0
value = "Entryfield1"
endwith


function PUSHBUTTON1_onClick
local n
n = 1
form.myFormProperty += n
form.entryField1.value = form.myFormProperty
return

function PUSHBUTTON2_onClick
local n
n = 2
form.myFormProperty += n
form.entryField1.value = form.myFormProperty
return

function PUSHBUTTON3_onClick
local n
n = 3
form.myFormProperty += n
form.entryField1.value = form.myFormProperty
return

function form_onOpen
this.myFormProperty = 1
this.entryField1.value = this.myFormProperty
return

endclass
Geoff Wass [dBVIPS]
2008-12-08 05:52:51 UTC
Permalink
Bruce,

I see Michael has explained how to use properties which all functions
within the class can see at all times.

Do not worry about making an extra line or two of code here and there.
It is often unavoidable. Even when it is avoidable, it is often good
programming practice to declare and initialize your variables. The idea
is too keep things simple as possible, but also as clear as possible.
You should be able to go to any random function and it should be clear
where all variables are coming from.
--
Geoff Wass [dBVIPS]
Montréal, Québec, Canada

.|.|.| dBASE info at http://geocities.com/geoff_wass |.|.|.
.|.|.| ---------------------------------------------------------- |.|.|.
.|.|.| IT Consultant http://Geoff_Wass.com |.|.|.
Bruce R. Roland
2008-12-08 20:25:29 UTC
Permalink
Geoff
Post by Geoff Wass [dBVIPS]
I see Michael has explained how to use properties which all functions
within the class can see at all times.
I don't know if I responded to Michael or not last night - I had tried to but occassionally I get knocked off the newsgroup - presumably by my IP - and I don't know if I took the time to retype and post a response to him.

At any rate - from what Michael was saying and the code he gave as an example it seems I am probably alreeady using properties to some degree and just not realizing it. It seems to me the way he used the properties in his sample code was not all that different from what my code is ending up to be.
Post by Geoff Wass [dBVIPS]
Do not worry about making an extra line or two of code here and there.
It is often unavoidable. Even when it is avoidable, it is often good
programming practice to declare and initialize your variables. The idea
is too keep things simple as possible, but also as clear as possible.
You should be able to go to any random function and it should be clear
where all variables are coming from.
I know what you mean about keeping things clear and there are several things I do in my code that work great to help in this. One I have found particularly usefule is to add a comment after every ENDWITH - ENDIF, etc. which references the WITH - IF statement for which the ENDWITH - ENDIF is associated. This really helps in long blocks to clearly know where the one I am looking at begins and ends - especially if there are others imbedded within.

I guess the real trouble I have - or maybe it is not such a problem but simply part of the code development process - is that I tend to write code at the start in an unconsolidated and lengthy manner. Afterwards I find as I work with it further I can almost always find code which can be consolidated into a neater and more direct code. This often pares a lot of lines out of my code and makes my programs more consise even though sometimes the longer version is easier to follow. The problem sometimes is to know where to leave well enough alone and stop consolidation. If I am like most coders I am sure I will forever be trying to improve and consolidate my code so it is smaller and better till the day I die.

Bruce
Geoff Wass [dBVIPS]
2008-12-09 05:47:50 UTC
Permalink
Post by Bruce R. Roland
Geoff
Post by Geoff Wass [dBVIPS]
I see Michael has explained how to use properties which all functions
within the class can see at all times.
I don't know if I responded to Michael or not last night - I had tried to but occassionally I get knocked off the newsgroup - presumably by my IP - and I don't know if I took the time to retype and post a response to him.
At any rate - from what Michael was saying and the code he gave as an example it seems I am probably alreeady using properties to some degree and just not realizing it. It seems to me the way he used the properties in his sample
code was not all that different from what my code is ending up to be.

That's good to hear. Eventually all of it will become instinctive. :-)
Post by Bruce R. Roland
Post by Geoff Wass [dBVIPS]
Do not worry about making an extra line or two of code here and there.
It is often unavoidable. Even when it is avoidable, it is often good
programming practice to declare and initialize your variables. The idea
is too keep things simple as possible, but also as clear as possible.
You should be able to go to any random function and it should be clear
where all variables are coming from.
I know what you mean about keeping things clear and there are several things I do in my code that work great to help in this. One I have found particularly usefule is to add a comment after every ENDWITH - ENDIF, etc. which
references the WITH - IF statement for which the ENDWITH - ENDIF is associated. This really helps in long blocks to clearly know where the one I am looking at begins and ends - especially if there are others imbedded within.

That is a good idea. Some people do that with loops, too.
Post by Bruce R. Roland
I guess the real trouble I have - or maybe it is not such a problem but simply part of the code development process - is that I tend to write code at the start in an unconsolidated and lengthy manner. Afterwards I find as I work
with it further I can almost always find code which can be consolidated into a neater and more direct code. This often pares a lot of lines out of my code and makes my programs more consise even though sometimes the longer version
is easier to follow. The problem sometimes is to know where to leave well enough alone and stop consolidation. If I am like most coders I am sure I will forever be trying to improve and consolidate my code so it is smaller and
better till the day I die.

This is entirely normal. What you are doing is called "refactoring". It
is good to get something working and then to refactor it. While
refactoring, not only will you make the code more manageable, but you
will probably find little things that you could do better and make the
program run faster.
--
Geoff Wass [dBVIPS]
Montréal, Québec, Canada

.|.|.| dBASE info at http://geocities.com/geoff_wass |.|.|.
.|.|.| ---------------------------------------------------------- |.|.|.
.|.|.| IT Consultant http://Geoff_Wass.com |.|.|.
Bruce R. Roland
2008-12-09 19:30:25 UTC
Permalink
Geoff
Post by Geoff Wass [dBVIPS]
This is entirely normal. What you are doing is called "refactoring". It
is good to get something working and then to refactor it. While
refactoring, not only will you make the code more manageable, but you
will probably find little things that you could do better and make the
program run faster.
I guess what really gets me is that I can seem to be so dense at times - then the answer you are looking for just up and slaps you in the face.

For example I had been looking for a way to put returns in a msgbox so I could format it better and had been struggling with that for a little. Then here comes Ken and asks about a piece of code he has regarding a save routine I believe it was. As I am reviewing that code I see "+ CHR(13) +" in his msgbox and am wondering what that character means as I have seen this in several different codes in these posts and elsewhere - when suddenly it hits me - duh - the code for return!!!

Sometimes you just feel stupid - or is this one of those senior moments? Priceless anyway!

Thanks to Ken I guess for having a problem - though I am sure he would have preferred helping me on this given the chance without the problem!

I guess the only good thing about this is to see a couple of Ken's recent posts from the standpoint that it makes me feel not so bad about having problems when I see even the DB Bigwigs/VIPS having problems also - not that I wish them to have problems but only that I makes me realize how much there is to learn and for a lack of better term - go wrong?!

Bruce
Post by Geoff Wass [dBVIPS]
--
Geoff Wass [dBVIPS]
Montréal, Québec, Canada
.|.|.| dBASE info at http://geocities.com/geoff_wass |.|.|.
.|.|.| ---------------------------------------------------------- |.|.|.
.|.|.| IT Consultant http://Geoff_Wass.com |.|.|.
Ken Mayer [dBVIPS]
2008-12-09 22:55:05 UTC
Permalink
Post by Bruce R. Roland
I guess the only good thing about this is to see a couple of Ken's recent posts from the standpoint that it makes me feel not so bad about having problems when I see even the DB Bigwigs/VIPS having problems also - not that I wish them to have problems but only that I makes me realize how much there is to learn and for a lack of better term - go wrong?!
Heck, we all (or at least most of us) need a bit of help from time to
time, in some cases just to remind ourselves about things we already
know ... but sometimes we find weird things that someone else has
already worked around or figured out, and there's no need to fumble on
your own if someone else can help.

Ken
--
/(Opinions expressed are purely my own, not those of dataBased
Intelligence, Inc.)/

*Ken Mayer* [dBVIPS]
/Golden Stag Productions/
dBASE at goldenstag dot net
http://www.goldenstag.net/GSP
http://www.goldenstag.net/dbase/dBASEBooks.htm
http://www.goldenstag.net/dbase
Bruce R. Roland
2008-12-05 03:33:59 UTC
Permalink
Michael
help local
"You cannot use a local variable for macro substitution with the & operator.
Again, you must copy it to a private (or public) variable first."
Hmmm..! This would mean that if the variables were declared as either Private or Public then they should work I would think. However, I just went back and tried them as private and got the variable undefined error again - same as I got when declaring them local. So I must be missing something here - but I am not sure what.

Please see my second post on this subject also RE: releasing the variables from memory. when I did this it made all my variables become undefined. the only thing I have found so far is that they work only when declared as public. But with the discussion which took place re: public vs. local variable declearations I was under the impression that declaring them as local should work as well - which it does not. Therefore I am either confused as to what was being said regarding the use of local vs. public declarations for variables or there is something else going on here I am not comprehending.

It would be nice to understand this better.

Bruce
Michael Nuwer
2008-12-05 03:53:08 UTC
Permalink
Post by Bruce R. Roland
It would be nice to understand this better.
Here is something that might help:

http://www.dbase.com/Knowledgebase/v5_docs/FORMVARS.txt
Rick Miller
2008-12-05 04:13:36 UTC
Permalink
Post by Michael Nuwer
Post by Bruce R. Roland
It would be nice to understand this better.
http://www.dbase.com/Knowledgebase/v5_docs/FORMVARS.txt
----
Hi Mike,

Thanks, was looking for that link.

Has the snow inundated You and Yours ?
It has a good start here.

Rick Miller
Michael Nuwer
2008-12-05 15:17:28 UTC
Permalink
Hi Rick,

It's good to hear from you. We haven't had any of the white stuff yet, which is
odd because we typically get your whether a day or two after you get it.

Hope your holidays are festive.

Mike
Post by Rick Miller
----
Hi Mike,
Thanks, was looking for that link.
Has the snow inundated You and Yours ?
It has a good start here.
Rick Miller
Rick Miller
2008-12-07 03:26:52 UTC
Permalink
Post by Michael Nuwer
Hi Rick,
It's good to hear from you. We haven't had any of the white stuff yet,
which is odd because we typically get your whether a day or two after
you get it.
Hope your holidays are festive.
----

Your turn for the white stuff will no doubt arrive soon <g>.

Yes, the white stuff has really perked everyone up
and started all the old and new versions of holiday
songs playing again.

Happy Holidays,
Rick Miller
Bruce R. Roland
2008-12-07 20:19:09 UTC
Permalink
Rick
Post by Rick Miller
Your turn for the white stuff will no doubt arrive soon <g>.
Yes, the white stuff has really perked everyone up
and started all the old and new versions of holiday
songs playing again.
Happy Holidays,
Rick Miller
I am not sure where you are that you are refering to the white stuff.

Depending on who you ask around these parts the proper name for the white stuff is referred to as a four letter word - usually "@&*#".

We have had 25 + inches in November and in 6 days of december several inches more!

And I am enjoying it all!!

Happy holiodays back at you!

Bruce
Rick Miller
2008-12-08 15:27:53 UTC
Permalink
Post by Bruce R. Roland
I am not sure where you are that you are refering to the white stuff.
----

Eau Claire, Wisconsin USA 54701

Where are You ?
----

Some here think the same <smile>.
Post by Bruce R. Roland
We have had 25 + inches in November and in 6 days of december several inches more!
And I am enjoying it all!!
----

You have a little more stamina than me <g>.
Post by Bruce R. Roland
Happy holiodays back at you!
----
Thank You.

Happy Holidays,
Rick Miller
Bruce R. Roland
2008-12-08 20:01:19 UTC
Permalink
Rick

Here is Erie, PA USA (More commonly known as Dreary Erie). While you are farther north I believe I would guess you are west of the great lakes as well so whereas we get the "Lake effect snow" you may not - unless you are somewhat south of Lake Superior which may affect you. Anyway I like the outdoors (Hunt and fish a lot) so I have just learned how to keep warm out in the cold all day and to enjoy it. You can either fight it or make the best of it.

Bruce
Rick Miller
2008-12-08 21:35:53 UTC
Permalink
Post by Bruce R. Roland
Rick
Here is Erie, PA USA (More commonly known as Dreary Erie). While you are farther north I believe I would guess you are west of the great lakes as well so whereas we get the "Lake effect snow" you may not - unless you are somewhat south of Lake Superior which may affect you. Anyway I like the outdoors (Hunt and fish a lot) so I have just learned how to keep warm out in the cold all day and to enjoy it. You can either fight it or make the best of it.
----

Ah so (Lake effect).
We are too far south (150 miles) of Lake Superior for that.

Gun deer hunting is winding up here.
Didn't fight the temp, just started a little fire
in the woods for lunch meal and warmed up at the time.
Was fishing done the shore from You at Oak Harbor, Ohio
back in May.

Rick Miller
Bruce R. Roland
2008-12-09 03:53:21 UTC
Permalink
Rick
Post by Rick Miller
Gun deer hunting is winding up here.
Didn't fight the temp, just started a little fire
in the woods for lunch meal and warmed up at the time.
Was fishing done the shore from You at Oak Harbor, Ohio
back in May.
Last week of Gun Deer here in PA. Only two weeks altogether. Got a petite little 7-point First Monday of season (Monday Last).

I am spoiled I guess. Don't fish April through August - too hot and fish too small. Start at end of August and fish for Steelhead through mid April usually. Any time you can catch one fish and it is big enough to feed four people, the dog and still have left overs .. Well! Hard to catch one under 22" until March - then gets hard to catch one over 20 ". Loads of fun!

BRuce
Rainald
2008-12-05 04:24:34 UTC
Permalink
Post by Michael Nuwer
Post by Bruce R. Roland
It would be nice to understand this better.
http://www.dbase.com/Knowledgebase/v5_docs/FORMVARS.txt
Thanks a lot, Michael!

I was just on my way to put together a list of the valuables for former
dBDOS people (better say: for Bruce);
FORMVARS was on top, OOP.how the second one.

Great to see that you go along the same lines!!

Rainald
P.S. Ins't really strange that these valuables are not being referenced
anymore?
They are still available but only "under the hood".
dBWin / VdB 5.x HOWs and Texts
http://www.dbase.com/Knowledgebase/v5_docs/
(not accessible directly)
P.PS. I finished my list - FWIW (for the lurkers):
ARRAY1.txt
http://www.dbase.com/Knowledgebase/v5_docs/ARRAY1.txt

ARRAY2.txt
http://www.dbase.com/Knowledgebase/v5_docs/ARRAY2.txt

BUFFER.txt
http://www.dbase.com/Knowledgebase/v5_docs/BUFFER.txt

CLASS.txt
http://www.dbase.com/Knowledgebase/v5_docs/CLASS.txt

CUSTCLAS.txt
http://www.dbase.com/Knowledgebase/v5_docs/CUSTCLAS.txt

CUSTFORM.txt
http://www.dbase.com/Knowledgebase/v5_docs/CUSTFORM.txt

FAX.txt
http://www.dbase.com/Knowledgebase/v5_docs/FAX.txt

FILLFORM.txt
http://www.dbase.com/Knowledgebase/v5_docs/FILLFORM.txt

FORMVARS.txt
http://www.dbase.com/Knowledgebase/v5_docs/FORMVARS.txt

GLOSSARY.txt
http://www.dbase.com/Knowledgebase/v5_docs/GLOSSARY.txt

INDEX.txt
http://www.dbase.com/Knowledgebase/v5_docs/INDEX.txt

Kiuchics.txt
http://www.dbase.com/Knowledgebase/v5_docs/Kiuchics.txt

LOWLEVEL.txt
http://www.dbase.com/Knowledgebase/v5_docs/LOWLEVEL.txt

LPTPRN.txt
http://www.dbase.com/Knowledgebase/v5_docs/LPTPRN.txt

maharcs.txt
http://www.dbase.com/Knowledgebase/v5_docs/maharcs.txt

MULTPAGE.txt
http://www.dbase.com/Knowledgebase/v5_docs/MULTPAGE.txt

NEWMACRO.txt
http://www.dbase.com/Knowledgebase/v5_docs/NEWMACRO.txt

OOP.txt
http://www.dbase.com/Knowledgebase/v5_docs/OOP.txt

POPUP.txt
http://www.dbase.com/Knowledgebase/v5_docs/POPOP.txt

PRINT.txt
http://www.dbase.com/Knowledgebase/v5_docs/PRINT.txt

sessions.txt
http://www.dbase.com/Knowledgebase/v5_docs/sessions.txtSTREAM.txt

TIMER.txt
http://www.dbase.com/Knowledgebase/v5_docs/TIMER.txt
Michael Nuwer
2008-12-05 15:18:20 UTC
Permalink
Post by Rainald
I was just on my way to put together a list of the valuables for former
dBDOS people (better say: for Bruce);
FORMVARS was on top, OOP.how the second one.
Great to see that you go along the same lines!!
Yes, these two documents are still the best place to start.
Post by Rainald
Rainald
P.S. Ins't really strange that these valuables are not being referenced
anymore?
They are still available but only "under the hood".
I found the link via a Google search. All the documents should be made easily
available by the people at dBASE, Inc. on their web site. I agree.
Rick Miller
2008-12-07 03:14:41 UTC
Permalink
Rainald,
Post by Rainald
ARRAY1.txt
http://www.dbase.com/Knowledgebase/v5_docs/ARRAY1.txt
ARRAY2.txt
http://www.dbase.com/Knowledgebase/v5_docs/ARRAY2.txt
BUFFER.txt
http://www.dbase.com/Knowledgebase/v5_docs/BUFFER.txt
CLASS.txt
http://www.dbase.com/Knowledgebase/v5_docs/CLASS.txt
CUSTCLAS.txt
http://www.dbase.com/Knowledgebase/v5_docs/CUSTCLAS.txt
CUSTFORM.txt
http://www.dbase.com/Knowledgebase/v5_docs/CUSTFORM.txt
FAX.txt
http://www.dbase.com/Knowledgebase/v5_docs/FAX.txt
FILLFORM.txt
http://www.dbase.com/Knowledgebase/v5_docs/FILLFORM.txt
FORMVARS.txt
http://www.dbase.com/Knowledgebase/v5_docs/FORMVARS.txt
GLOSSARY.txt
http://www.dbase.com/Knowledgebase/v5_docs/GLOSSARY.txt
INDEX.txt
http://www.dbase.com/Knowledgebase/v5_docs/INDEX.txt
Kiuchics.txt
http://www.dbase.com/Knowledgebase/v5_docs/Kiuchics.txt
LOWLEVEL.txt
http://www.dbase.com/Knowledgebase/v5_docs/LOWLEVEL.txt
LPTPRN.txt
http://www.dbase.com/Knowledgebase/v5_docs/LPTPRN.txt
maharcs.txt
http://www.dbase.com/Knowledgebase/v5_docs/maharcs.txt
MULTPAGE.txt
http://www.dbase.com/Knowledgebase/v5_docs/MULTPAGE.txt
NEWMACRO.txt
http://www.dbase.com/Knowledgebase/v5_docs/NEWMACRO.txt
OOP.txt
http://www.dbase.com/Knowledgebase/v5_docs/OOP.txt
POPUP.txt
http://www.dbase.com/Knowledgebase/v5_docs/POPOP.txt
PRINT.txt
http://www.dbase.com/Knowledgebase/v5_docs/PRINT.txt
sessions.txt
http://www.dbase.com/Knowledgebase/v5_docs/sessions.txtSTREAM.txt
TIMER.txt
http://www.dbase.com/Knowledgebase/v5_docs/TIMER.txt
----

Thank You for all the additional links.

Wow, in a thread with 2 Professors.

Nice to hear You are still hanging out here,
Rick Miller
Rainald
2008-12-08 20:48:39 UTC
Permalink
Post by Rick Miller
Thank You for all the additional links.
You're welcome.
I thought someone lurking later might benefit from the list.
Too bad dBI did remove the 5.x things from the KB :-( :-(
Post by Rick Miller
Wow, in a thread with 2 Professors.
LOL
Post by Rick Miller
Nice to hear You are still hanging out here,
Not "still". I was in the state of hibernation for a couple of years and
only re-appeared a few weeks a go.
Not much success so far as the results of my postings are concerned
:-( :-(

Rainald
Rick Miller
2008-12-08 21:47:55 UTC
Permalink
Post by Michael Nuwer
Post by Rick Miller
Thank You for all the additional links.
You're welcome.
I thought someone lurking later might benefit from the list.
Too bad dBI did remove the 5.x things from the KB :-( :-(
Post by Rick Miller
Wow, in a thread with 2 Professors.
LOL
Post by Rick Miller
Nice to hear You are still hanging out here,
Not "still". I was in the state of hibernation for a couple of years and
only re-appeared a few weeks a go.
Not much success so far as the results of my postings are concerned
:-( :-(
----

Glad Your hibernation is done for the time being.
Everything has become results oriented so maybe
a classroom (cyber or otherwise) where theory and
it's subsequent implementation is a better fit for
Your wisdom.
But fear not many lurkers still seek the why and how.

Happy Holidays,
Rick Miller
Rainald
2008-12-05 04:58:57 UTC
Permalink
Post by Bruce R. Roland
help local
"You cannot use a local variable for macro substitution with the &
operator. Again, you must copy it to a private (or public)
variable first."
Hmmm..! This would mean that if the variables were declared as
either Private or Public then they should work I would think.
As far as PUBLICs are concerned: They work just *everywhere*.
They are *globally* available.
And that's the *bad* thing we have been talking about.
Post by Bruce R. Roland
However, I just went back and tried them as private and got the
variable undefined error again - same as I got when declaring them
local. So I must be missing something here - but I am not sure
what.
Yes. In your report the variables are not seen.
And this is just correct.
Post by Bruce R. Roland
Please see my second post on this subject also RE: releasing the
variables from memory. when I did this it made all my variables
become undefined.
Right.
That's the use of releasing variables.
When "released", a variable has just gone Nirvana ;-) :-)
Post by Bruce R. Roland
the only thing I have found so far is that they
work only when declared as public.
I believe You.
But that's just because of the - wrong <!> - way you creating your
things.
Would you use the right ways, you'd make the values needed for you
report (f.e.) be seen when the report needs them.
Post by Bruce R. Roland
But with the discussion which
took place re: public vs. local variable declarations I was under
the impression that declaring them as local should work as well -
which it does not.
It will work if the right road is taken.
It will not work the way you are doing things at present.

That your things work (someway) at present is just due to the
forgiveness of dBASE.
You use(d) PUBLICs and by that only *camouflage* enabled some results.
This definitely is no road to success.

If you really want to proceed, you have to re-think and re-think and do
that all over again.
You'd otherwise get stuck in dead-end one-way streets.
Mike Nuwer has directed you to a paper which shows the very basics.
(The very same was on top of a posting I had hanging around 90% complete
as a reply in your first thread).
Post by Bruce R. Roland
Therefore I am either confused as to what was
being said regarding the use of local vs. public declarations for
variables or there is something else going on here I am not
comprehending.
Yes, it's something else!
It's just the way OOP-dBASE (DML) is working.

What you'd really need (prior to fiddling around with some broken
report) would be to get yourself into the OOP-thinking.
Mike Nuwer has already shown the way to start with variables.
Next thing to read (possibly parallel to FORMVARS.how) would be another
basic paper by Alan Katz: "OOP.how" (OOP.txt)
http://www.dbase.com/Knowledgebase/v5_docs/OOP.txt

If any questions in so far, pls ask them (possibly in new threads with
significant subjects).

HTH
Rainald
Michael Nuwer
2008-12-05 03:44:10 UTC
Permalink
Post by Bruce R. Roland
Hmmm..! This would mean that if the variables were declared as either Private or Public then they should work I would think. However, I just went back and tried them as private and got the variable undefined error again - same as I got when declaring them local. So I must be missing something here - but I am not sure what.
--------
A local or a private variable should be declared inside the function. And the
local variable is visible only inside that function.

function myFunction
local myVariable

The code that you posted declares the variables in the wrong place. None of the
locals are visible to the functions inside the "DisplaynhtpInvoice" object. But
dBASE will automatically create a variable if it is not declared, which is what is
happening in your code.
Bruce R. Roland
2008-12-05 12:49:12 UTC
Permalink
Michael
Post by Michael Nuwer
A local or a private variable should be declared inside the function. And the
local variable is visible only inside that function.
function myFunction
local myVariable
The code that you posted declares the variables in the wrong place. None of the
locals are visible to the functions inside the "DisplaynhtpInvoice" object. But
dBASE will automatically create a variable if it is not declared, which is what is
happening in your code.
OK. So that would explain the reason for local in my code not working and Public working. That is to say the form itself is not a function (Routine) so local will not work for variables declared in the form but rather for ones only declared in the function it seems. That explains some of my inquiry.

That being the case as you may see the variables I declare in the form are used across several functions. Rather than declaring them as local in each and every function it would be more convenient to declare themn once as I did and then have them available to all the functions which is what I currently do. Does this mean that since local (and assuming private as well from the results I got when I tried this) are only available to the function in which they are declared - and in my code they are not declared in the function but rather the form - that my only option here would be to make them Publlic as I did?

Bruce
Michael Nuwer
2008-12-05 15:18:42 UTC
Permalink
Post by Bruce R. Roland
That being the case as you may see the variables I declare in the form are used across several functions. Rather than declaring them as local in each and every function it would be more convenient to declare themn once as I did and then have them available to all the functions which is what I currently do. Does this mean that since local (and assuming private as well from the results I got when I tried this) are only available to the function in which they are declared - and in my code they are not declared in the function but rather the form - that my only option here would be to make them Publlic as I did?
No. For the type of data you're describing, I would advise using properties:


function form_onOpen
this.myVariable1 = ""
this.myVariable2 = 0
Bruce R. Roland
2008-12-05 20:57:22 UTC
Permalink
Michael

Please bear with me - it probably seems I am a little dense here but I don't think I am getting it yet.
Post by Michael Nuwer
Post by Bruce R. Roland
That being the case as you may see the variables I declare in the form are used across several functions. Rather than declaring them as local in each and every function it would be more convenient to declare themn once as I did and then have them available to all the functions which is what I currently do. Does this mean that since local (and assuming private as well from the results I got when I tried this) are only available to the function in which they are declared - and in my code they are not declared in the function but rather the form - that my only option here would be to make them Publlic as I did?
function form_onOpen
this.myVariable1 = ""
this.myVariable2 = 0
Your suggestion is to make these parameters of the function (or is it psrsmeters of the form object and simply that they are created in the function - or may it be parameters of the calling object)? If you look at my code which I have reposted for reference below - that would seem to entail adding something similar to what you suggest above to each function or having the same declarations three times - one for each function?

Again, if possible I would like to declare these only once and then be able to use them in all three of the functions. Maybe this could be done in the fSet_Params_Setup function as that sets values for some of the variables (some based on others). This sounds somewhat like what you are suggesting. I don't know for sure.

Other discussion leads me to think that maybe these need to be set up in the main app program since they are used by three functions but that does not make sense to me since these are only used within this one form and no others and the main application runs many forms now and could run many more as time goes on which do not use these. Thus, it would seem more appropriate to have them tied to only this the form that uses them.

as to some of the suggestions on other reading on this issue - I did read some of the articles Reinald had suggested on variables and parameters but at my current level I am finding them difficult to understand at best and confusing even more. I don't know how to get the understanding I need to understand this which is the problem or part of it at least.

Any way, if you can answer my question above then maybe I can gain enough understanding to go further.

To all - please be patient with me and someday I'll get it - I hope (yes I have some doubt here- smile)

I am sure my confusion shows here and the truth is - maybe I am in way over my head on this (OOP programming).

At any rate my programs do run for now - correct or incorrect - so while there is room for improvement - there is no need to rush. That is to say I need to learn this but it is not something I need to do overnight or my application is going to crash (I think).

Bruce

***********************************************************
Code sample // this is the actual code as it now runs
***********************************************************

LOCAL DisplaynhtpInvoice

PUBLIC ofields,;
nID_Ref,;
cExpn_Field_Ref,;
cInvoice_Field_Ref,;
cTotal_Field_Ref,;
oInvoice_Object_Ref,;
oTotal_Object_Ref,;
cInvoice_Value,;
cExpn_Value,;
cTotal_Value,;
nCalculated_Invoice,;
nCalculated_Expenses,;
nCalculated_Wages,;
nCalculated_Total,;
cEnabled_Ref,;
cPicture_Ref

cEnabled_Ref := "_Data.ENABLED"
cPicture_Ref := "_Data.PICTURE"

DisplaynhtpInvoice = NEW DisplaynhtpInvoice()

IF (Modal)
DisplaynhtpInvoice.MDI = false
DisplaynhtpInvoice.READMODAL()
ELSE
DisplaynhtpInvoice.MAXIMIZE := false
DisplaynhtpInvoice.MINIMIZE := false
DisplaynhtpInvoice.OPEN()
ENDIF

CLASS DisplaynhtpInvoice OF Form_TemplateFORM FROM Aims.prg

//////////////////////////////////////////////////////////////////////////////////
///// Class object definitions are here//////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

FUNCTION fSet_Params_Setup

oFields = FORM.qNhtp_Invoice.ROWSET.FIELDS
oParentTree = "FORM."

cInvoice_Field_Ref := "Invoice_No_" + n

oInvoice_Object_Ref := oParentTree + "deoInvoice_No_"
oTotal_Object_REF := oParentTree + "deoTotal_Charges_"

oTotal_Object_Ref += n + cEnabled_Ref
oInvoice_Object_Ref += n + cPicture_Ref


FUNCTION fSet_Params_Onedit

FOR n = 1 TO 14

FORM.Fset_Params_Setup()

&oTotal_Object_Ref := false

&oInvoice_object_Ref := "AA-####"

NEXT

// Ensure save() fires even when no changes occur during
// edit - (ENABLED parameters reset upon the rowset being
// saved when exiting from the edit mode (rowset ONSAVE()
// is called). If no changes made MODIFIED is false and no
// save occurs, hence no reset of ENABLED parameters. By
// setting MODIFIED to true a save is forced even if no
// changes occur ensuring ENABLED parameters are reset).

FORM.qNhtp_Invoice.ROWSET.MODIFIED = true


FUNCTION fSet_Params

FOR n = 1 TO 14

FORM.Fset_Params_Setup()

&oTotal_Object_Ref := true

IF oFields[cInvoice_Field_Ref].VALUE == "" or oFields[cInvoice_Field_Ref].VALUE = NULL
&oInvoice_Object_Ref := NULL
ENDIF
NEXT

ENDCLASS

***********************************************************
End Code sample
***********************************************************
Michael Nuwer
2008-12-05 22:17:41 UTC
Permalink
Post by Bruce R. Roland
Any way, if you can answer my question above then maybe I can gain enough understanding to go further.
After looking at your code, I'd say that you don't need so many variables -- see
below.
Post by Bruce R. Roland
To all - please be patient with me and someday I'll get it - I hope (yes I have some doubt here- smile)
I am sure my confusion shows here and the truth is - maybe I am in way over my head on this (OOP programming).
We have all been where you are. Hang in there, it will come.
Post by Bruce R. Roland
At any rate my programs do run for now - correct or incorrect - so while there is room for improvement - there is no need to rush. That is to say I need to learn this but it is not something I need to do overnight or my application is going to crash (I think).
After looking at your code, here is how I would rewrite it. (Keep in mind that I
cannot test it.)


DisplaynhtpInvoice = NEW DisplaynhtpInvoice()

IF (Modal)
DisplaynhtpInvoice.MDI = false
DisplaynhtpInvoice.READMODAL()
ELSE
DisplaynhtpInvoice.MAXIMIZE := false
DisplaynhtpInvoice.MINIMIZE := false
DisplaynhtpInvoice.OPEN()
ENDIF

CLASS DisplaynhtpInvoice OF Form_TemplateFORM FROM Aims.prg

//////////////////////////////////////////////////////////////////////////////////
///// Class object definitions are here//////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

FUNCTION fSet_Params_Onedit
local n
private c
FOR n = 1 TO 14
c = "form.deoTotal_Charges_"+ n +"_Data"
with (&c)
ENABLED = false
endwith
c = "form.deoInvoice_No_"+n+"_Data"
with (&c)
PICTURE = "AA-####"
endwith
NEXT
FORM.qNhtp_Invoice.ROWSET.MODIFIED = true

FUNCTION fSet_Params
local n, oFields
private c
oFields = FORM.qNhtp_Invoice.ROWSET.FIELDS
FOR n = 1 TO 14
c = "form.deoTotal_Charges_"+ n +"_Data"
with (&c)
ENABLED = false
endwith

IF oFields["Invoice_No_"+n].VALUE == "" or ;
oFields["Invoice_No_"+n].VALUE = NULL
c = "form.deoInvoice_No_"+n+"_Data"
with (&c)
PICTURE = NULL
endwith
ENDIF
NEXT

ENDCLASS
Bruce R. Roland
2008-12-06 03:22:43 UTC
Permalink
Michael

Wow! Looking at the code you suggested it looks like exactly what I needed and was looking for (mind I have not tried it yet but it looks exacxtly like what I was looking for).

I think this will work from what I see and I think this answers all my questions on this issue (although I reserve the right to grill you further after I work with this a little - that is if you don't mind) <smiling>.

Thanks for now - will be back in touch Sunday or Monday to let you know how things went.

Bruce
Post by Bruce R. Roland
DisplaynhtpInvoice = NEW DisplaynhtpInvoice()
IF (Modal)
DisplaynhtpInvoice.MDI = false
DisplaynhtpInvoice.READMODAL()
ELSE
DisplaynhtpInvoice.MAXIMIZE := false
DisplaynhtpInvoice.MINIMIZE := false
DisplaynhtpInvoice.OPEN()
ENDIF
CLASS DisplaynhtpInvoice OF Form_TemplateFORM FROM Aims.prg
//////////////////////////////////////////////////////////////////////////////////
///// Class object definitions are here//////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
FUNCTION fSet_Params_Onedit
local n
private c
FOR n = 1 TO 14
c = "form.deoTotal_Charges_"+ n +"_Data"
with (&c)
ENABLED = false
endwith
c = "form.deoInvoice_No_"+n+"_Data"
with (&c)
PICTURE = "AA-####"
endwith
NEXT
FORM.qNhtp_Invoice.ROWSET.MODIFIED = true
FUNCTION fSet_Params
local n, oFields
private c
oFields = FORM.qNhtp_Invoice.ROWSET.FIELDS
FOR n = 1 TO 14
c = "form.deoTotal_Charges_"+ n +"_Data"
with (&c)
ENABLED = false
endwith
IF oFields["Invoice_No_"+n].VALUE == "" or ;
oFields["Invoice_No_"+n].VALUE = NULL
c = "form.deoInvoice_No_"+n+"_Data"
with (&c)
PICTURE = NULL
endwith
ENDIF
NEXT
ENDCLASS
Bruce R. Roland
2008-12-06 04:36:16 UTC
Permalink
Michael
Now for the only last question I have. As you suggested and you can see in my code the following two lines are repeated in both the fSet_Params and fSet_Params_Onedit functions. Is there a way to make them available to both functions but only have them in the code once - say placing them in another location? I only ask this a if that is possible then I have eliminated two lines of code from my program (actually this is why I had originally written the code the way I had). If there is a way to do this I would like to figure it out - If not the code works Ok so that's fine as well.
Sorry forgot to add the two lines referenced in the question! They are:

oInvoice_Object_Ref = "FORM.deoInvoice_No_" + n + "_Data"
oTotal_Object_REF = "FORM.deoTotal_Charges_" + n + "_Data"

Bruce
Bruce R. Roland
2008-12-06 04:31:42 UTC
Permalink
Michael

I lied - I just had to try what you suggested right away - and it worked !!!!

Below is my code as I have rewritten it and it seems to work ok. If there are problems with this I think they will show up as I use this form and I can deal with those issues then. But for now - Yee-Haw!

You may note that there is an extra function in this code which was not in my original post. I simply cut it with the class objects by mistake when I originally posted but your suggestions for this issue worked on it as well so everything came out ok in the end.

Thanks.

Now for the only last question I have. As you suggested and you can see in my code the following two lines are repeated in both the fSet_Params and fSet_Params_Onedit functions. Is there a way to make them available to both functions but only have them in the code once - say placing them in another location? I only ask this a if that is possible then I have eliminated two lines of code from my program (actually this is why I had originally written the code the way I had). If there is a way to do this I would like to figure it out - If not the code works Ok so that's fine as well.

Thanks loads

Bruce

***********************************************************
Code sample // this is the actual code as it now runs
***********************************************************

PARAMETER Modal

LOCAL DisplaynhtpInvoice

DisplaynhtpInvoice = NEW DisplaynhtpInvoice()

IF (Modal)
DisplaynhtpInvoice.MDI = false // ensure not MDI
DisplaynhtpInvoice.READMODAL()
ELSE
DisplaynhtpInvoice.MAXIMIZE := false
DisplaynhtpInvoice.MINIMIZE := false
DisplaynhtpInvoice.OPEN()
ENDIF

CLASS DisplaynhtpInvoice OF Form_TemplateFORM FROM Aims.prg

//////////////////////////////////////////////////////////////////////////////////
///// Class object definitions are here//////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

FUNCTION fCalculate_Totals

// This function calculates/recalculates the totals for
// each line and the totals for the invoice each time a
// change is made to any expense/cost/rate value.

nCalculated_Expenses = 0
nCalculated_Invoice = 0
nCalculated_Total = 0
nCalculated_Wages = 0

// Store object ID for use in generating references

nID_Ref = FORM.ACTIVECONTROL.ID

// Generate ParentTree references.

oFields = THIS.FORM.qNhtp_Invoice.ROWSET.FIELDS

// Generate field references

cExpn_Field_Ref = "Expenses_" + nID_Ref
cInvoice_Field_Ref = "Invoice_Total_" + nID_Ref
cTotal_Field_Ref = "Total_Charges_" + nID_Ref

// Ensure Fields have a value (are not NULL).
// (If NULL, Calculation results will be a NULL)

IF oFields[cExpn_Field_Ref].Value = NULL
oFields[cExpn_Field_Ref].Value := 0
ENDIF

IF oFields[cInvoice_Field_Ref].Value = NULL
oFields[cInvoice_Field_Ref].Value := ""
ENDIF

IF oFields[cTotal_Field_Ref].Value = NULL
oFields[cTotal_Field_Ref].Value := 0
ENDIF

// Retrieve and store field values

cExpn_Value = oFields[cExpn_Field_Ref].Value
cInvoice_Value = oFields[cInvoice_Field_Ref].Value
cTotal_Value = oFields[cTotal_Field_Ref].Value

// Calculate Total (Invoice Amount + Reimbursements)
// and set the value of Total_Charges to the result.

nCalculated_Total := (oFields[cInvoice_Field_Ref].value + oFields[cExpn_Field_Ref].Value)
oFields[cTotal_Field_Ref].Value := nCalculated_Total


// Total all Invocied Amounts - set TOTAL_Invoices to result

FOR N = 1 to 14
cInvoice_Field_Ref := "Invoice_Total_" + n
IF oFields[cInvoice_Field_Ref].Value # NULL
nCalculated_Wages += oFields[cInvoice_Field_Ref].Value
ENDIF

NEXT

oFields["TOTAL_Invoices"].Value := nCalculated_Wages

// Total expenses for invoice - set Total_Expenses to result

FOR N = 1 to 14
cExpn_Field_Ref := "Expenses_" + n

IF oFields[cExpn_Field_Ref].Value # NULL
nCalculated_Expenses += oFields[cExpn_Field_Ref].Value
ENDIF

NEXT

oFields["Total_Expenses"].Value := nCalculated_Expenses

// Total all charges for invoice - set Total_Due to result

FOR N = 1 to 14
cTotal_Field_Ref := "Total_Charges_" + n
IF oFields[cTotal_Field_Ref].Value # NULL
nCalculated_Invoice += oFields[cTotal_Field_Ref].Value
ENDIF

NEXT

oFields["Total_Due"].Value := nCalculated_Invoice

**********************************************

FUNCTION fSet_Params_Onedit // Fires on entering edit

// Cycle FOR/NEXT loop once for each line of invoice.

FOR n = 1 TO 14

oInvoice_Object_Ref = "FORM.deoInvoice_No_" + n + "_Data"
oTotal_Object_REF = "FORM.deoTotal_Charges_" + n + "_Data"

// Set ENABLED for Total_Charges to false during
// edit mode (Prevents editing of Total_Charges)

WITH(&oTotal_Object_Ref)
ENABLED = false
ENDWITH

// Ensure PICTURE parameter is set during edit mode
// (Displays picture format during edit).

WITH(&oInvoice_object_Ref)
PICTURE = "AA-####"
ENDWITH

NEXT

// Ensure save() fires even when no changes occur during
// edit - (ENABLED parameters reset upon the rowset being
// saved when exiting from the edit mode (rowset ONSAVE()
// is called). If no changes made MODIFIED is false and no
// save occurs, hence no reset of ENABLED parameters. By
// setting MODIFIED to true a save is forced even if no
// changes occur ensuring ENABLED parameters are reset).

FORM.qNhtp_Invoice.ROWSET.MODIFIED = true

****************************************************

FUNCTION fSet_Params // Fires from form and rowset

// Cycle FOR/NEXT loop once for each line of invoice.

FOR n = 1 TO 14

oFields = FORM.qNhtp_Invoice.ROWSET.FIELDS
oInvoice_Object_Ref = "FORM.deoInvoice_No_" + n + "_Data"
oTotal_Object_REF = "FORM.deoTotal_Charges_" + n + "_Data"
cInvoice_Field_Ref = "Invoice_No_" + n

// Ensure ENABLED parameter set to true on form opening.

WITH(&oTotal_Object_Ref)
ENABLED = true
ENDWITH

// Ensure PICTURE parameter set to a NULL for fields
// with no value when form opens.

IF oFields[cInvoice_Field_Ref].VALUE == "" or oFields[cInvoice_Field_Ref].VALUE = NULL
WITH(&oInvoice_Object_Ref)
PICTURE = NULL
ENDWITH
ENDIF
NEXT


ENDCLASS

***********************************************************
End Code sample
***********************************************************
Michael Nuwer
2008-12-06 16:26:35 UTC
Permalink
Post by Bruce R. Roland
You may note that there is an extra function in this code which was not in my original post. I simply cut it with the class objects by mistake when I originally posted but your suggestions for this issue worked on it as well so everything came out ok in the end.
fCalculate_Totals is structured according to preferred OOP standards. All of the
variables are used inside one and only one function. The only suggestion that I
would add is that the variables should all be declared "local." Otherwise dBASE
declares them as private. The advantage of local is that when the function
terminates, dBASE removes the variables from memory.

FUNCTION fCalculate_Totals
local nID_Ref, oFields, n
local nCalculated_Expenses, ;
nCalculated_Invoice, ;
nCalculated_Total, ;
nCalculated_Wages
local cExpn_Field_Ref, cInvoice_Field_Ref, cTotal_Field_Ref
local cExpn_Value, cInvoice_Value, cTotal_Value
Post by Bruce R. Roland
Now for the only last question I have. As you suggested and you can see in my code the following two lines are repeated in both the fSet_Params and fSet_Params_Onedit functions. Is there a way to make them available to both functions but only have them in the code once - say placing them in another location? I only ask this a if that is possible then I have eliminated two lines of code from my program (actually this is why I had originally written the code the way I had). If there is a way to do this I would like to figure it out - If not the code works Ok so that's fine as well.
The following might work.

FUNCTION fSet_Params_Onedit
local n
private c
FOR n = 1 TO 14
c = form.getTotal_Object_REF( n )
with (&c)
ENABLED = false
endwith
c = form.getInvoice_Object_Ref( n )
with (&c)
PICTURE = "AA-####"
endwith
NEXT
FORM.qNhtp_Invoice.ROWSET.MODIFIED = true

FUNCTION fSet_Params
local n, oFields
private c
oFields = FORM.qNhtp_Invoice.ROWSET.FIELDS
FOR n = 1 TO 14
c = form.getTotal_Object_REF( n )
with (&c)
ENABLED = false
endwith

IF oFields["Invoice_No_"+n].VALUE == "" or ;
oFields["Invoice_No_"+n].VALUE = NULL
c = form.getInvoice_Object_Ref( n )
with (&c)
PICTURE = NULL
endwith
ENDIF
NEXT

function getInvoice_Object_Ref( n )
return "FORM.deoInvoice_No_" + n + "_Data"

function getTotal_Object_REF( n )
return "FORM.deoTotal_Charges_" + n + "_Data"
Post by Bruce R. Roland
Thanks loads
You're welcome.
Michael Nuwer
2008-12-05 02:52:18 UTC
Permalink
help local
"You cannot use a local variable for macro substitution with the & operator.
Again, you must copy it to a private (or public) variable first."
Hello All!
Hoping someone can give me some insight as to why two variables I use won't work if they are declared local but will if declared Public.
We had some discussion on the use of Public variables vs. Local over the past week or two here in the newsgroup. From that discussion I concluded that the variables I am using in most of my programs could, in fact, and should be, in fact, declared as local rather than public. Thus, I changed the declaration of these variables from public to local.
With the exception of two of my declared variables all of them work as local rather than public variables which is what I expected of all of them after the discussion on public vs. local.
The two I had to leave as public in order for the code to work should from everything I see work if declared as local - but as said they don't.
The code for the form in which these are used is laid out below. The two variables in question are only used in the form in which they are declared - nowhere else in my code.
The only thing I can reasonably come up with for this problem is that these two are used outside the CLASS even though used on the form containing the class.
Anyone have anything that may help me understand this?
Originally only "DisplaynhtpInvoice" was declared local - all others were declared as Public.
The obvious two variables to which I refer here as giving me a problem - if it actually is a problem - are the two declared Public in the sample code below.
Thanks.
Bruce
***********************************************************
Code sample
***********************************************************
LOCAL DisplaynhtpInvoice,;
ofields,;
nID_Ref,;
cExpn_Field_Ref,;
cInvoice_Field_Ref,;
cTotal_Field_Ref,;
oInvoice_Object_Ref,;
oTotal_Object_Ref,;
cInvoice_Value,;
cExpn_Value,;
cTotal_Value,;
nCalculated_Invoice,;
nCalculated_Expenses,;
nCalculated_Wages,;
nCalculated_Total
PUBLIC cEnabled_Ref,;
cPicture_Ref
cEnabled_Ref := "_Data.ENABLED"
cPicture_Ref := "_Data.PICTURE"
DisplaynhtpInvoice = NEW DisplaynhtpInvoice()
IF (Modal)
DisplaynhtpInvoice.MDI = false
DisplaynhtpInvoice.READMODAL()
ELSE
DisplaynhtpInvoice.MAXIMIZE := false
DisplaynhtpInvoice.MINIMIZE := false
DisplaynhtpInvoice.OPEN()
ENDIF
CLASS DisplaynhtpInvoice OF Form_TemplateFORM FROM Aims.prg
//////////////////////////////////////////////////////////////////////////////////
///// Class object definitions are here//////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
FUNCTION fSet_Params_Setup
oFields = FORM.qNhtp_Invoice.ROWSET.FIELDS
oParentTree = "FORM."
cInvoice_Field_Ref := "Invoice_No_" + n
oInvoice_Object_Ref := oParentTree + "deoInvoice_No_"
oTotal_Object_REF := oParentTree + "deoTotal_Charges_"
oTotal_Object_Ref += n + cEnabled_Ref
oInvoice_Object_Ref += n + cPicture_Ref
FUNCTION fSet_Params_Onedit
FOR n = 1 TO 14
FORM.Fset_Params_Setup()
&oTotal_Object_Ref := false
&oInvoice_object_Ref := "AA-####"
NEXT
// Ensure save() fires even when no changes occur during
// edit - (ENABLED parameters reset upon the rowset being
// saved when exiting from the edit mode (rowset ONSAVE()
// is called). If no changes made MODIFIED is false and no
// save occurs, hence no reset of ENABLED parameters. By
// setting MODIFIED to true a save is forced even if no
// changes occur ensuring ENABLED parameters are reset).
FORM.qNhtp_Invoice.ROWSET.MODIFIED = true
FUNCTION fSet_Params
FOR n = 1 TO 14
FORM.Fset_Params_Setup()
&oTotal_Object_Ref := true
IF oFields[cInvoice_Field_Ref].VALUE == "" or oFields[cInvoice_Field_Ref].VALUE = NULL
&oInvoice_Object_Ref := NULL
ENDIF
NEXT
ENDCLASS
***********************************************************
End Code sample
***********************************************************
Rainald
2008-12-05 04:07:53 UTC
Permalink
Post by Bruce R. Roland
Hoping someone can give me some insight as to why two variables I
use won't work if they are declared local but will if declared
Public.
It seems that you are mistaking some things.
I assume that you are referring to the discussion in your old thread
"Can't seem to get single2.wfm code to run right"
There Geoff had commented that using PUBLIC variables was "not a
recommended thing"
Message-ID: <***@news.dbase.com>
and I had jumped in on this with further remarks.
Message-ID: <***@news-server>
When you asked back, I tried to explain the major differences
Message-ID: <***@news-server>

Pls go back to the old thread and read again there.
Post by Bruce R. Roland
We had some discussion on the use of Public variables vs. Local
over the past week or two here in the newsgroup.
No. The discussion was not "PUBLICs" vs. "LOCALs".
It was just on PUBLICs not being appropriate in an OOP-environment as is
32-bit dBASE (and had been dBWin and VdB 5.7).
As I explained in the said posting of Nov. 26 - 02:15
Message-ID: <***@news-server>
- contrary to dBDOS there are *three* categories of variables -
* PUBLIC
* PRIVATE
* LOCAL.

Under dBDOS we had only the first two.
LOCALs appeared with dBWin (5.0) and have been the mainly used type
since then.

The difference lies in the *scope* which means:
Where a variable is seen:
* PUBLICs (in other languages called "GLOBALs) are seen everywhere
throughout the system (the application;
* PRIVATEs (which were the standard in dBDOS) are seen in the routine
(procedure/function) where the are initialized and in all routines
(procedures/functions) called from there;
* LOCALs are - as their name says - "local" which means that they are
only seen in the routine itself and they are not seen on any level below
(routines called from the current procedures).

As dBASE since dBWIN has been a system working alongside the guidelines
of OOP, in general only *LOCAL* variable should be used.
One may used PRIVATEs if needed (but this is limited to some rare
exceptional cases - as I said in the quoted posting and Mike Nuwer has
repeated here - f.e if macro-substitution is used [in case you do not
know what this is, pls ask in a new thread]).

To repeat it:
- standard in programming is to use LOCALs,
- In some exceptional cases PRIVATEs are needed,
- PUBLICs are a left-over from ancient times and are NoNos as they are
"Globally" seen and by this spoil what are the most basic patterns of an
OOP architecture.
Post by Bruce R. Roland
From that
discussion I concluded that the variables I am using in most of my
programs could, in fact, and should be, in fact, declared as local
rather than public.
RightyRight!
Post by Bruce R. Roland
Thus, I changed the declaration of these variables
from public to local.
Correct.
Post by Bruce R. Roland
With the exception of two of my declared variables all of them work
as local rather than public variables which is what I expected of
all of them after the discussion on public vs. local.
OK. Good to hear.
Post by Bruce R. Roland
The two I had to leave as public in order for the code to work
should from everything I see work if declared as local - but as
said they don't.
If this is the case, something is wrong in you code and/or the
architecture of your application.
We'd have to go after this and change things so that no more PUBLICs are
needed.
Post by Bruce R. Roland
The code for the form in which these are used is laid out below.
The two variables in question are only used in the form in which
they are declared - nowhere else in my code.
If the variables are only used there, there would be no need at all to
make them PUBLIC!
As said before:
PUBLIC means "globally seen".
A report normally does not need that.
Post by Bruce R. Roland
The only thing I can reasonably come up with for this problem is
that these two are used outside the CLASS even though used on the
form containing the class.
This might the reason.
A LOCAL variable is seen *nowhere* except in the routine it was
*initialized*
In case of using a FORM for calling a report this would be the
event-handler calling the report (f.e. ReportButton_onClick). Once the
event-handler fired and the report takes over, the LOCAL variable will
be not existing (or better: not seen anymore).
Post by Bruce R. Roland
Anyone have anything that may help me understand this?
I'd hope that the above explanations might show you the *why?*

When using the PUBLICs as you did in the past you just jumped over the
fences which are there out of good reason!
In order to make the values (which you had/have) in your PUBLICs you'll
need to have a different construction which will make the values seen
inside the report.

Unfortunately I can not help you in as far as the report is concerned.
The report engine introduced with VdB 7.0 (and almost unchanged until
now) is quite something (Sorry, Ken <g>) and - although being involved
in quite some Beta-testing of this component - I never ever really used
it (like many others; I do not know anybody who might be using the dBASE
report engine [many are using "Crystal Reports", most of the folks in
Germany are using "Lists &n Labels"]).
This does not at all mean to discourage you in trying it with the
built-in report-engine.

So pls accept that I can not help you with your code.
I'd hope, however that I might have helped on understanding about
variable.
In case anything unclear, pls ask back.

HTH
Rainald
Bruce R. Roland
2008-12-05 12:16:41 UTC
Permalink
Rainald
Post by Rainald
It seems that you are mistaking some things.
I assume that you are referring to the discussion in your old thread
"Can't seem to get single2.wfm code to run right"
There Geoff had commented that using PUBLIC variables was "not a
recommended thing"
I don't think I was mistaken here. This is why I was trying to switch my public variables to Local ones to begin with. I did understand from that thread that public is not recommended and from what I could see is not needed because of the interconnection of programs through the linking available (linking by using " additive").
Post by Rainald
No. The discussion was not "PUBLICs" vs. "LOCALs".
It was just on PUBLICs not being appropriate in an OOP-environment as is
32-bit dBASE (and had been dBWin and VdB 5.7).
I apologize if I misspoke here - I just was taking this through interpretation to be somewhat a discussion on Public vs. local from the comments made RE: Publics not being recommended and Locals being maybe suggested as more appropriate. While you are right that the thread was not about one vs. the other there was an underlyimg impact to this effect by the thread in some little way. So again I appologize for mis speaking.
Post by Rainald
- contrary to dBDOS there are *three* categories of variables -
* PUBLIC
* PRIVATE
* LOCAL.
This is pretty well spelled out in the OLH and while I do not have trouble understanding what it says - I am having trouble with seeing it in action which is the reason for this thread. I think some of my comments on down this post may explain that further.
Post by Rainald
of OOP, in general only *LOCAL* variable should be used.
One may used PRIVATEs if needed (but this is limited to some rare
exceptional cases - as I said in the quoted posting and Mike Nuwer has
repeated here - f.e if macro-substitution is used [in case you do not
know what this is, pls ask in a new thread]).
I did read this and it did add some understanding RE using locals for macro substitution and the fact that they will not work as such. Thus, I now know why that does not work and know to be alert for that on out.
Post by Rainald
- standard in programming is to use LOCALs,
- In some exceptional cases PRIVATEs are needed,
- PUBLICs are a left-over from ancient times and are NoNos as they are
"Globally" seen and by this spoil what are the most basic patterns of an
OOP architecture.
Got it.
Post by Rainald
If this is the case, something is wrong in you code and/or the
architecture of your application.
We'd have to go after this and change things so that no more PUBLICs are
needed.
PUBLIC means "globally seen".
A report normally does not need that.
And I think this is where I am with this and why I am asking these questions. Locals are not working in my code - they only work if made public - and this is why I need to figure this out.
Post by Rainald
A LOCAL variable is seen *nowhere* except in the routine it was
*initialized*
In case of using a FORM for calling a report this would be the
event-handler calling the report (f.e. ReportButton_onClick). Once the
event-handler fired and the report takes over, the LOCAL variable will
be not existing (or better: not seen anymore).
I am with you on this in theory - everything you say is as it should be with respect to a local being seen only by the routine (program) in which it is declared. The problem is with my code this seems not to be the case for some reason or I am misunderstanding what is meant here or what constitutes a routine. (i.e., I thought the form program I added at the bottom constituted a routine since it is a program. As such it seems any variables declared as local within that program should be available to that program. However, in my code this seems not to be the case as when I declare them local (I tried Private with the same results as well) I get a "variable undefined" error - which I do not get if I declare them public.

Thus, my confusion as to what is going on and why local declarations of these variables is not working when in theory (and from what you are saying should in fact) work.
Post by Rainald
When using the PUBLICs as you did in the past you just jumped over the
fences which are there out of good reason!
In order to make the values (which you had/have) in your PUBLICs you'll
need to have a different construction which will make the values seen
inside the report.
I should state here for the record the code I posted is for a form and not a report. The variables declared are used only within the form and not used in any report or any other program.
Post by Rainald
So pls accept that I can not help you with your code.
I'd hope, however that I might have helped on understanding about
variable.
Understandable - we are all at different levels of our understanding of something and it seems this is one arewa you don't understand yet - but will someday - and so I realize you can't advise me on this yet. But someday you will <smile>.

Bruce
Continue reading on narkive:
Loading...