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 IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

DO program error 1

Status
Not open for further replies.

TheLazyPig

Programmer
Sep 26, 2019
96
PH
Hi!

I'm creating an extract form where the process of the code is from a deped.prg.

Untitled_s7btd1.png


Here is my extract button code below...

Code:
SET CENTURY OFF
SET CENTURY ON
SET DELETED ON
SET SAFETY OFF
SET UDFPARMS TO REFERENCE

CLOSE ALL
CLEAR

LOCAL lcDir,bkDir,pgDir,lcDateFrom,lcDateTo,lcMonth,lcYear,cYearMon,cMonthName
*----------------------------------
lcDir      = "'C:\ORC_PRG\NEW_ORC\'"
bkDir      = "'C:\ORC_PRG\DATA\DEPED\'"
lcDateFrom = THISFORM.txtdateFrom.VALUE
lcDateTo   = THISFORM.txtdateTo.VALUE
lcMonth    = MONTH(THISFORM.txtdateFrom.VALUE)
lcYear     = YEAR(THISFORM.txtdateFrom.VALUE)
*----------------------------------

IF  isBlank(lcDateFrom) OR ;
    isBlank(lcDateTo) 
    MESSAGEBOX("Please input correct fields.")
ELSE	

	DO CASE
		CASE lcMonth = 1
			cMonthName = "JANUARY"
		CASE lcMonth = 2
			cMonthName = "FEBRUARY"
		CASE lcMonth = 3
			cMonthName = "MARCH"
		CASE lcMonth = 4
			cMonthName = "APRIL"
		CASE lcMonth = 5
			cMonthName = "MAY"
		CASE lcMonth = 6
			cMonthName = "JUNE"
		CASE lcMonth = 7			
			cMonthName = "JULY"
		CASE lcMonth = 8
			cMonthName = "AUGUST"
		CASE lcMonth = 9
			cMonthName = "SEPTEMBER"
		CASE lcMonth = 10
			cMonthName = "OCTOBER"
		CASE lcMonth = 11
			cMonthName = "NOVEMBER"
		CASE lcMonth = 12	
			cMonthName = "DECEMBER"
	ENDCASE	
	
	cMonthName = UPPER(LEFT(ALLTRIM(cMonthName),3))
	cMonName   = SUBSTR(cMonthName,1,3)
	cYearMon   = SUBSTR(DTOS(lcDateFrom),3,2)+cMonName

	DO lcDir+"\deped.prg" WITH lcDateFrom,lcDateTo,cYearMon
	
	USE crormain IN 0 SHARED NOUPDATE
	
	SELECT COUNT(*) FROM crormain INTO CURSOR lnCnt
    
    IF MESSAGEBOX("Extract Deped ORC?",36,"Confirmation") = 6 
	   COPY TO bkDir+"\"+lcYear+"\"+cMonthName+"\orc_deped2_"+LOWER(cMonName)+lcYear TYPE XL5 
	   COPY TO bkDir+"\"+lcYear+"\crormain2"
	   
	   MESSAGEBOX("File [orc_deped_"+LOWER(cMonName)+lcYear+".xls] Created!")
	      
	ELSE 
	   MESSAGEBOX('Extraction Cancelled')
	   RETURN 0
	ENDIF 


ENDIF

After I run this program I get an error of...
Untitled1_if5dii.png


But deped.prg location is correct.

If I run deped.prg alone without the form, a pop up of details of the extract then I need to close it for the process to execute again then

Untitled2_bilsxt.png


But I only need the crormain that's why I USE it in my code

Is this the reason why I get the error or is it another?

Thanks for the replies!
 
Hi LazyPig

There seem to be several typos

Code:
lcDir      = "[highlight #FCE94F]'[/highlight]C:\ORC_PRG\NEW_ORC\[highlight #FCE94F]'[/highlight]"

should probably read - quotation marks only once

Code:
lcDir      = "C:\ORC_PRG\NEW_ORC\"

and - you have two "\" - one from lcDir and one from "\deped.org"

Code:
DO lcDir+"[highlight #FCE94F]\[/highlight]deped.prg" WITH lcDateFrom,lcDateTo,cYearMon

and bkDir which also ends with a "\"

Code:
COPY TO bkDir+"[highlight #FCE94F]\[/highlight]"+lcYear+"\"+cMonthName+"\orc_deped2_"+LOWER(cMonName)+lcYear TYPE XL5 
COPY TO bkDir+"[highlight #FCE94F]\[/highlight]"+lcYear+"\crormain2"

hth

MarK

 
Hi Lazypig,

Did you declare the PARAMETERS in your deped.prg? It must be the first statement in that program, like

PARAMETERS ....

Rest of code

hth

MarK


 
Do I have to name the parameters same as from extract?
 
Do I have to name the parameters same as from extract?

No. The names of the parameters as declared by the PARAMETERS or LPARAMETERS statement do not have to be the same as those passed by the caller. Also, you can declare more parameters than are actually passed, in which case the surplus parameters will each contain a logical .F.

And, by the way, LPARAMETERS is preferred over PARAMETERS as it makes the parameters local to the called routine, which is usually what you want.
Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi all,

Code:
DO lcDir+"\deped.prg" WITH lcDateFrom,lcDateTo,cYearMon

Well, take a closer look here. Do works with a literal file name, unquoted. For example, you can do DO deped.prg WITH lcDateFrom,lcDateTo,cYearMon when you first changed directory or have the path to depend in your SET PATH.
The price for DO or also CCOPY FILE to allow specifying file names directly, unquoted is, that those names are taken literally.

If you use an expression like lcDir+something, VFP really looks for a file name starting with lcDir. While no file name can contain a " and some other charaavers are forbidden in file names, + is not. In any case VFP isn't understanding that you want to specify the result of your expression as file name. Use brackets around it to get VFP there:

Code:
DO (lcDir+"\deped.prg") WITH lcDateFrom,lcDateTo,cYearMon

The aspect, that you can only pass in parameters to a PR , if it also starts with PARAMETERS or LPARAMETERS is already addressed.

Well, it's one thing to add the parameters, what you name them clearly depends on the code following, because it has to use the names of the PARAMETERS. It won't know the names lcDateFrom,lcDateTo,cYearMon, you pass the values of them, not the variables themselves including their name, the names are set by the PARAMETER or LPARAMETER and by convention you'd call them with t prefix, not l. T as in taken values, taken from outside. So even deciding against that convention you should know the parameters can and will usually have different names. Otherwise it would be hard to write code that receives these parameters and doesn't know what their names are. Wouldn't it?

Or in a short question: How did you expect the PRG to know and address in its code, what is passed into it? Without parameters defined in a prg or procedure or function or method starting with PARAMETERS or LPARAMETERS, how would it even be able to receive anything?

Chriss
 
Regarding the parameters and their names, the question you have to ask yourself is what you actually expect from the PRG to do with your parameters.

If it's not yet programmed to receive parameters, you can't force usage of things you pass by WITH. Even adding a PARAMETERS line doesn't change thee code and its behavior.

It does what it does and what it did before you added the PARAMETER statement at the start of it. The PRG code has to be rewritten to make use of parameters, before you decide that you want to call it with parameters.

One thing you might want to do is get rid of the dependency of the PRG code of the form. The simplest reason is that you can't access THISFORM from a PRG that's now its own PRG file and not part of the form scx/sct files anymore.
So for example, you want to get rid of the line
Code:
lcDateFrom = THISFORM.txtdateFrom.VALUE

Well, you still need a value in lcDateFrom, so you can't just delete the line, the code still needs something that sets lcDateFrom to a value. Not only can you make use of a parameter for that, you are actually forced to make use of a parameter now. The lcDateFrom value can't fall from the sky as alternative to be read from the forms tstDaetFrom textbox. It could also come from a file, but you don't want to store a value to afile to be read by the PRG code, do you? You don't want to take retours, when there is a direct way.

So you start the parameterization process and have your first parameter LPARAMETERS lcDateFrom in the simplest case, to not need to change any further code.

Once that's done you still need several changes. LPARAMETERS lcDateFrom can pass that in instead of reading it from THISFORM.txtdateFrom.VALUE, but then need to remove lcDateFrom from your declaration of local variables:
Code:
LOCAL lcDir,bkDir,pgDir,lcDateFrom,lcDateTo,lcMonth,lcYear,cYearMon,cMonthName

Get rid of that:
Code:
LOCAL lcDir,bkDir,pgDir[s],lcDateFrom[/s],lcDateTo,lcMonth,lcYear,cYearMon,cMonthName

So end up with
Code:
LOCAL lcDir,bkDir,pgDir,lcDateTo,lcMonth,lcYear,cYearMon,cMonthName
Otherwise, the parameter comes in and is replaced by a local variable with the same name, reinitialized to .F.

So your hard earned parameter only very shortly has the passed in value and is then released and overridden by your local variable you still have.
It's not the only variable you need to remove there, but lets do this slowly.

You changed one local variable to a parameter now. Just doing one thing and not the other you are not done with it. You also must remove the initialization with THISFORM.txtdateFrom.VALUE, or you still depend on that and still override what's passed in with the form control value, if it would work to access THISFORM.

So even when you remove the name from LOCAL and have it as LPARAMETER instead, you still shot yourself in the foot by the line
Code:
lcDateFrom = THISFORM.txtdateFrom.VALUE

There you also have another reason to rename things as parameters. Any code that then still uses the local variable you used before will not work on the passed in parameter, and you'll notice that in the debugging phase of your code change.

It's a little adventure, isn't it? You have to understand parameters, the WITH clause of calling a parametized function and need to amend the code of the function to actually use the parameters, don't use local variables anymore and don't grab their values from form controls. Any one of the changes alone doesn't suffice. You cant have a local variable and parameter of the same name, you don't keep the code declaring and initializing the variable when instead you now want to get a parameter passed in.

It seems to me even though I try to explain this slowly and step by step I still overwhelm you with all these things. You better learn to write a function with parameters and how to call it in a new example, start from scratch and don't need to think over how you need to change what you did before.

Very generally speaking changes of code require you to know what your code does to even be able to know how a change ripples through and does what you aim for. Here one change, adding LPARAMETERS, needs another change, not declaring the corresponding local variable anymore, and another change, not initializing this variable anymore, before the passed-in value can really become effective. And you can only see and know that when you know what your code actually did before you even made the first change.

Chriss
 
As a summary: Code changes can be like moving, there's a lot to pack, move, unpack, you stand in the way until finally everything is in its new place and fine again.

But like real moving to a new home, there's a motivation why you do it, a promise or advantage, so what is it?
That should be your driver of the change and not just trying to change the call without parameters and add a WITH clause to see what happens and then painstakingly address error by error until things work again.

If, as I assume your driver is to get rid of errors addressing THSIFORM in a PRG, the solution would be to replace all the variables that you use to grab the form control values with parameters. And then, as consequence of that, remove them from local variables and remove the offending code lines that grab the values from the form. Instead use parameters.

Or in another picture: If you want to drink from a glass instead of the bottle, the first step isn't to pour the bottle content on the ground. First take a glass to have something to pour the drink into it.

Chriss
 
Hi TheLazyPig,

In addition to Chris's explanations I join the code below. Maybe it helps you to better understand the relation between DO ... WITH/ REPLACE ... WITH, the PARAMATERS/LPARAMETERS, the LOCAL VARIABLES and their respective naming conventions.

Code:
Create Cursor Emp_Dtl(cFact C(5) Null, ;
				nEmpNo N(15,0) Null, ;
				cFullName C(60) Null, ;
				cDepartment C(50) Null, ;
				dJoin D Null, ;
				dResign D Null, ;
				cPeriod c(50) Null)
				
INSERT INTO Emp_Dtl values("ABCDA", 987456321, "Niki S", "Front Office", {^2001-01-01}, {^2020-05-31}, "")
INSERT INTO Emp_Dtl values("ABCDB", 123456789, "Jeff B", "Front Office", {^2005-02-28}, {^2019-04-30}, "")
INSERT INTO Emp_Dtl values("ABCDE", 456789123, "Homer F", "Back Office", {^2010-07-01}, {^2020-05-31}, "")

SELECT Emp_Dtl

SCAN

[highlight #FCE94F]	REPLACE cPeriod WITH AMDateDiffAsWords(dJoin, dResign) && the DO ... WITH ... [/highlight]

ENDSCAN

BROWSE 

CLOSE ALL
CLEAR ALL 

RETURN 

**********

FUNCTION AMDateDiffAsWords()
[highlight #FCE94F]	LPARAMETERS  tdSDate, tdEDate 

*!* Declared local parameters - tdSDate takes the value of dJoin and tdEDate takes the value of dResign
*!* Below the declared local variables as you need them[/highlight]

[highlight #FCE94F]		LOCAL ldFirstNextMonth as Date, ;
				 liTotalMonths as Integer, ;
				 liYears as Integer, ;
				 liMonths as Integer, ;
				 liWeeks as Integer, ;
				 liDays as Integer, ;
				 lcAnswer as Character[/highlight]
				 
		ldFirstNextMonth = {}
		liTotalMonths = 0
		liYears = 0
		liMonths = 0
		liWeeks = 0
		liDays = 0
		lcAnswer = ""  

		*!*	If Day(tdSDate) > day(tdEDate), we calculate the number of days remaining in the 
		*!*	start month (may be zero) and add it to the number of days in the end date

		IF tdEDate > tdSDate
			IF DAY(tdSDate) > DAY(tdEDate)
				ldFirstNextMonth = GOMONTH(tdSDate - DAY(tdSDate) + 1 , 1)
				liDays = DAY(tdEDate) + (ldFirstNextMonth - tdSDate) - 1

			ELSE
				liDays = DAY(tdEDate) - DAY(tdSDate)
			
			ENDIF
		   
		*!*	Now the total number of months

		   liTotalMonths = MONTH(tdEDate) - MONTH(tdSDate) + (12 * (YEAR(tdEDate) - YEAR(tdSDate))) - IIF(DAY(tdSDate) > DAY(tdEDate), 1, 0)
		   liYears = INT(liTotalMonths / 12)
		   liMonths = liTotalMonths - (liYears * 12)
		   liWeeks = INT(liDays / 7)
		   liDays = liDays - (7 * liWeeks)
		   
		ELSE 
			=MESSAGEBOX("Please check order of parameters", 48, "Difference in Y/M/W/D between dates")

		ENDIF
		  
		*!*	And format the answer as text

		   IF liYears > 0
		      lcAnswer = ALLTRIM(STR(liYears)+ " Year" + IIF(liYears > 1,"s",""))
		      ENDIF
		   IF liMonths > 0
		      lcAnswer = lcAnswer +" "+ ALLTRIM(STR(liMonths))+" Month"+ IIF(liMonths > 1,"s","")
		      ENDIF
		   IF liWeeks > 0
		      lcAnswer = lcAnswer +" "+ ALLTRIM(STR(liWeeks)) +" Week"+ IIF(liWeeks > 1,"s","")
		      ENDIF
		   IF liDays > 0
		      lcAnswer = lcAnswer +" "+ ALLTRIM(STR(liDays))+" Day"+ IIF(liDays > 1,"s","")
		      ENDIF

	RETURN lcAnswer
ENDFUNC 
***********

hth

MarK

 
You can avoid having to worry about slashes in constructing a file path by using the ForcePath() function. Instead of:

Code:
lcDir+"\deped.prg"

use:

Code:
FORCEPATH("deped.prg", m.lcDir)

Tamar

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top