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

Finding out the day of the week 1

Status
Not open for further replies.

T17Rax

Technical User
Jun 11, 2015
39
GB
Hi all,

I have a program that issues a monetary entitlement to people if the day they are entitled to that value is selected.
So for example, if they are supposed to receive £2.00 on a Monday, the field "Mon" would have to be "T" or "Y" ("Yes").

However, when the program attempts to scan the table and search if a particular day is "Y", the program skips to "SKIP" and throws an error telling me that "End of file encountered" when I have the command "Do while not EOF()" and after going through a bit of a debug, I found out that it was because the day it was scanning for was not todays the date (or rather the current day that the program is being executed).

Is there a routine where FoxPro can seek through the calendar, see what day of the week it is and marry it up to the table?
I appreciate your comments and help
Thanks :)

A conclusion is simply a place where you got tired of thinking.
 
Check in help CDOW() and DOW()

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Just to be sure I understand what you are asking:

You want a function that will tell you the current day of the week, that is, the day on which the program is running. Is that right?

If so, all you need is:

[tt]DOW(DATE())[/tt]

That will give you 1 for Sunday, 2 for Monday, and so on (at least, that's the default situation). If you want to follow the standard that says 1 is Monday, you should do this:

[tt]DOW(DATE(), 2)[/tt]

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Rather use DOW for a day number and not CDOW, as it is english within the IDE, but your local language in the executable using some vfp9rLNG.dll for the language resource texts and grpahics.

What number is returned depends on what is defined as first day of the week, the default us US, which means sunday. The way to make monday 1 is via SET FDOW TO 2 (fdow = first day of week) and the compute DOW(DATE(),0) or simpler compute DOW(DATE(),2), so with parameter 0 you always take the FDOW setting, with other values you directly specify FDOW.

And FDOW is given as the day number of the US locale, so 1 means sunday - as initially said - 2 means monday and so on. This simply shifts all the day numbers as you're used to in your locale. The number always is something between 1 and 7, also in this case VFP is 1 based instead of 0 based. So you can take the day number as array index of weekdays. That helps in cases you want control over the language aside of the language resource DLLs, eg if your application should be able to switch languages.

Another one is taking DTOC(DATE()) after setting SET DATE LONG, you get a long text format of a date including weekday and month name. But that can have side effects, if you eg use the inverse CTOD() to convert date strings to dates, that will expect long text format dates. Often this is done in SQL queries insteada of using setting independant formats.

Bye, Olaf.

 
The code is as follows:

Code:
IF CDOW(DATE()) = "Monday"
	GO TOP
		SCAN FOR mon="Y" && Here's where the code fails
*!* Because it's not Monday today, the code skips to "SKIP" and displays "End of file Encountered message". I only figured
*!* this out on Friday when I changed "Monday" to "Friday" and the rest of the references to match the current day, and 
*!* the code worked. 
			IF mon="Y"
			replace Freem WITH "Y"
				IF freema = 0
				replace freema WITH freemx
				ENDIF 
			ENDIF
		endscan
	ENDIF


Mike, the program would be due to run everyday. If they're entitled to the value on a Monday, then the value would be against there record if 'mon="Y"'. If its for Tuesday, the code would repeat but for a tuesday and so forth for the rest of the week.
So in essence, the days of the week using DOW() would have to be variables matching the physical day of week in the table?
i.e, "if DOW(Date(2)) = mon then
...
endif" ?

That's a very clear and helpful explanation Olaf, thank you for that!




A conclusion is simply a place where you got tired of thinking.
 
Still unsure what you want. Do you also have fields Tue, Wed, Thu, Fri, Sat, Sun? Or ony Mon?

Since the SCAN FOR mon="Y" scans for records with Mon="Y" independant of the current day, it will find records fulfilling that condition, if records exist, no matter what day of the week. If you don't find Mon="Y" on friday, you'll still not find them on saturday or sunday, unless dat changed, of course.

You don't have to check the condition, SCAN FOR does so, you get past the scan loop, if no record fulfills the condition and you are at EOF then.

Bye, Olaf.
 
Olaf,

I have the fields Mon, Tues, wed, thur, Fri.
Each field can have either "" or "Y".
If any of those fields have "Y", then the user of that day can have a monetary value for that specific day.

If its Monday, and mon = "Y", then the user will get (for example) £2. But only for that day.
If its Tuesday and tue = "" (blank), the user will not be credited £2.
If its Wednesday and wed = "Y", then the user shall be credited £2 but only for that day.

Now, respectively the code will only work to apply the credit to each user if the day they are entitled to is marked "Y" but because the code starts off with Monday as the first day of the week and I tested it on Friday (because its due for release soon), the code failed and told me I was at the end of file, because Monday was not Friday. I changed Monday to Friday in the code and it worked, applying the credit where necessary.
Rather than the code scanning through the table for the correct day as it should, it worked where it met Friday and I think it's because somewhere it realised that the day I tested the code was a Friday and could only work if the IF statement matched.

Does this make sense?
I apologise for not being clear

A conclusion is simply a place where you got tired of thinking.
 
Maybe this way

Code:
LOCAL lni,ldDate,laDay[5],lcDay
***********************
* Create demo Cursor
***********************
RAND(-1)
CREATE CURSOR cTmp (Freem C(1),;
	Freema I DEFAULT INT(1000*RAND()) * FLOOR(5*RAND()),;
	Freemx I DEFAULT INT(1000*RAND()),;
	Mon C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Tues C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Wed C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Thur C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Fri C(1) DEFAULT IIF(RAND() < 0.2, "Y",""))

FOR lni = 1 TO 500
	APPEND BLANK 
NEXT
***********************

ldDate = DATE()+1

laDay[1] = "Mon"
laDay[2] = "Tues"
laDay[3] = "Wed"
laDay[4] = "Thur"
laDay[5] = "Fri"

IF BETWEEN(DOW(m.ldDate,2),1,5)
	lcDay = laDay[DOW(m.ldDate,2)]
	UPDATE cTmp SET ;
		Freem = "Y" ,;
		Freema = IIF(Freema = 0, Freemx, Freema);
		WHERE &lcDay == "Y"
ENDIF

or
Code:
LOCAL lni,ldDate
RAND(-1)
CREATE CURSOR cTmp (Freem C(1),;
	Freema I DEFAULT INT(1000*RAND()) * FLOOR(5*RAND()),;
	Freemx I DEFAULT INT(1000*RAND()),;
	Mon C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Tues C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Wed C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Thur C(1) DEFAULT IIF(RAND() < 0.2, "Y",""),;
	Fri C(1) DEFAULT IIF(RAND() < 0.2, "Y",""))

FOR lni = 1 TO 500
	APPEND BLANK 
NEXT

ldDate = DATE()+1
IF BETWEEN(DOW(m.ldDate,2),1,5)
	DO CASE
	CASE DOW(m.ldDate) = 2 && Monday
		UPDATE cTmp SET ;
			Freem = "Y" ,;
			Freema = IIF(Freema = 0, Freemx, Freema);
			WHERE Mon == "Y"
	CASE DOW(m.ldDate) = 3 && Tuesday
		UPDATE cTmp SET ;
			Freem = "Y" ,;
			Freema = IIF(Freema = 0, Freemx, Freema);
			WHERE Tues == "Y"
	CASE DOW(m.ldDate) = 4 && Wednesday
		UPDATE cTmp SET ;
			Freem = "Y" ,;
			Freema = IIF(Freema = 0, Freemx, Freema);
			WHERE Wed == "Y"
	CASE DOW(m.ldDate) = 5 && Thursday
		UPDATE cTmp SET ;
			Freem = "Y" ,;
			Freema = IIF(Freema = 0, Freemx, Freema);
			WHERE Thur == "Y"
	CASE DOW(m.ldDate) = 6 && Friday
		UPDATE cTmp SET ;
			Freem = "Y" ,;
			Freema = IIF(Freema = 0, Freemx, Freema);
			WHERE Fri == "Y"
	ENDCASE
ENDIF

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
The code you gave will never ever go tell you, you are at the end of file, you're not showing what errors. You say SCAN FOR mon="Y" errors, but if you have your table selected SCAN will start from top of the table. Did you forget that, perhaps? Anyway, you can of course END at EOF, you will, as that is the natural end of the scan loop, even with FOR clause. You scan through all records fulfilling the condition and end at EOF, you don't just visit the first record.

Vilhelm has a good idea, but as you see you need code per day with such a design, the data desing is not best.
You should rather have a field called days with the day numbers where users get credited, eg 246 for monday, wednesday and friday. Then you could do

Code:
UPDATE cTmp SET ;
Freem = "Y" ,;
Freema = Freemx ;
WHERE Transform(DOW(DATE(),1)) $ Days And Freema=0

Since all this should repeat each week makes me wonder, what sets Freema=0 again.
I fear you have to tell much more, before you get what you really want.

Bye, Olaf.
 
Olaf,

I apologise once again. I was hoping to keep around the problem area without realising the rest of the code may be needed!
I see what you mean with returning to the top of the file but i'm sure in my code below I told to move the to top of form again - as read in other posts.
I've noted below in the code where it fails in the comments.

Here's the PRG as follows:
Code:
SET DEFAULT TO c:\cashless
SET CENTURY ON 
SET DELETED ON 
Select 1
Use Id 
Select 2
Use CLASSS && set the tables we will be playing with
Select 3
Use FREESISSUED
Do While Not Eof()
Select 1
GnIDNO = Idno
GnFreeMealAllowanceRemaining = Freema
GcClass = Lower(Alltrim(CLASSNO))
If GnFreeMealAllowanceRemaining = 0  && There is currently no FSM, so we're good to go
SELECT 2 
LOCATE FOR LOWER(ALLTRIM(CLASSS)) = GcClass
FSMAllowance = Freema
SELECT 1
replace freema WITH FSMAllowance
Select 2
	LOCATE FOR classs = "TEACH"
	freemx = Freema
	SELECT 1
	IF CDOW(DATE()) = "Monday"
	GO TOP
		SCAN FOR mon="Y" &&**** After I debugged the code, the rest of the code was skipped and "SKIP" was highlighted 
			IF mon="Y"
			replace Freem WITH "Y"
				IF freema = 0
				replace freema WITH freemx
				ENDIF 
			ENDIF
		endscan
	ENDIF
	IF CDOW(DATE()) = "Tuesday"
	GO TOP
		SCAN FOR tue="Y"
			IF tue="Y"
			replace Freem WITH "Y"
				IF freema = 0
				replace freema WITH freemx
				ENDIF 
			ENDIF
		endscan
	ENDIF
	IF CDOW(DATE()) = "Wednesday"
	GO TOP
		SCAN FOR wed="Y"
			IF wed="Y"
			replace Freem WITH "Y"
				IF freema = 0
				replace freema WITH freemx
				ENDIF 
			ENDIF
		endscan
	ENDIF
	IF CDOW(DATE()) = "Thursday"
	GO TOP
		SCAN FOR thur="Y"
			IF thur="Y"
			replace Freem WITH "Y"
				IF freema = 0
				replace freema WITH freemx
				ENDIF 
			ENDIF
		endscan
	ENDIF
	IF CDOW(DATE()) = "Friday"
	GO TOP
		SCAN FOR fri="Y"
			IF fri="Y"
			replace Freem WITH "Y"
				IF freema = 0
				replace freema WITH freemx
				ENDIF 
			ENDIF
		endscan
	ENDIF
	IF freem = "Y" then
	Select 3
	Append Blank
	Replace amount With FSMAllowance
	Replace Idno With GnIDNO
	replace date WITH DATE()
	replace time WITH TIME()
	ENDIF
Else
&& We're not good to go. Already has resid FSM !
	GO BOTTOM
	cMessageTitle = "IMPORTANT!"
	cMessageText = "The free meals can't be issued today.There are Free school Meal residuals remaining. Please contact your supplier for more information!"
	nDialogType = 0 + 16
	nAnswer = MESSAGEBOX(cMessageText,cMessageTitle,nDialogType)
	nAnswer = 1
Endif
Select 1 && Always return to ID to continue scanning the database..
Skip && next record ||||| *** This is where it states "End of file encountered"
Loop && continue until done
ENDDO

Thank you.


A conclusion is simply a place where you got tired of thinking.
 
Ok, here we go:

Code:
Select 3
Use FREESISSUED
Do While Not Eof()
*...lots of code...
Select 1 && Always return to ID to continue scanning the database..
Skip && next record ||||| *** This is where it states "End of file encountered"
Loop && continue until done
ENDDO

Of course you sooner or later get an error, if you loop this way.
If you have a loop on workarea 3, you need to Skip in workarea 3, not in workarea 1.
Also you don't do Loop as last command before ENDDO, ENDDO does cause to go back to the loop start anyway, Loop is a command to issue, when you want to loop earlier than ENDDO does.

To get a correct loop, you have to select the workarea you loop through. You can have it easier using a SCAN..ENDSCAN instead, as that automatically skips in the workarea it loops and selects the workarea it began with, so you can't make such errors, you also don't GO TOP before SCAN, unless you do SCAN REST or SCAN WHILE, but then you normally don't want to start at the top. SCAN or SCAN FOR always start at top, though.

Workarea 1 contains your ID table and so you skip your IDs here, this is totally unrelated to the loop you wanted to do.

In fact it's even more complicated, since your inner scan loops indeed work on workarea 1, the id table. Makes me wonder if all that is right, I think you have introduced quite some chaos with the workarea numbers and which DBF to open in them, get used to working with the alias names and don't open any table in a definite workarea, USE sometable IN 0 and you don't need to know the workarea number it opens in, it always opens in a yet unused workarea via IN 0 and you address it by its alias name. That also makes much cleaner and easier readable code.

Bye, Olaf.
 
It's all a learning curve Olaf haha.
I'll read over the code again, perhaps start from scratch and see what I can do with it. I can understand it may be quite a bit of chaos!
Using your knowledge in those commands, I'll have a look at what I can replace, take out, move etc.
Hopefully it should be up and running pretty soon.
Thank you.



A conclusion is simply a place where you got tired of thinking.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top