473,320 Members | 1,933 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

How do I loop through chosen types of controls on a form?

Seth Schrock
2,965 Expert 2GB
I'm trying to setup a class module that will allow me to pass the form name and the types of controls that I want tested (textboxes, comboboxes, etc.) and have it test if they are populated. My thinking is that I would have a parameter that would be something like TxtCboLstChkOpt and if I wanted to only check Textboxes and Checkboxes I would pass it 10010 as flags for the class to know which types to check. My problem is that I don't know how to only run the loop once and select those types that have a 1 in their section. Normally I would have this hard coded into a Select Case statement like the following:
Expand|Select|Wrap|Line Numbers
  1. For Each ctl in Controls
  2.     Select Case ctl.Type
  3.         Case acTextBox, acCheckBox
  4.             'Perform my checks
  5.  
  6.     End Select
  7. Next ctl
I don't want to have to test for the 32 different possible combinations of flags nor to I want to test each position and loop through all the controls once for each type of control for a total of five loops if all flags are checked.

I'm guessing that a bitwise comparison is going to be part of the answer, but I'm not very good with that. I wish that I could change the third line to be
Expand|Select|Wrap|Line Numbers
  1. Case If txt = True Then acTextBox, If cbo = True then acComboBox, etc.
so that it would add the control type to the case statement criteria. I'm just out of ideas. Hopefully I have worded my question clearly so you know what I'm looking for.
Oct 29 '13 #1

✓ answered by Rabbit

Are you using flags or checkboxes to determine what controls to check? Because the second block of code makes it sound like you want to use checkboxes.

Either way, you don't have to use select, I would just use 5 if statements for the 5 control types you want to check.
Expand|Select|Wrap|Line Numbers
  1. For Each ctl in Controls
  2.     If txt = True And ctl.Type = acTextBox Then
  3.         'Perform checks for textbox
  4.     Else If etc.
  5.     End If
  6. Next ctl

13 5055
NeoPa
32,556 Expert Mod 16PB
Unfortunately, the values of acTextBox, acComboBox, acListBox, etc are not powers of two, so cannot be used in the way you suspected. If you want to pass multiple values to a procedure or class method then you will need to use either an array or a string with value lists embedded within it.

PS. The control property you would want to check would be ControlType rather than Type.
Oct 29 '13 #2
Rabbit
12,516 Expert Mod 8TB
Are you using flags or checkboxes to determine what controls to check? Because the second block of code makes it sound like you want to use checkboxes.

Either way, you don't have to use select, I would just use 5 if statements for the 5 control types you want to check.
Expand|Select|Wrap|Line Numbers
  1. For Each ctl in Controls
  2.     If txt = True And ctl.Type = acTextBox Then
  3.         'Perform checks for textbox
  4.     Else If etc.
  5.     End If
  6. Next ctl
Oct 29 '13 #3
Seth Schrock
2,965 Expert 2GB
@Rabbit My plan for the second code block was to set boolean variable (txt, cbo) based on the flags. So your suggestion would then loop through all of the controls five times (once for each control type)?

@NeoPa I wasn't thinking that the values of acTextBox, acComboBox, etc were powers of two, but that I could use my flags to then choose which type of control to add to the list. You suggest using an array. Would it be something that I could add control types to the array based on my flag system and then have it loop through the list of types to see if it is supposed to check it (instead of the select case statement)? Using the example in the OP, my flag is set to 10010. I test the first character (textboxes) and it is set to true, so I add it to the array. I test the second character (comboboxes) and it is set to false so I don't add it to the array. I continue on through each type and I end up with Textboxes and Checkboxes in my array of types. So then inside each loop through the controls, I would then loop through the array to see if I'm supposed to check it. Would something like that work?

I'll fix the .Type to .ControlType.
Oct 29 '13 #4
Rabbit
12,516 Expert Mod 8TB
No, it's just one loop. It's like your switch, just using if statements.
Oct 29 '13 #5
Seth Schrock
2,965 Expert 2GB
I got it. I used your solution Rabbit, except that instead of using the ElseIF, I just made the criteria be
Expand|Select|Wrap|Line Numbers
  1. If (bTxt = True And ctl.ControlType = acTextBox) Or (bCbo = True And ctl.ControlType = acComboBox) Or _
  2.        (bLst = True And ctl.ControlType = acListBox) Or (bChk = True And ctl.ControlType = acCheckBox) Or _
  3.        (bOpt = True And ctl.ControlType = acOptionGroup) Then
So my final code that works is
Expand|Select|Wrap|Line Numbers
  1. Public Sub CheckControls(frm As String, TxtCboLstChkOpt As String, Optional tag As String = "req")
  2. Dim bTxt As Boolean
  3. Dim bCbo As Boolean
  4. Dim bLst As Boolean
  5. Dim bChk As Boolean
  6. Dim bOpt As Boolean
  7.  
  8. 'Check which control types to check
  9. bTxt = (Mid(TxtCboLstChkOpt, 1, 1) = 1)
  10. bCbo = (Mid(TxtCboLstChkOpt, 2, 1) = 1)
  11. bLst = (Mid(TxtCboLstChkOpt, 3, 1) = 1)
  12. bChk = (Mid(TxtCboLstChkOpt, 4, 1) = 1)
  13. bOpt = (Mid(TxtCboLstChkOpt, 5, 1) = 1)
  14.  
  15. Dim ctl As Control
  16.  
  17. For Each ctl In Forms(frm).Controls
  18.     If (bTxt = True And ctl.ControlType = acTextBox) Or (bCbo = True And ctl.ControlType = acComboBox) Or _
  19.        (bLst = True And ctl.ControlType = acListBox) Or (bChk = True And ctl.ControlType = acCheckBox) Or _
  20.        (bOpt = True And ctl.ControlType = acOptionGroup) Then
  21.  
  22.         If Forms(frm).Controls(ctl.Name).tag = tag Then
  23.  
  24.             If Forms(frm).Controls(ctl.Name).value & "" <> "" Then
  25.                 Forms(frm).Controls(ctl.Name).Controls.Item(0).ForeColor = vbBlack
  26.             Else
  27.                 Forms(frm).Controls(ctl.Name).Controls.Item(0).ForeColor = vbRed
  28.                 blnCompleted = False
  29.             End If
  30.  
  31.         End If
  32.     End If
  33.  
  34. Next ctl
  35.  
  36. End Sub
Thanks for all your help.

**EDIT: For those who would try to copy this code, the variable blnCompleted referenced in line 28 would need to be declared. I don't have it declared in this code because it was declared at the module level instead of at the procedure level.
Oct 29 '13 #6
ADezii
8,834 Expert 8TB
I was just running out the door and did not have time to read the entire Thread, so please forgive me if I am off course. Why not create a Public Function and pass to it a Reference to the Current Form as well as a number of Variable Control Types to be analyzed?
Expand|Select|Wrap|Line Numbers
  1. Public Function fEvalControls(frm As Access.Form, ParamArray varControls())
  2. Dim varControl As Variant
  3.  
  4. For Each varControl In varControls
  5.   Debug.Print frm.Name, varControl
  6.     Select Case varControl
  7.       Case acListBox
  8.         'Analyze for each specific Control Type on Form frm
  9.       Case acComboBox
  10.       Case acTestBox
  11.       Case acCheckBox
  12.       Case acSubform
  13.       Case acTabCtl
  14.       Case Else
  15.     End Select
  16. Next
  17. End Function
Expand|Select|Wrap|Line Numbers
  1. 'Pass to Function a Reference to the Form as well as any Control
  2. 'Types that you wish to analyze
  3. Call fEvalControls(Me, acTextBox, acListBox, acComboBox)
Expand|Select|Wrap|Line Numbers
  1. 'Form Name & Values of Control Type Intrinsic Constants
  2. Form1          109 
  3. Form1          110 
  4. Form1          111 
Oct 30 '13 #7
Seth Schrock
2,965 Expert 2GB
Unless I'm misunderstanding you, that is basically what I'm doing. However, your code will always check for the six control types that you have listed even if you didn't call for it to. Whereas mine checks to see if that control type is supposed to be checked before doing anything with it. Eventually, I'm going to expand the capabilities of the procedure to include which required controls were empty in the message box that will be shown the user, but that can wait as it isn't needed for my current project.

My main goal was to make it so that I could just copy the module to any of my programs and have it work instead of having to create it for each form. Yours would allow me to do the same thing I believe, but, from my understanding of the code, yours doesn't quite do what I was wanting. Also, the same check is performed for each control type selected, so I don't need to have each control type be a separate case.
Oct 30 '13 #8
ADezii
8,834 Expert 8TB
Guess I was off course (LOL)! You can always Redimension an Array of checked Control Types and Pass that to the Function instead, this will eliminate the checking of ALL Control Types, or those specified in ParamArray().
Oct 30 '13 #9
NeoPa
32,556 Expert Mod 16PB
I think maybe I wasn't following the question as clearly as I could have either :-(

If you want to specify something (like a procedure parameter), so it is entirely under your own control, then a bit flag value should work fine for you. IE. A value of 18 (10010 binary) would indicate that two of the five control types (The two you allocate to those positions) should be checked for or processed.

Personally, when multiple options need to be coded, I prefer the Select Case statement over multiple If Then Elses as it's neater code, even though it may not necessarily produce the most efficient compiled code. That said, that's a matter of style rather than the ability of the code to work correctly.

With the 5-bit value it is certainly possible to use it as separate bit-flags. To code that you can use something like the following :
Expand|Select|Wrap|Line Numbers
  1. Select Case True
  2. Case (intX And &H10) = &H10
  3. ...
  4. Case (intX And &H8) = &H8
  5. ...
  6. Case (intX And &H4) = &H4
  7. ...
  8. Case (intX And &H2) = &H2
  9. ...
  10. Case (intX And &H1) = &H1
  11. ...
  12. End Select
This illustration uses hex literal values, but in real code I would normally use constants defined to represent these. intX is the value you're testing of course.
Nov 1 '13 #10
Seth Schrock
2,965 Expert 2GB
Horray! I think that I have finally figured out bitwise comparison and it usage thanks to your last post NeoPa. I think that I will stick with my single If/Then statement as it puts all the criteria in one condition making it so that I don't have to write my control checking code multiple times (or the procedure calling code if I set the control checking code in its own procedure). However, I am going to use bitwise comparison to set my boolean variables. I just setup and enum to hold the values of the control types as I have ordered them.
Expand|Select|Wrap|Line Numbers
  1. Public Enum cTypes
  2.     txt = 16
  3.     cbo = 8
  4.     lst = 4
  5.     chk = 2
  6.     opt = 1
  7. End Enum
I then have my procedure using bitwise comparison to set my variables.
Expand|Select|Wrap|Line Numbers
  1. Public Sub CheckControls(frm As String, TxtCboLstChkOpt As Long, Optional tag As String = "req")
  2. Dim bTxt As Boolean
  3. Dim bCbo As Boolean
  4. Dim bLst As Boolean
  5. Dim bChk As Boolean
  6. Dim bOpt As Boolean
  7. Dim ctl As Control
  8.  
  9.  
  10. 'Check which control types to check
  11. bTxt = (TxtCboLstChkOpt And txt)
  12. bCbo = (TxtCboLstChkOpt And cbo)
  13. bLst = (TxtCboLstChkOpt And lst)
  14. bChk = (TxtCboLstChkOpt And chk)
  15. bOpt = (TxtCboLstChkOpt And opt)
  16.  
  17.  
  18. 'Mark controls that are required and empty
  19.  
  20. For Each ctl In Forms(frm).Controls
  21.     If (bTxt = True And ctl.ControlType = acTextBox) Or (bCbo = True And ctl.ControlType = acComboBox) Or _
  22.        (bLst = True And ctl.ControlType = acListBox) Or (bChk = True And ctl.ControlType = acCheckBox) Or _
  23.        (bOpt = True And ctl.ControlType = acOptionGroup) Then
  24.  
  25.         With Forms(frm).Controls(ctl.Name)
  26.  
  27.             If .tag = tag Then
  28.  
  29.                 '.Controls.Item(0) refers to the attached label
  30.                 If .value & "" <> "" Then
  31.                     .Controls.Item(0).ForeColor = okColor
  32.                 Else
  33.                     .Controls.Item(0).ForeColor = errColor
  34.                     blnCompleted = False
  35.                 End If
  36.  
  37.             End If
  38.  
  39.         End With
  40.  
  41.     End If
  42.  
  43. Next ctl
  44.  
  45. End Sub
and to call my code, I just add the enumed values together.
Expand|Select|Wrap|Line Numbers
  1. Dim verifyFields As clsRequired
  2. Set verifyFields = New clsRequired
  3. verifyFields.CheckControls Me.Name, txt + chk
The only issue that I'm having now is that it didn't like it when I put the enum in the class module, so I had to put it in a regular module. This kind of defeats the idea of having a self contained class module that I can just copy and paste between projects and it works. Now I have to remember to go copy the enum as well. I'll continue looking online for a solution to this and start a new thread here if I can't find anything.

Thanks NeoPa.
Nov 1 '13 #11
NeoPa
32,556 Expert Mod 16PB
Always a pleasure Seth :-)

However - bTxt will never be True. bTxt may trigger the True side of an If or IIf(), but that is not the same as bTxt = True (because True is a specific numeric value of -1 - or Hex FFFF). It is necessary to test this correctly when the values returned are not exactly equal to True.

You may get away with it as Access, in some newer versions, may assign True whenever the value to be assigned is non zero, but this is an area where care is necessary - even if that is simply to make the code more clearly readable. I hope this makes sense.
Nov 2 '13 #12
Seth Schrock
2,965 Expert 2GB
Once again you have caught me with that. But I think that I understand it more this time having seen that, say 18 AND 16 = 16 and not just a "True". I guess I was assuming that since bTxt was a boolean variable that it would take on the value of "True" when assigned anything other than 0. However, I do like to code "right" and not necessarily just what works (which it does work as I've tested it).
Nov 2 '13 #13
NeoPa
32,556 Expert Mod 16PB
I guess I was assuming that since bTxt was a boolean variable that it would take on the value of "True" when assigned anything other than 0.
It seems you're quite right on that score Seth. Boolean variables only allow boolean values it seems.

IE.
Expand|Select|Wrap|Line Numbers
  1. If 18 = True Then FAILS
  2.  
  3. bTxt = 18
  4. If bTxt = True Then SUCCEEDS
Nov 2 '13 #14

Sign in to post your reply or Sign up for a free account.

Similar topics

2
by: CLarkou | last post by:
Is there any other way of looping in the fields of records in a Datasheet form, except from the following one (moving to each record) for checking the field values ? For I = 1 To var_end_R...
2
by: Calvin KD | last post by:
Hi everyone, I'd like to interrogate a web form to check for values of the controls on the form. The following codes worked when I execute it in a User Control that has some web controls on it but...
21
by: Kevin L | last post by:
I have the following loop: Dim objPanel As Panel For Each objPanel In Me.Controls 'do something here Next
2
by: Kay | last post by:
Hi all, I have a 42 groupboxes in a panel, each groupbox has 3 check boxes in it. The 42 groupboxes are actually in a panel, and the panel is on the second tab page of a tab control... What...
6
by: be.special | last post by:
hi! i have a class chooseLevel : Form and i need to loop over all the radio buttons that are on my form, and check their text. if their text is smaller than 4, i got to disable them. how do i do...
9
by: netasp | last post by:
hi all, how can I populate one aspx form when page is loading based on page ID? for example: loading page A (to search for VB code) would display labels and texboxes, dropdown lists all related...
1
by: emlj001 | last post by:
I have a form that starts at page, http://www.scmeachoraldiv.org/allstate/registration/default.asp My problem is on the page http://www.scmeachoraldiv.org/allstate/registration/part2.asp I...
3
PAHSTeacher
by: PAHSTeacher | last post by:
I have programmed recreationally in VBA for a few years. I am making a simple website with Visual Web Developer 2005 (ASP.NET), using VB (for the first time). I would like to loop through all of...
3
AHayes
by: AHayes | last post by:
_Background I'm attempting to build a C# Windows application for work where I need to dynamically create and remove menu items (buttons). I've figured out how to dynamically create and (I think)...
7
by: bigukfan | last post by:
I have a single form with a Tab Control containing 15 tabs. Various Text Boxes and Combo Boxes on each Tab. The Form is unbound. I want to use the KeyPress Event on the Tab Control to loop through...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.