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

InteractiveChange

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
585
PH
Hi... Good day to eveyone... i have been stucked in this...

PROCEDURE text1.interactivechange

this.parent.text1.value = SPACE(10)

SET SAFETY OFF
SET CONFIRM off
SET TALK off
SET ECHO off
*SET ESCAPE OFF

SELECT 1
USE sms ALIAS tsulat

INDEX on idnum TO idnumx

ctr = 0

SEEK this.Parent.text1.value

IF FOUND()
this.Parent.text1.value = TRIM(tsulat.idnum)
this.parent.text2.value = TRIM(tsulat.sname) + + "," + CHR(13) + TRIM(tsulat.fname)
this.Parent.text3.value = TRIM(tsulat.mobile)
this.Parent.text4.value = TRIM(tsulat.grade)
nctr = ctr


Even if im not yet done with entering 10 characters in text1, it always says record not found....why is it it only accepts one character only and not ten as initialized.... kind of new in vfp 9.. thanks in advanced for your help....
 
Single step through the code, you'll see you always set this.parent.text1.value = SPACE(10) and then you always SEEK this.Parent.text1.value, you always SEEK SPACE(10) and don't find a row emoty in column idnum

It helps to debug code and don't just see the control, names, property names etc. but what their current values are.

Your're overcomplicating things in many ways here, you're code in text1 textbox is addressing itself as this.parent,text1, that would be like you talking of yourself as your mothers daughter mandy, instead of just saying me or I.

You're overwriting anything you type in with space(10). So you never seek what you type. So, well, rethink your object naming and also your object addressing, I guess that'll clarify some things.

Use the visual designers, they'd guide you into existing events, that you fill with your code, writing classes in PRGs you can go wrong so easily, that it's completely incomprehensible why anyone would choose that route voluntarily.

Bye, Olaf.

Olaf Doschke Software Engineering
 
thanks olaf.... i debugged it and wrote...

PROCEDURE text1.interactivechange

SET SAFETY OFF
SET CONFIRM off
SET TALK off
SET ECHO off
*SET ESCAPE OFF

SELECT 1
USE sms ALIAS tsulat

INDEX on idnum TO idnumx

ctr = 0

idcode = ALLTRIM(this.value)

SEEK idcode

but it only accepts one digit then it immediately seeks to the database... is there a way that it should wait for 10 characters to be entered before it seeks into the database? thanks
 
Well, I told you already in length, when you use interactive change that will seek any value from the first digit up to what id you actually want to enter, so don't use interactivechange.

Side note, when you have indexed a dbf you waste time indexing it every time you open it. this will fall on you later, when every single digit you enter causes a 5 second indexing of all data....

Bye, Olaf.

Olaf Doschke Software Engineering
 
Mandy,

There is a lot you can do to improve this code.

Most importantly, the reason that it does the seek after you enter only character is that you are doing this in the InteractiveChange. That event fires, by definition, each time the user makes any change to the textbox. Even a single keystroke will fire it.

The solution is to write the code in the LostFocus, which only fires when the entry is complete.

In addition, it is a bad idea to open (USE) the table each time the event fires. It's much more efficient to open it when the form is launched, and to keep it open until the form closes.

Going further, it is a very bad idea to index the table each time the event fires. Indexing is one of the slowest operations in VFP, and it is unnecessary most of the time. You only need to define the index once, when you first create the table. After that, VFP will keep it up to date each time you add, delete or amend the data.

Less important, you would not normally do things like SET SAFETY, SET CONFIRM, etc. in this kind of event. These are global settings, so, again, do them when the form opens, or at the start of the program. But if you do change these setting at other times, you should also keep a note of the settings' previous values, so that you can set them back at the end of the bit of code.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
thanks for the enlightenment mike and olaf... i appreciate it... so i put everything in procedure init...

PROCEDURE Init

SET TALK OFF
SET BELL OFF
SET CENTURY ON
SET CONFIRM OFF
SET SAFETY OFF
SET ECHO off

SELECT 2
USE payments ALIAS pay
INDEX on idnum TO pidnumx

SELECT 1
USE sms ALIAS tsulat
INDEX on idnum TO idnumx

SET relation TO idnum INTO pay

ENDPROC

since i am knew to vfp 9, please teach me how to use lostfocus for my text1... thank you in advanced....
 
OK, you're getting closer, but still not quite there.

The Init is the right place for most of that code. But you should still not use the INDEX command, for the reason I explained earlier. You probably want to use SET ORDER instead. If you are not sure how to do that, look at the VFP Help file.

Also, issuing SELECT 1 and SELECT 2 is a bad idea, because it means that you will have to keep track of specific work area numbers. Better to do [tt]USE payments ALIAS pay IN 0[/tt] and [tt]USE sms ALIAS tsulat IN 0[/tt]. Then, when you want to select one or other of those tables, you can refer to them by their aliases: [tt]SELECT pay[/tt] and [tt]SELECT tsulat[/tt].

Finally, you asked how to use LostFocus. The answer is that you use it basically the same way as you used InteractiveChange. Except that now you only need to do the SELECT and SEEK commands in the LostFocus, because you have done everything else in the Init.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
thank you mike... i have followed your advise with sele 1 and sele 2.... thnaks... i still have one problem... how do i put the cursor again to text1 after getting idnumber? i need to get idnumber every after another... i have written program as...

PROCEDURE text1.lostfocus()

idcode = TRIM(this.value)

IF EMPTY(idcode)
=MESSAGEBOX("No record found in the Database",16,"Message not sent!")
RETURN
ENDIF

GO top

SEEK idcode

IF FOUND()
this.Parent.text1.value = TRIM(tsulat.idnum)
this.parent.text2.value = TRIM(tsulat.sname) + + "," + CHR(13) + TRIM(tsulat.fname)
this.Parent.text3.value = TRIM(tsulat.mobile)
this.Parent.text4.value = TRIM(tsulat.grade)
nctr = ctr

DO case
CASE ctr = 0
this.Parent.edit1.Value = this.parent.text2.value + " " + "is in, morning session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr + 1
replace ctr WITH nctr
CASE ctr = 1
this.Parent.edit1.Value = this.parent.text2.value + " " + "is out, morning session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr + 1
replace ctr WITH nctr
CASE ctr = 2
this.Parent.edit1.Value = this.parent.text2.value + " " + "is in, afternoon session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr + 1
replace ctr WITH nctr
CASE ctr = 3
this.Parent.edit1.Value = this.parent.text2.value + " " + "is out, afternoon session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr - 3
replace ctr WITH nctr
ENDCASE

ELSE
=MESSAGEBOX("No record found in the Database",16,"Message not sent!")

ENDIF

thisform.sms.sendsms(ALLTRIM(this.Parent.teXT3.Value),ALLTRIM(this.Parent.edit1.Value))
this.Parent.text1.value = " "
this.Parent.text2.value = " "
this.Parent.text3.value = " "
this.Parent.text4.value = " "


ENDPROC

* --------------------------------------------------------------------------
ENDDEFINE
 
You have skipped reading a lot of what I already wrote in your older thread.
If you set cursor back to text1, how will you ever get out of this endless loop?
Because even when you now don't want to send another SMS and just exit the form, the lostfocus will happen.

It's all been said, but in the end you can go into that pitfall and then see for yourself. rename this method to text1.valid() and the RETURN 0.

Bye, Olaf.



Olaf Doschke Software Engineering
 
It's still not quite right.

Your first message box is misplaced. The message will appear if the user loses focus from the control without entering anything, in other words, if the text box is empty. If the user clicks in the textbox and then - for whatever reason - clicks somewhere else, they will see the message. But doing that is not an error, and the user doesn't need to be told of the fact.

In any case, the wording of the message is wrong. An empty text box is not the same as "No record found in the Database".

Also, before you do the SEEK, you need to SELECT the relevant table. VFP is an event-driven system, and as such you can never be certain in what order the code will be executed. You don't know that some other event hasn't selected a different table, so you need to select it explicitly here.

And, for the same reason, it would be a good idea to SET ORDER TO the index just before the SEEK.

Finally - and less important - the GO TOP is unnecessary - but does no harm.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Big thanks olaf and mike... the program is now working as i wanted it to... yehey!!!

PROCEDURE text1.valid()

idcode = TRIM(this.value)

IF EMPTY(idcode)
=MESSAGEBOX("Id number is required!",16,"Message not sent!")
RETURN 0
ENDIF

SELECT 1

SEEK idcode

IF FOUND()
this.Parent.text1.value = TRIM(tsulat.idnum)
this.parent.text2.value = TRIM(tsulat.sname) + + "," + CHR(13) + TRIM(tsulat.fname)
this.Parent.text3.value = TRIM(tsulat.mobile)
this.Parent.text4.value = TRIM(tsulat.grade)
nctr = ctr

DO case
CASE ctr = 0
this.Parent.edit1.Value = this.parent.text2.value + " " + "is in, morning session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr + 1
replace ctr WITH nctr
CASE ctr = 1
this.Parent.edit1.Value = this.parent.text2.value + " " + "is out, morning session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr + 1
replace ctr WITH nctr
CASE ctr = 2
this.Parent.edit1.Value = this.parent.text2.value + " " + "is in, afternoon session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr + 1
replace ctr WITH nctr
CASE ctr = 3
this.Parent.edit1.Value = this.parent.text2.value + " " + "is out, afternoon session!" + " " + DTOC(DATE()) + " " + CDOW(DATE()) + " " + TIME()
nctr = ctr - 3
replace ctr WITH nctr
ENDCASE

ELSE
=MESSAGEBOX("No record found in the Database",16,"Message not sent!")
RETURN 0

ENDIF

thisform.sms.sendsms(ALLTRIM(this.Parent.teXT3.Value),ALLTRIM(this.Parent.edit1.Value))
= " "
this.Parent.text2.value = " "
this.Parent.text3.value = " "
this.Parent.text4.value = " "
this.Parent.text1.value = " "
RETURN 0
ENDPROC
 
By the way, Mandy, the meaning of returning 0 is move 0 controls in tab order. And in simple words stay in this control.

You'll have to have some exit situation, for example you could return .t. in the case of empty input. (.t. is the normal case and does not specify which control gets focus next, that can be any control clicked on, so use .t., not another number than 0, that'd enforce a specific control again, even if you click on something else, and would be an annoyance)

Also, I don't know if there is a glitch in posting your code, but ="" near the end means an error, perhaps this actually is This.Value="" to reset the input after each SMS was sent.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Thanks so much olaf... i have also realised what youve said, so i have .T. so that i could still exit.... the program is working so well now... the ="" at the last part was just a typo error, ive noticed it after you have told me... i dont know why it did not return an error everytime i run the program... anyway olaf thank you so much... please continue helping novice porgrammers like me...god bless.....

PROCEDURE text1.valid()

idcode = TRIM(this.value)

IF EMPTY(idcode)
=MESSAGEBOX("Id number is required!",16,"Message not sent!")
RETURN .t.
ENDIF

SELECT 1

SEEK idcode

IF FOUND()
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top