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!

Check boxes 3

Status
Not open for further replies.

Mandy_crw

Programmer
Jul 23, 2020
578
PH
Hi everyone... may i ask help how to do or solve a problem...I have five checkboxes namely all, pre-elem, elem, jhs and shs... or use do case of iif? if i want, first

All.... NEED TO SCAN ALL RECORDS​
Pre-Elem... Need to scan having code = substr(code,1,1)​
Elem... need to scan having int(val(code)) =< 6​
Jhs... need to scan having int(val(code)) =>7 or int(val(code)) =< 10​
Shs... need to scan having int(val(code)) => 11 or int(val(code)) =<12​

there are no problem with that... my problem is.... what if the user would click combination, like jhs and shs, or pre-elem and elem or elem and jhs os shs... and so on and so forth? would that be possible? if so? please teach me how... thank you everyone... I tried, but the output is not accurate... God bless
 
This is a matter of dynamically building a condition clause. Something like this:

Code:
lcCondition = " .T. "
IF thisform.pre_elem
    lcCondtion = lcCondition +  " AND code = substr(code,1,1) "
ENDIF
IF thisform.elem
  lcCondtion = lcCondition +  " AND int(val(code)) =< 6) "
ENDIF
IF thisform.jhs
  lcCondtion = lcCondition +  " AND int(val(code)) =>7 or int(val(code)) =< 10  "
ENDIF
IF thisform.shs
  lcCondtion = lcCondition +  " AND  int(val(code)) => 11 or int(val(code)) =<12 "
ENDIF

Once have assembled the condition, you can add it to either SCAN FOR, or SET FILTER TO or SELECT ... WHERE. For example:

Code:
lcCommand = "SCAN FOR " + lcCondition

then execute the command:
Code:
&lcCommand

This is very much off the top of my head. It might not be 100% correct, but I hope it will put you in the right direction.

By the way, you can't use DO CASE here because the various conditions are not mutually-exclusive.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I don't understand what all that means and how it should work but let's put that aside, I'm sure you know.

I can contribute that a checkbox in itself can be true or false, so several checkboxes will be able to be any combination. If you want a user to only pick one of the five options all,pre-elem,elem,jhs,or shs, then an optiongroup is the solution to that, and the optiongroup value will be between 1 and 5, picking just one of them and never two or more at the same time.

You should be able to decide whether you want the user to check multiple options or just one of them. That's deciding whether to use an optiongroup with 5 options (1 choice) or 5 checkboxes (any combination possible).

Chriss
 
Chris, what you say is perfectly correct of course. But I noticed that Mandy said "what if the user would click combination" (my emphasis), which led me to assume that she needed a set of checkboxes.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hi Mike and Chriss.... this is what i have done... is this correct?

A = this.Parent.text8.value && All
B = this.Parent.text9.value && Pre-Elem
C = this.Parent.text10.value && Elementary
D = this.Parent.text11.value && JHS
E = this.Parent.text12.value && SHS

DO CASE
CASE A = 1 AND B = 1 AND C = 1 AND D = 1 AND E = 1 && All
MyScan = "INT(VAL(tsulat.CODE)) =>1 or SUBSTR(tsulat.CODE,1,1) = 'K'"
CASE A = 0 AND B = 1 AND C = 0 AND D = 0 AND E = 0 && Pre-Elem
MyScan = "SUBSTR(tsulat.CODE,1,1) = 'K'"
CASE A = 0 AND B = 1 AND C = 1 AND D = 0 AND E = 0 && Pre-Elem & Elementary
MyScan = "INT(VAL(tsulat.CODE)) => 1 and INT(VAL(tsulat.CODE)) =< 6 or SUBSTR(tsulat.CODE,1,1) = 'K'"
CASE A = 0 AND B = 1 AND C = 0 AND D = 1 AND E = 0 && Pre-Elem & JHS
MyScan = "INT(VAL(tsulat.CODE)) => 7 and INT(VAL(tsulat.CODE)) =< 10 or SUBSTR(tsulat.CODE,1,1) = 'K'"
CASE A = 0 AND B = 1 AND C = 0 AND D = 0 AND E = 1 && Pre-Elem & SHS
MyScan = "INT(VAL(tsulat.CODE)) => 11 and INT(VAL(tsulat.CODE)) =< 12 or SUBSTR(tsulat.CODE,1,1) = 'K'"
CASE A = 0 AND B = 0 AND C = 1 AND D = 0 AND E = 0 && Elementary
MyScan = "INT(VAL(tsulat.CODE)) => 1 and INT(VAL(tsulat.CODE)) =< 6"
CASE A = 0 AND B = 0 AND C = 1 AND D = 1 AND E = 0 && Elementary & JHS
MyScan = "INT(VAL(tsulat.CODE)) => 1 and INT(VAL(tsulat.CODE)) =< 10"
CASE A = 0 AND B = 0 AND C = 1 AND D = 0 AND E = 1 && Elementary & SHS
MyScan = "INT(VAL(tsulat.CODE)) => 1 AND INT(VAL(tsulat.CODE)) =< 6 OR INT(VAL(tsulat.CODE)) => 11"
CASE A = 0 AND B = 0 AND C = 0 AND D = 1 AND E = 0 && JHS
MyScan = "INT(VAL(tsulat.CODE)) => 7 and INT(VAL(tsulat.CODE)) =< 10"
CASE A = 0 AND B = 0 AND C = 0 AND D = 1 AND E = 1 && JHS & SHS
MyScan = "INT(VAL(tsulat.CODE)) => 7 and INT(VAL(tsulat.CODE)) =< 12"
CASE A = 0 AND B = 0 AND C = 0 AND D = 0 AND E = 1 && SHS
MyScan = "INT(VAL(tsulat.CODE)) => 11 and INT(VAL(tsulat.CODE)) =< 12"
OTHERWISE
MyScan = "UPPER(ALLTRIM(this.Parent.CboCode.value)) = UPPER(ALLTRIM(tsulat.CODE))"
ENDCASE
 
Mandy, at first glance I would say that your code should work - or, at least, it will get you close. But it is clearly much longer and more convoluted than the code I suggested. Did you have a good reason for going down that route?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Actually Mike i have done this before I'va ask this forum, because i wanted to learn more professional approach... just like you did... I saw that my code seem to look not "professional"... still trying to digest Mike and honestly I do have plans of changing my code to what you have suggested Mike... Thank you always...
 
Well,

I can't judge if all the cases are right, but you're using a textbox and inputs are either 0 or 1, that's covered by a checkbox.
You allow some cases, but not all combinations. There would be 2^5=32 combinations of 1s and 0s a user could combine. The cases you don't cover with a specific CASE are covered by OTHERWISE, though.

Well, one thing that seems odd to me is that you A=1 is "all" by the meaning of your textboxes, but your CASE for "all" is A=1 AND B=1 AND C=1 AND D=1 AND E=1. I think that's ill logic. Either you have one textbox the user can set 1 to mean "all" or there is no such textbox and only setting all textboxes to 1 means "all".

Also, no matter if there is a single choice of "all" or only setting all choices to 1 means "all". Merely by the language meaning of "all" I would expect the scan condition to be none or just ".T.", that is, you scan all records, no record is excluded. But I can't help you with the meaning of things.

Once more, you give too little information to judge this as correct or not. The only thing I would change in this constrct is use checkboxes, not textboxes. The can toggle between 0/1 or toggle between .F. or .T., that's your choice. With the code as given you would need the checkbox values to be 0 or 1, too, but you could simple use A,B,C,D,and E as .T. or .F. values without comparing them to 1 or 0, if you use checkboxes toggling between .F. and .T.

Changing from textboxes to checkboxes won't change that code very essentially and it will still feel like the same mess, but we can't help you without knowing the meanings you don't share. but one thing qualitatively improves with checkboxes instead of textboxes: You could enter any number into a textbox, not just 0 or 1, in a checkbox you can only toggle between the two values. (For the experts knowing there is a triple-state when allowing null: W ell you simply don't allow that, init all checkboxes with .f. or 0 and they toggle between two states only).

Chriss
 
Mandy,

what Mike didn't look into is, your conditions never make sense together.
A number can never be both between 7 and 10 and between 11 and 12. Because those intervals don't overlap.

In this sense, you would never set two conditions to .t. or 1, as they would yield no result together, they would need to be picked exclusively, as separate options, never as combinations.

So I would conclude here, your problem isn't elegant or not elegant code, but first getting a grip on the conditions you really need and understanding their implications, before thinking about picking controls or writing code. More elegant code doesn't turn a wrong into a right.

I could think of many things that would fit, it could rather be a question of min and max limits than of combining multiple conditions, the condition is the same in all cases, just with varying lower and upper bounds. But you need to explain what things mean to get a good answer.

If it's all about the spans of values, what's questionable is that you store values in a char field and need the substring function instead of storing numbers. And overall the condition would just be something along the lines of min<=code<=max with varying min and max values. And that's also were professional design comes into play, at the basis, the design of the data, for example.

Chriss
 
what Mike didn't look into is, your conditions never make sense together.
A number can never be both between 7 and 10 and between 11 and 12. Because those intervals don't overlap.

It's true I didn't notice that. That changes things a little. To cover those last three conditions, an option group with three options would clearly be better.

I suggest you have a checkbox for ALL, another checkbox for Pre-Elem, and the three option buttons for Elem, Jhs and Shs respectively. Start with all of those except the ALL checkbox disabled, and with the ALL checkbox set to .T. If the user un-ticks ALL, then enable the other controls. The user would then check or uncheck Pre-Sch, and choose one of the options for the other three.

In that case, you could still use my code as a model, but it would be simpler. If the user specified ALL, you won't need a filter condition - just do a straight SCAN or whatever. Otherwise, you can build the condition from the other checkbox and the option group.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Seems to me this is an issue of which levels of student should be included. When multiple checkboxes are checked, we want students from all those levels. So any condition combining the different checkboxes wants to be OR.

I think Mike Lewis is on the right track above, but I think all his ANDs and ORs need to be switched.

FWIW:

Pre-Elem = pre-school (kids under 5)
Elem = grade school, looks like here that's grades 1 through 6
Jhs = junior high school, here grades 7 and 8
Shs = senior high school, grades 9 and up

Tamar
 
Hi Mike, Chris, and Tamar... Thank for all your answers, it was really helpful... I like to explain more... For the "all" when clcik, all checkboxes will be automatically click, but i cant use scan because in the table there are codes "F" "U" and "P" which should not be included...
FOR CODES
PRE-Elem are K,K1,K2
Elem are 1,2,3,4,5,6
Jhs are 6,7,8,9,10
Shs are 11,12

Thank experts for helping me out always... God bless..
 
Okay, I see. So this is driven by your school system.

For database purposes I'd store the codes, but work with a column "class" which I'd set to K=-2, K1=-2, K2=0, so extend 1-12 to negative numbers and the interval -2 to 12.Then you have a number you can use to make queries only comparing numbers.

The way it is your conditions for pre-elementary is Left(Code,1)="K", or val(code)=0, as VAL() of anything not starting with a digit is 0.

Otherwise it's val(code) you compare with numbers from 1 to 12, maybe int(val(code)), it doesn't make it a better value, though, not even if you compare with an integer table field. If VFP works on numbers, it's always double float anyway. So overall val(code) is enough for you to work with for the classification of theschool classes.

Chriss
 
You could turn this upside down.

Compute the class number from -2 to 12 as I suggested from the code like that:
class = ICase(code='K ',-2,code='K1',-1,code='K2',0, val(code)=0, 999, val(code))

Then compute levels of P,E,J,S from the code like that:
level = ICase(class<=0,'P',class<=6,'E',class<=10,'J',class<=12,'S','X')

Then you can combine the picked levels to a string, say 'PS' for all students pre-elementary or senior high and find them with the condition level $ 'PS'. You could combine any school levels. In other words, the classification deserves to be computed from the code you have stored, so it is simply a single value, like a char(1) and you can then easily make a filter condition from it.

Chriss
 
Yes Chriss.... Thank you so much... I'll try this... to make my code more professional looking... [bigsmile] God bless....
 
Notice these two ICASE expresions take into account quirky circumstances.

Val(code) should only be 0 if a code starts with 'K', and those cases with K are covered by the first part of ICase, if val(code)=0 in the third Icase condition, then this is wrong. So I translate that to class=999 which doesn't exist. This is done to mark cases where the code field should be inspected for correctness. If you have other cases in code that are valid, too, you might need to adapt this to your needs.

In the second ICase, I don't end with senior high school students for the last value in the ICASE() which is the result for "anything else", but I check their class is only up to 12 and will compute 'X' for anything above 12. So a level 'X' again indicates a data error. You could also add a portion for class values below -2 and mark them as 'X', too. I didn't do that as I don't think any of your codes start with a negative number in themselves, the only negative class value comes from the translation of K, K1, or K2, so every level up to 0 is pre-elementary.

I wouldn't mind, if you have questions about how to implement this, it's not that straightforward, but an index might help, at least on the expression ICase(code='K ',-2,code='K1',-1,code='K2',0, val(code)=0, 999, val(code)) with a tag "class". Computing that then is done with any insert or update of table data, so it's a value VFP can read or find in the index and doesn't need to compute this within scans or queries, as it's always already computed and part of the CDX file.

An index in the second ICase(class<=0,'P',class<=6,'E',class<=10,'J',class<=12,'S','X') is not possible, as class isn't a field. And I wouldn't even try to replace every "class" by the first Icase.

I also don't mind, if you don't get this. It just would be ideal if you would have fields class and level in your table, in which these values are stored and thus simply available just like code is an available field. BEcause code in itself is not easy to translate into the levels from pre-elementary up to senior hight.

Chriss
 
Hi Mandy,

... and a little demo how you could approach this problem

Code:
goForm = CREATEOBJECT("frmForm")
goForm.Visible = .T.
goForm.Show()

READ EVENTS

CLOSE ALL
CLEAR ALL 

RETURN

**********

DEFINE CLASS frmForm as Form

AutoCenter = .T.
BorderStyle = 2
Width = 540
MinWidth = 540
MinButton = .F.
MaxButton = .F.
ShowTips = .T.
Themes = .F.

*!*	Add the visual elements

	ADD OBJECT lblCHKAll as Label WITH Left = 12, Top = 12, Caption = "All"
	ADD OBJECT lblCHKGA as Label WITH Left = 102, Top = 12, Caption = "Grade A"
	ADD OBJECT lblCHKGB as Label WITH Left = 192, Top = 12, Caption = "Grade B"
	ADD OBJECT lblCHKGC as Label WITH Left = 282, Top = 12, Caption = "Grade C"

	ADD OBJECT chkAll as CheckBox WITH Top = 36, Left = 12, AutoSize = .T., Value = .T., Caption = "All"
	ADD OBJECT chkGrA as CheckBox WITH Top = 36, Left = 102, AutoSize = .T., Value = .F., Caption = "Grade A"
	ADD OBJECT chkGrB as Checkbox WITH Top = 36, Left = 192, AutoSize = .T., Value = .F., Caption = "Grade B"
	ADD OBJECT chkGrC as Checkbox WITH Top = 36, Left = 282, AutoSize = .T., Value = .F., Caption = "Grade C"

	ADD OBJECT cmdFilter as CommandButton WITH ;
		Left = 426, ;
		Top = 12, ;
		Height = 42, ;
		BackColor = RGB(0, 255, 255), ;
		Caption = "Show Selection"

	ADD OBJECT grdSchool as Grid WITH ;
		Left = 12, ;
		Top = 60, ;
		Width = ThisForm.Width - 24, ;
		Height = ThisForm.Height - 84, ;
		DeleteMark = .F., ;
		Visible = .F.
		
*!*	Now the procedures:
*!*	Uncheck all other checkboxes if ALL is checked

		PROCEDURE chkAll.Click() 
			FOR i = 1 TO ThisForm.ControlCount
				IF AT(UPPER("chkGr"), ThisForm.Controls(i).Name) != 0
					
					ThisForm.Controls(i).Value = .F.
					
				ENDIF
			ENDFOR
		ENDPROC 
		
*!*	Uncheck the ALL checkbox if you check any other checkbox

		PROCEDURE chkGrA.Click()
			ThisForm.CheckBoxClick()
		ENDPROC
		
		PROCEDURE chkGrB.Click()
			ThisForm.CheckBoxClick()
		ENDPROC

		PROCEDURE chkGrC.Click()
			ThisForm.CheckBoxClick()
		ENDPROC
		
*!*	Filtering the data and showing the results
			
		PROCEDURE cmdFilter.Click()
			LOCAL lcFilter as Character
			lcFilter = ""
				
			IF ThisForm.chkAll.Value = .T.
				SELECT * FROM csrSchool INTO CURSOR csrFilter
					
			ELSE 

				IF ThisForm.chkGrA.Value = .T.
					lcFilter = "csrSchool.cGrade = [A] OR "
				ENDIF

				IF ThisForm.chkGrB.Value = .T.
					lcFilter = lcFilter + "csrSchool.cGrade = [B] OR "
				ENDIF

				IF ThisForm.chkGrC.Value = .T.
					lcFilter = lcFilter + "csrSchool.cGrade = [C]"
				ENDIF

				IF RIGHT(lcFilter, 3) = "OR "
					lcFilter = Substr(lcFilter, 1, Len(lcFilter) - 4)
				ENDIF 

				IF EMPTY(lcFilter)
					= MESSAGEBOX("Please check at least one option", 64, "Show selected data", 3000)
					
				ELSE 
					SELECT * FROM csrSchool WHERE &lcFilter INTO CURSOR csrFilter

				ENDIF 
			ENDIF 
			
			IF ALIAS() = UPPER("csrFilter")
				WITH ThisForm.grdSchool
					.BackColor = RGB(0, 255, 255)
					.ColumnCount = -1
					.RecordSource = "csrFilter"
					.Visible = .T.

					WITH .Column1
					  .Header1.Caption = "Name"
					  .Width = 90
					ENDWITH

					WITH .Column2
					  .Header1.Caption = "Grade"
					  .Width = 60
					ENDWITH
				ENDWITH 			
			ENDIF
		ENDPROC 
				
	PROCEDURE Load()
	
		CREATE CURSOR csrSchool (cName C(10), cGrade C(1))
		
		INSERT INTO csrSchool VALUES ("Mandy", "A")
		INSERT INTO csrSchool VALUES ("Jeff", "B")
		INSERT INTO csrSchool VALUES ("Chris", "C")
		INSERT INTO csrSchool VALUES ("Sandy", "B")
		INSERT INTO csrSchool VALUES ("Mickey", "C")
		INSERT INTO csrSchool VALUES ("Paolo", "B")
		INSERT INTO csrSchool VALUES ("Paula", "A")
		
		LOCATE 
		
	ENDPROC 
	
	PROCEDURE Destroy()
		ThisForm.Release()
		CLEAR EVENTS
	
	ENDPROC 

	PROCEDURE CheckBoxClick()
		ThisForm.chkAll.Value = .F.
	ENDPROC 
	
ENDDEFINE 
**********

Enjoy

MarK
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top