×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

Marco Plaza's Code for nf_num2en.prg

Marco Plaza's Code for nf_num2en.prg

Marco Plaza's Code for nf_num2en.prg

(OP)
Marco--

First, thank you for sharing your code. In the code, you declare the arrays as private:

CODE -->

private abn,aun,atn,atw,an 

I am curious as to why? I have gotten away from using private variables since the scope of them is visible to called programs which in the past has caused me many issues before the LOCAL declaration came about. I have a check in my editor to show undeclared variables (which by default would be PRIVATE). For arrays, I use the following declaration:

CODE -->

LOCAL ARRAY abn[1], aun[1], atn[1], atw[1], an[1] 

This initializes and declares the array as a local object. If I have to pass an array to a function, then I pass by reference, @abn; or I use an object that has an array assigned as a property.

But I am just curious why you use PRIVATE?

Thank you.

Greg

Greg

RE: Marco Plaza's Code for nf_num2en.prg

worth reposting the code here as i suspect that other thread will get removed soon....

CODE -->

*--------------------------------
* Marco Plaza, 05/2022
* nf_num2en.prg @nfox.dev
* ( use it as you like )
*--------------------------------
lparameters num

local num,cnum,rn,n1,n2,n3,x
private abn,aun,atn,atw,an

cnum = transform(m.num,'999999999999999.99')

alines(abn,"trillion,billion,million,thousand,,",2,',')
alines(aun,"one,two,three,four,five,six,seven,eight,nine,ten",1,',')
alines(atn,"ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen",1,',')
alines(atw,"twenty-,thirty-,forty-,fifty-,sixty-,seventy-,eighty-,ninety-",1,',')

rn = ''

for x = 1 to 18 step 3

	alines(an,transform(substr(m.cnum,m.x,3),'@R 9,9,9'),2,',')
	n1 = val(an(1))
	n2 = val(an(2))
	n3 = val(an(3))

	rn = m.rn + iif( m.n1=0,'',' '+aun(m.n1)+' hundred')
	rn = m.rn + iif( an(1)='.' and m.n2+m.n3 > 0,'and','')
	rn = m.rn + iif( m.n2=0,'',' '+iif(m.n2=1,atn(m.n3+1),atw(m.n2-1)))
	rn = m.rn + iif( m.n3=0 or m.n2=1,'',' '+aun(m.n3))

	rn = m.rn + iif(m.n1+m.n2+m.n3>0,' '+ abn((m.x-1)/3+1),'')
	

endfor

rn = strtran(m.rn,'- ','-') + iif(' and '$m.rn,'hundredths','')

return ltrim(rn) 

RE: Marco Plaza's Code for nf_num2en.prg

PRIVATE is not a declaration, it just hides already existing private variables of that name until the code ends. The names therefore become avaiable from that line onwards to use them for own private vars. Which is likely the reason people often read it as declaration.

The PRIVATE command protects variables in private scope defined outside of the function by "parking" them, so there is no side effect of anybody using private variables abn,aun,atn,atw,an for whatever other use case before calling nf_num2eng.prg. After the function ends it's own private arrays are released and the hidden private variables become visible again and are untouched.

If Marco wanted to use local arrays, that's possible, too, as ALINES will take any already existing array and extend it. But not by simply replacing PRIVATE with LOCAL.

CODE

Local abn
alines(abn,"trillion,billion,million,thousand,,",2,',') 

Causes error "abn is not an array". The replacement with local variables would mean to use LOCAL abn[1],aun[1],atn[1],atw[1],an[1] to define these vars as arrays and let them be dimensioned by ALINES. Or dimension them to the necessary size in the LOCAL statement. A function not making further calls can use private variables just like locals, a possible disruption comes, as you say, Greg, when you do call further programs and they meddle with them.

LOCAL is good practice for something used local, that's true, but there is no big benefit about LOCAL nor a risk in using PRIVATE. Especially since a same name private variable defined outside doesn't penetrate this function. PRIVATE ALL would also work.

Chriss

RE: Marco Plaza's Code for nf_num2en.prg

(OP)
Chris--

The risk in PRIVATE vs LOCAL is demonstrated below (note that if you do not 'declare' a variable, then by default it is PRIVATE):

CODE -->

PRIVATE pnValue
pnValue = 1
?pnValue  && Displays 1
CallUDF()

?pnValue  && Displays 2

FUNCTION CallUDF
   pnValue = 2
ENDFUNC 

Since the variable is declared as PRIVATE in the top procedure, the CallUDF() is changing the same variable as the parent procedure. PRIVATE allows the variable to be in-scope for all child methods/procedures. Yes, each declaration causes a 'new' variable to be created, but if you missed declaring it as PRIVATE or LOCAL then you can have unexpected variable changes. This behavior is what I don't like. If I want a called procedure to access the calling procedure's variables, then I pass them as parameters. If I want the value returned, then I use the RETURN statement to pass the value back (if multiple values are needed to be passed back then I typically use a custom object with properties) or I explicitly pass them by reference. The same code with the variable defined as LOCAL:

CODE -->

LOCAL lnValue
lnValue = 1
?lnValue  && Displays 1
CallUDF()

?lnValue  && Still Displays 1

FUNCTION CallUDF
   lnValue = 2   && by default this is a new variable with PRIVATE scope
ENDFUNC 

Note that I use the prefix "l" for LOCAL and "p" for PRIVATE. Since the second example declares the variable as LOCAL, the value is not changed by the call to the CallUDF() function.

Greg

RE: Marco Plaza's Code for nf_num2en.prg


Hi Greg,

As Chris already stated, in this context it makes no difference...

The thing is I have a little helper that do the locals and I have it configured
that way for a particular project.

This function is a "blind-street".. so don't worry.

Also, Chris asked for a 'better naming' and here it is with a little improvement here and there:

Ps:
I would like to highlight the fact that I see no real need for "refactoring" the good-old working code from ramani;
just made this for fun of programming.. rethink a routine that we all had to do many years ago when checks where in use.


CODE -->

*--------------------------------
* Marco Plaza, @nfoxdev, 2022
* nf_num2en.prg v 1.1
* use as you like
*--------------------------------
lparameters numInput as number,ldecAsNumber as boolean as string

if not vartype(m.numInput) $ 'NY' or vartype(m.ldecasnumber) # 'L'
	error 'invalid parameter type'
	return .null.
endif

local maskedInput,num2en,numAtPos1,numAtPos2,numAtPos3,groupStartPos,groupn,rem
private aBigNum,aUnits,aTenths,aTwent,charAtPos

maskedInput = transform(m.numInput,'999999999999999.99') 

alines(aBigNum	,"trillion,billion,million,thousand,,",2,',')
alines(aUnits	,"one,two,three,four,five,six,seven,eight,nine,ten",1,',')
alines(aTenths	,"ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen",1,',')
alines(aTwent	,"twenty,thirty,forty,fifty,sixty,seventy,eighty,ninety",1,',')

num2en = ''
groupn = 0

for groupStartPos = 1 to iif(m.ldecAsNumber,15,18) step 3 

	alines(charAtPos,transform(substr(m.maskedInput,m.groupStartPos,3),'@R 9,9,9'),2,',')
	
	numAtPos1 = val(charAtPos(1))
	numAtPos2 = val(charAtPos(2))
	numAtPos3 = val(charAtPos(3))

	num2en = m.num2en + iif( m.numAtPos1  = 0 ,'',' '+aUnits(m.numAtPos1)+' hundred' )
	num2en = m.num2en + iif( charAtPos(1) = '.' and m.numAtPos2+m.numAtPos3 > 0 ,'and'	,'')
	num2en = m.num2en + iif( m.numAtPos2  = 0 ,'',' '+iif(m.numAtPos2=1,aTenths(m.numAtPos3+1),aTwent(m.numAtPos2-1)+'-') )
	num2en = m.num2en + iif( m.numAtPos3  = 0 or m.numAtPos2 = 1 ,'',' '+aUnits(m.numAtPos3) )

	m.groupn = m.groupn+ 1
	num2en = m.num2en + iif(m.numAtPos1+m.numAtPos2+m.numAtPos3>0,' '+ aBigNum(m.groupn),'')

endfor

* remove space after twenty etc..
num2en = strtran(m.num2en,'- ','-')

* reminder
rem = mod(m.numInput,1)*100

if m.rem>0 or m.ldecAsnumber
	num2en = m.num2en + iif(!m.ldecasNumber,'hundredths','and '+transform(m.rem,'@l 99')+'/100')
endif

return ltrim(m.num2en)

*---------------------------------
procedure testme
*---------------------------------
clear
okres = 'nine trillion one hundred fifty-one billion one hundred eleven million two hundred fifty-four thousand one hundred fifty-five and nineteen hundredths'
cures = nf_num2en( 9151111254155.19 )
? m.okres
? m.cures
? 'test ok?',m.okres = m.cures 

Marco Plaza
@nfoxProject
https://www.github.com/nftools

RE: Marco Plaza's Code for nf_num2en.prg

(OP)
Marco--

I realized from the start that it made no difference in the context of this program. Either way your program will work with no problems since it does not call any other UDF. Actually, the line:

CODE -->

private aBigNum,aUnits,aTenths,aTwent,charAtPos 

could be eliminated; these array variables will be PRIVATE by default when created by the ALINES() command (again, no problems having it). In my coding practice for VFP I have adopted to never use PRIVATE and always declare all variables as LOCAL. Globals, if needed are added as properties to _VFP system variable. In the past, I have had problems with PRIVATE declared variables or variables that were never declared getting unexpectedly changed and the debugging to find the culprit can be time consuming. I have the ability to highlight any variable that is in a method or UDF that has not been declared to be LOCAL or LPARAMETER; this is my attempt to eliminate the scope "side-effects" for PRIVATE declared variables.

I was just curious as to why you specifically chose PRIVATE rather than LOCAL ARRAY...

Greg

Greg

RE: Marco Plaza's Code for nf_num2en.prg


well.. no .. to isolate from caller programs
private can't be eliminated.

( Check again Chris post on that regard )

try:

CODE -->

dimension ss(10)
ss = null
display memory like ss
alines(ss,'a,b',1,',')
display memory like ss 

Marco Plaza
@nfoxProject
https://www.github.com/nftools

RE: Marco Plaza's Code for nf_num2en.prg

Greg,

you miss the point. Your code demonstrating the bad side effect comes from the bad practice to not use PRIVATE within the CallUDF function to distinguish its own private variable use from outside private variables.

In your last post you show again how you miss the point that indeed only a line like PRIVATE listing vars you want to be sure will be generated new by your code will prevent you to change other peoples private vars. Marco could have made that easier with PRIVATE ALL, but indeed most code not using a private command is just sure of itself only using its own local vars. It's a small danger indeed, not for yourself, for the caller. And therefore calling code usually does not use private vars, and they vanish from being used.

Private vars only unfold their potential to save time for declaration and parameter passing when you create them in one PRG/procedure/function/method/event and then call something that explicitly knows about them and is tailored to use them in whatever way necessary. Also to change them can be a wanted effect instead of unwanted side effect.

We are able to do without private variables in any other language than VFP, it's a concept that proves itself as rarely useful and creating a lot of misunderstandings. If you want your variables owned by only you, you declare them LOCAL, if you want to share them with what you call (and also what that code calls, etc.) you can pass them by reference. In VFP you can also make them PRIVATE and will therefore not need to pass them on at all, they stay in scope.

Chriss

RE: Marco Plaza's Code for nf_num2en.prg

(OP)
Marco--

Sorry, but I do not understand what you are trying to explain. Let me try with an example code to show what I am doing:

CODE -->

DIMENSION laArray[2]   && By default this is a PRIVATE scope
laArray = 1
? laArray[1]
? laArray[2]

MyUDF()

? laArray[1]
? laArray[2]

FUNCTION MyUDF
laArray = 2
ENDFUNC 

The above will output to the screen 1, 1, 2, 2 for the array values. What I want is MyUDF not to be able to change the values of the array but to see the variable name as another variable. This is achieved with the following:

CODE -->

LOCAL ARRAY laArray[2]
laArray = 1
? laArray[1]
? laArray[2]

MyUDF()

? laArray[1]
? laArray[2]

FUNCTION MyUDF
laArray = 2
ENDFUNC 

The above will now output to the screen 1, 1, 1, 1 for the array values; the array is not changed by MyUDF function. The variable is a new variable and not scoped from the calling program. However, if I want MyUDF to change the values, then I would pass by reference as follows:

CODE -->

LOCAL ARRAY laArray[2]
laArray = 1
? laArray[1]
? laArray[2]

MyUDF(@laArray)

? laArray[1]
? laArray[2]

FUNCTION MyUDF
LPARAMETERS taArray
EXTERNAL ARRAY taArray
taArray = 2
ENDFUNC 

Hope the above will clarify what I am trying to ask in regards to PRIVATE vs. LOCAL.

Greg

Greg

RE: Marco Plaza's Code for nf_num2en.prg

Greg,

Quote (Greg)

I want MyUDF to change the values, then I would pass by reference

Indeed that concept makes private vars obsolete, also within VFP, but if you want, you can do without any parameters and any passing on of values when using the PRIVATE scope. It's a strange scope, as it's not bound to a class or a PRG, anything that is called has access to the private variables, also code not intended for it.

Chriss

RE: Marco Plaza's Code for nf_num2en.prg

You can do something like this to have encapsulation in procedural programming. In this scenario a private variable from the main code of a PRG is like the property of a class. It is available to the main PRG code and the internal functions within the same PRG used by it or using each other:

CODE

Private pScopedLikeaPRGProperty
pScopedLikeaPRGProperty = 42 && initializing = creating the actual variable
prg_internal_function()

Function prg_internal_function()   
   If Not Program(Program(-1)-1)==JustStem(Sys(16))
      Error 'prg_internal_function is only for internal use of '+JustStem(Sys(16))
   ENDIF
   * pScopedLikeaPRGProperty is accessible here and is defined from the main code in this PRG, not coming from elsewhere
   * because the only entrance to here is calling the PRG.
   * The PRG main code hides any previously defined private variable of the same name and generates a new one. 

You can now technically still SET PROCEDURE TO the PRG with this code, but when you try to call prg_internal_function() the function will error. The function is private to the PRG just like the private var.

Chriss

RE: Marco Plaza's Code for nf_num2en.prg


the following assumption is not true.. ( that's the problem )

Quote (ggreen61)


DIMENSION laArray[2] && By default this is a PRIVATE scope

I failed on my first sample... so:

CODE -->

clear
dimension names(2) 
names = 'my x value'
display memory like names
 num2letters()
display memory like names 
? "names() was changed by num2letters()!"


dimension names(2) 
names = 'my x value 2'
display memory like names
 num2letters2()
display memory like names 
? "names() was'nt changed by num2letters"


*----------------------
function num2letters()
*----------------------

dimension names(10)
alines(names,'a,b',1,',')


function num2letters2()

private names && hide existing names  
dimension names(10)
alines(names,'a,b',1,',') 


Marco Plaza
@nfoxProject
https://www.github.com/nftools

RE: Marco Plaza's Code for nf_num2en.prg

(OP)
Marco--

The second function, num2letters2, forces a new variable to be declared with the same name as the parent with the private declaration. VFP is 'smart' enough to create a new variable and not use the same one from the calling program in num2letters2. I just don't like the potential to change a variable's value in a called program that is declared in the parent unless it is passed by reference -- passing by reference is a clear indication in the program code that the value can be changed. I have found that if I have to come back to the program and make changes maybe years later, that it is harder to make changes if the variables can be changed in any of the 'child' functions by use of the private scope.

I was just wondering on your use of private when you also used local. Why not both private or both local? Why the choice of using both? I just wanted to learn if there is a particular reason for doing so.

RE: Marco Plaza's Code for nf_num2en.prg


Greg,
The above sample was just to show the behaviour of the private declaration.

Also, all that you say about passing arrays by reference it's totally right.



Marco Plaza
@nfoxProject
https://www.github.com/nftools

RE: Marco Plaza's Code for nf_num2en.prg

Greg,

finally we can say that you can do totally without private vars by means of other techniques like passing by ref and for an extended scope between local and global, I'd rather use a property of a class. But the way legacy screen work(ed) with READ states allowed to use private vars within them as quasi properties, that use is overcome with OOP and so finally, yes, doing without them is not only possible but totally okay. No reason to think there is still some use case you're missing, even saving time for passing on is very marginal. But also no reason in this context to think there's harm possible. The function itself harms no developer using private vars as it explicitly doesn't touch them. So the only risk is sometimes in the future calling something into which the private arrays used bleed in and that modify them.

I think it's still important to know about them as they are a feature you can't turn or configure off and private vars can happen anytime you have a typo in a name differing from the LOCAL declaration. It should show, if it's the only place you make the typo, when you eventually then have two vars with similar but not the same name, one local and one private. It can slip tests not covering all branches of the code and so not covering all corner cases in unit tests. That makes PRIVATE ALL a good idea, for example, in all code. But who wants that?

You can insist all your code has no typos and errors and therefore is hardened against bleeding in private variables as well as having no own private variables bleeding into to code called by you, but it can still happen that you accidentally create or modify a private variable. Tools like Thor offers for that matter (adding LOCALs for variable names used in the code) can help with it. It's still not causing compilation errors, if something slips through, so no reason to be sure something like it won't ever happen as you don't actively and intentionally use private vars.

In any case, even with tool help you will need to check what the variable declaration and use fits your expectation. It doesn't help that Thor catches you having liCount and lnCount in code, for example, if some code address the one and other code addresses the other name and the overall result fails to work because it actually has two count variables and would only work if all code uses the same variable. That's not arguing for private vars, but for not relying too much on being protected against them by not intentionally using them.

Chriss

RE: Marco Plaza's Code for nf_num2en.prg

(OP)
Chris--

I recognized from the start the particular use of PRIVATE in Marco's code example did not have a problem -- there were not any subsequent calls to other UDFs. I just wanted to know why he chose to use it when he obviously used LOCAL in declaring variables right before the line with PRIVATE. Why not LOCAL for both? Was there a particular reason for use of PRIVATE? I was interested in learning if there were some other benefit that I was not aware of.

I would have preferred that PRIVATE would have been eliminated from VFP and the forcing of declaring each variable and type (like other languages). Having a variable being able to be defined simply by mistyping it leads to errors/bugs that a compiler should be able to catch right away. But alas, that is not the case and now I must try to overcome the 'agony' of private when a variable is mistyped. Also, I am not sure of the effect of declaring variables LOCAL and then having the PRIVATE ALL declaration. Does the private all override the local? If the local is declared after the PRIVATE ALL, does it override? I could build my own tests to determine the outcomes, but I just use LOCAL. The editor that I use for VFP (forms, visual classes, programs) has a high-light capability to show me undeclared LOCAL variables as shown (the yellow backgrounded variable):



I use this capability to verify all variables are declared as LOCAL. The editor also has the capability to high-light all the occurrences of a selected variable (much like NotePad++). Between these two capabilities I am fairly certain I am not missing a variable in a typo.

Greg

Greg

RE: Marco Plaza's Code for nf_num2en.prg

Hi Greg,

PRIVATE ALL doesn't override local, as it's not a declaration command. The moment PRIVATE is called it take any already existing private vars with the given names or name patterns (PRIVATE ALL LIKE/ ALL EXCEPT)and hides them - whish is shown as variable scope (hid) in LIST MEMROY. They will be unhidden at the time vars are released at the end of the current method/event/procedure/function/PRG. That should be clear by now.

Nice editor feature, Thor's Create LOCALs would simply create LOCAL lcUndeclaredVar. If you're using the tool you'll find your typos in one of the LOCAL declarations, but only if you look closely. The risk then isn't having a private var, but two LOCAL vars that should actually be the same, which can also cause problems. In the end there's no Lint tool that'll recognize you actually meant the same variable name, which makes ZLOC valuable. Do macros like ZLOC work in your editor?

Chriss

RE: Marco Plaza's Code for nf_num2en.prg

(OP)
Chriss--

The editor is not as directly extensible as Thor was designed. It is based on VFP code and several ActiveX components. So, it is extensible from the point of view of having the source code. Something like Thor's interface could be developed; I just never did. Back when Thor was first being developed by Jim Nelson, he and I talked about an attempt to integrate. Unfortunately, we did not see a way since My editor does not interface back into the VFP development environment the same as Thor does. The code editor component has its own commands for accessing the code lines and tokens which is not easily exposed to something like Thor. I do have a 'hot-key' for a selected variable to auto-add it to the LOCAL command line at the beginning of the procedure/function. Most of the Thor functions that Jim was adding was also added into my editor as well. The editor also has its own macro recording facility for saving repetitive key-strokes and then calling via hot-keys.


Greg

RE: Marco Plaza's Code for nf_num2en.prg

What Marco did is pretty good, but it was not what I was doing. I'm about using best practices and standards. Encapsulation is an English word that has been co-opted into Computer Science. Putting something in a capsule.

OOP is about learning to think of virtual-world "coding" as if they are physical. Code is and always has been a blueprint. That is why we modularize. We don't copy 6 identical copies of code. Although I actually did just debug something at work. I fixed it a year ago. We instructed the user not to add hyphens in this over-loaded string. However, this year, they again added hyphens. Further down in the code from where I made the fix, another identical copy of the code, with the bug crashed. I did a gofish and found 16 more copies of this exact buggy code.

A physical car would have 6 actual spark plugs. In programming we should re-use the 1 spark plug design.

No spark plug should just magically draw gas from the tank and detonate it. The physical world requires the spark plug to be in the cylinder. The software world absolutely does not required a copy of some code inside another prg. Make everything encapsulated unto itself, then reuse them like Lego bricks. It's as simple and elegant as that.

Having your module depend on floating private vars and even perpetuating those vars will have bad effects later on. Like I wrote elsewhere, I saw a system built by then recent college grads almost kill 2 patients because of a single public variable. Just making things work is not good enough at all.

Mike Yearwood - Former Microsoft Visual FoxPro MVP award winner. TWICE

RE: Marco Plaza's Code for nf_num2en.prg

I have not used private or public variables in over 25 years - only local. The only public variable is goApp - the application object of our framework. In large applications, private and public vars can be very dangerous and difficult when debugging. Encapsulation is very important and comes so natural now that I don't even think about it.

However, there are cases where variables need to persist for the entire session of the application. Our application object is a collection containing five additional collection object managers (colCursorMngr, colFormMngr, colTempFileMngr, colWinsockMngr and colGlobalObjectMngr). The colGlobalObjectMngr is used to add, change, and persist variables as properties of "Empty" objects added to the colGlobalObjectMngr at design and runtime. While it is true that the Set|Get calls require a bit more code, encapsulation is honored.

RE: Marco Plaza's Code for nf_num2en.prg

I fully agree with Mike here. While we can discuss the nuances of public and private variables, the best solution | best practice calls for encapsulation which makes public and private moot.

RE: Marco Plaza's Code for nf_num2en.prg

Quote (Greg)

The editor also has its own macro recording facility for saving repetitive key-strokes and then calling via hot-keys.
ZLOC is doing more than just replaying a macro, it's a macro command that result in the choice of variable names and constant defined at that point and does so at designtime what m. only does at runtime.

So maybe the more general question is do you allow intellisense functionality as in the internal editor with such niche features as ZLOC is? (I stress it as the normal autocomplete is surely available also when using Notepad++, for example.) Those things are what I'd miss from an alternate editor.

Chriss

RE: Marco Plaza's Code for nf_num2en.prg

vernpace

What framework is that?

Mike Yearwood - Former Microsoft Visual FoxPro MVP award winner. TWICE

RE: Marco Plaza's Code for nf_num2en.prg

Mike,

It's called FXFrame - my own proprietary framework. The initial version was developed 25 years ago and has been modified a bit over the years. For various reasons, I never released it to the public and I never will.

As you know, the great part about a good framework is that it allows developers to concentrate on application design without being bogged down with VFP minutia.

RE: Marco Plaza's Code for nf_num2en.prg

Exactly. While training and using and supporting and extending Visual MaxFrame I developed a UI "template" that is applicable to almost every UI of an application. This member UI lets the user maintain members. This workhistory UI lets another user maintain the work history of all members.

The users decide if they want to assign someone to batch enter each of those.

From inside the member's detail page, the workhistory for a particular member is shown.
Updating that info is done with the same workhistory screen.

From the workhistory detail, the user can add a new workhistory entry and select a member from the member screen as a picklist, but not while the workhistory is already in child mode, because it's already restricted to the current member.

2 separate forms are built, but they provide services to each other, such as parent-child form and picklist form all while giving add on the fly, edit on the fly, find on the fly, delete on the fly. If the user flow is from member to workhistory on the details page, to edit work history on the workhistory UI, the data is not re-extracted from the server.

Mike Yearwood - Former Microsoft Visual FoxPro MVP award winner. TWICE

RE: Marco Plaza's Code for nf_num2en.prg

Interesting - good job! Complex application developement is very difficult without a good framework. Does MaxFrame allow forms to talk to each other?

Your screen shots remind me of an MRP system I developed awhile back.

RE: Marco Plaza's Code for nf_num2en.prg

Yes. MaxFrame forms talk to each other.

Mike Yearwood - Former Microsoft Visual FoxPro MVP award winner. TWICE

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close