Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Function returns single Var iso Array

Status
Not open for further replies.

Nifrabar

Programmer
Mar 16, 2003
1,343
0
0
NL
Hi!
I am writing piece of code to close all projects before I want to zip my data-files.
In the underlisted function CloseProjects I expect to return an array holding the projects names. But instead it just returns a single var.
What do I oversee?

-Bart
Code:
LOCAL lcDay, lnM, lcMonth, lcYear, lcTime, lcBUName, lcAppName, lcUser, lnProjects 
lcDay 	= ALLTRIM(STR(DAY(DATE())))
lnM 	= MONTH(DATE())
lcMonth = ICASE(lnM = 1,"Januari"	,lnM = 2 ,"Februari" ,lnM = 3,"Maart",;
				lnM = 4,"April"  	,lnM = 5 ,"Mei"		 ,lnM = 6,"Juni",;
				lnM = 7,"Juli"  	,lnM = 8 ,"Augustus" ,lnM = 9,"September",;
				lnM =10,"Oktober"	,lnM =11 ,"November" ,lnM =12,"December")
lcYear  = ALLTRIM(STR(YEAR(DATE())))				
lcTime  = CHRTRAN(TRANSFORM(TIME()), ':', '-')
lcBUName= INPUTBOX("Naam van Backup-bestand",_screen.Caption,"BU")
lcAppName = "MarlocApp"
lcUser 	  = "MarlocUser"

lnProjects = 0

IF VARTYPE(oApp)="O" AND !ISNULL(oApp)
	lcAppName 	= oApp.AppName
	lcUser		= oApp.CurrentUser
ENDIF 	

lcBUName= "Backup\" + lcBUName + "_" + lcAppName + "_"+ lcUser + "_" + lcDay + lcMonth + lcYear + "_" + lcTime

*close any projects to prevent DBC being not included in BU-zip file
laProjects = CloseProjects()

* here we actual zip the datamap into the backup-map
ln=azip(.T. ,lcBUName , "data\*.*" ) 

*restore 'environment'
=OpenProjects(laProjects)

*****************************************************************************************************
FUNCTION CloseProjects
LOCAL  lnProjects, lnCnt, laProjects[1]
lnProjects 	= 0
lnCnt		= 0
* eerst project(en) sluiten, anders wordt de dbc niet gebackupped
IF VERSION(2)<>0  && geen runtime versie
	lnProjects = application.Projects.count
  	IF lnProjects > 0
		DIMENSION laProjects[lnProjects]
		STORE "" TO laProjects
    	FOR lnCnt = 1 TO lnProjects
      		laProjects[lnCnt] = application.Projects(1).name
      		Application.Projects(1).Close
    	ENDFOR
  	ENDIF
ENDIF

RETURN laProjects

*****************************************************************************************************
FUNCTION OpenProjects
LPARAMETERS taProjects
LOCAL lnCnt, lnProjects
lnCnt 		= 0
lnProjects 	= ALEN(taProjects,1)
* eerder gesloten projecten opnieuw opnenen
IF VERSION(2)<>0  && geen runtime versie
	IF tnProjects > 0
		FOR lnCnt = 1 TO lnProjects
	  		MODIFY PROJECT (taProjects(lnCnt)) NOWAIT
		ENDFOR
  	ENDIF
ENDIF

**************
 
Hi Nifrabar,
I don't think you can return an array via the return command.
What I would do is to declare the array in your main program and then pass it to CloseProjects() as a parameter.

At the moment when you execute the line RETURN laProjects it will just return the 1st element in the array.

Good luck,
Shardlow.
 
Shouldn't your code :

FOR lnCnt = 1 TO lnProjects
laProjects[lnCnt] = application.Projects(1).name
Application.Projects(1).Close
ENDFOR

be :

FOR lnCnt = 1 TO lnProjects
laProjects[lnCnt] = appplication.Projects(lnCnt).name
Application.Projects(lnCnt).Close
ENDFOR

 
Shardlow, you are right.

Essentially a function can only return a single value - a reference perhaps but just one value.

You have two choices, either pass the array - by reference to the function or declare it as a visible (global or private by scope).

Martin

Regards

Griff
Keep [Smile]ing
 
mm0000,
The answer is NO. I also asumed at first. But it seems that while projects(1) is closed another project,e.g. project(2), can only be refered to as projects(1).

Shardlow and Griff,
I first tried in the main procedure saying :
Private array laProjects[1] which also is proper programming
But probably I gave wrong returnvalue (by reference). Would you give me a hand on this?

Before I used same code but than in just one procedure iso calls to CloseProjects() and Openprojects(). For reason of being better readable I changed to the above solution.
I am rewriting my framework and are trying to tidy up all code a bit according to my nowadays-knowledge. My old framework was started in 1998 when I first started with VFP (3!!).

So I have to remain with a global array?

-Bart



 
I would use collections for this (VFP8 and above).

Code:
FUNCTION CloseProjects
LOCAL  lnProjects, lnCnt, loProjects
lnProjects     = 0
lnCnt        = 0
loProjects = CREATEOBJECT("COLLECTION")
* eerst project(en) sluiten, anders wordt de dbc niet gebackupped
IF VERSION(2)<>0  && geen runtime versie
    lnProjects = application.Projects.count
      IF lnProjects > 0
         FOR lnCnt = 1 TO lnProjects
              loProjects.add(application.Projects(1).name)
              Application.Projects(1).Close
        ENDFOR
      ENDIF
ENDIF
RETURN loProjects

*****************************************************************************************************
FUNCTION OpenProjects
LPARAMETERS toProjects
LOCAL lcProject
IF VERSION(2)<>0  && geen runtime versie
   FOR EACH lcProject IN toProjects
       MODIFY PROJECT (lcProject) NOWAIT
   ENDFOR
ENDIF

The main procedure would read

Code:
LOCAL loProjects AS Object
...

*close any projects to prevent DBC being not included in BU-zip file
loProjects = CloseProjects()

* here we actual zip the datamap into the backup-map
ln=azip(.T. ,lcBUName , "data\*.*" ) 

*restore 'environment'
=OpenProjects(loProjects)

Hope this suits your needs...


Jean
 
Since CloseProjects is actually doing the closing, why return the array at all? Why not just return the number of projects closed, or even a logical value?

Tamar
 
Hi Bart,

As was already stated, you can return an array if it was passed by reference as a parameter to your function, but not if it was created in your function. You can, however, return an object with an array property

oList = CreateObject("empty")

AddProperty(oList, "aProjects[1]", [])
DIMENSION oList.aProjects[3]
oList.aProjects[1] = "Eenie"
oList.aProjects[2] = "Meenie"
oList.aProjects[3] = "Minie"

RETURN oList

If you are using a version of VFP earlier than 8, use a line or a relation instead of the Empty class to carry your array property.

pamela

 
nifrabar said:
I first tried in the main procedure saying :
Private array laProjects[1] which also is proper programming
But probably I gave wrong returnvalue (by reference). Would you give me a hand on this?

If the array is global (or private), you don't need to pass it (even not by reference) and you surely mustn't pass something back by reference. The idea of passing vars by reference is to let the called procedure/ function/ method change that thing itself instead of passing in a copy (pass by value), that could be modified and still wouldn't change a bit in the original var.

But as others pointed out it's much more elegant to create a collection or some other object and pass that back to the caller by RETURN loObject.

You might call that "return by reference", as passing objects is always done by reference, it still is a little different, as the local var you pass back get's out of scope and you need to receive the object reference into a variable at the caller side.

If you work with vfp7 or earlier versions not knowing a collection class, you can create an object (eg custom) and add an array property to that object and pass it back.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top