Objects as parameters in Visual FoxPro

A procedure, function or form in Visual FoxPro cannot return more than a single parameter and sometimes this is not enough. The traditional solution in earlier versions of the language was to create an array to hold the multiple values and to return that array as the single parameter. The introduction of object orientation in Visual FoxPro gives us a more flexible alternative and allows this form to return three parameters.

[DateRange form in Visual FoxPro] The form shown here addresses a common requirement and asks the user to enter two dates, the start and end of a period. It has to return three parameters. Two of these are obvious, we need to know the start date and the end date of the period. The third parameter is more subtle and is often overlooked; we need to know if the data entered by the user is valid. We can rely on logic within the form itself to validate the dates and ensure that the end is later than the start but the code that calls the form must know whether the user has pressed the 'OK' or the 'Cancel' button before the program can proceed to process the two dates.

One solution might be to return an unrealistic pair of dates - such as {01/01/0001} or {31/12/1999} - but this form uses a more robust technique. It has a boolean property lSelected which is .F. by default and is set .T. when the user presses the 'OK' button. All three values are returned as the properties of an object.

Return an object parameter from a VFP form

The form returns these three values as the properties of an object so first we need a simple class as the basis of this object:

DEFINE CLASS xdaterange AS custom

   Name = 'xdaterange'

   *-- Start date of period
   dfromdate = .F.

   *-- End date of period
   dtodate = .F.

   *-- .T. if dates have been selected
   lselected = .F.

ENDDEFINE

Next, the form needs a property to hold this object.

When a form closes the Unload event is the last to run and it is this that returns the parameter. By this time, every object on the form has been destroyed and we cannot read the date in either of the textboxes. Any value returned by a form has to be retrieved from a property of the form because nothing else is available at the moment when the form closes and returns its parameter. Code in the form's Init method must put a DateRange object into this form property ready to accept the data entered by the user.

ThisForm.oDateRange = CREATEOBJECT ('xDateRange')

We must store the dates from the textboxes in this object before the form closes. If the user presses the 'OK' button then we store the start and end dates and .T. in the three properties. The click event holds the following code:

With ThisForm
   .oDateRange.dFromDate = .txtFromDate.Value
   .oDateRange.dToDate = .txtToDate.Value
   .oDateRange.lSelected = .T.
   .Release
EndWith

The code for the 'Cancel' button is much simpler:

With ThisForm
   .oDateRange.lSelected = .F.
   .Release
EndWith

Finally, we just need a Return statement in the Unload event of the form.

Return ThisForm.oDateRange

Remember that any form which returns a parameter to its calling program must be defined as modal. Set its WindowType to 1 - Modal.

Calling the form

Any FoxPro form can be called as though it were a function. Once you have the parameter back as an object you can use the regular VFP syntax to refer to the properties of the object:

Do Form GetDateRange With "Costing Report" To loDates
If loDates.lSelected
   pdFromDate = loDates.dFromDate
   pdToDate = loDates.dToDate
Else
   *-- Do nothing - the user has selected no dates.
Endif

Note that the With clause of this example is just passing a string parameter into the form. This is just some text to act as a title so that the user is reminded why the date range is being requested.