I am seeing behaviour regarding checkboxes on a form which seems really weird, and I'm wondering if anyone else has come across it and can explain it.
Here's the form, which is bound to a table called FrequencyCodes:
Although the form is bound, the checkboxes are unbound. On the Form's load event they are populated by a procedure which reads a comma-separated string (in the column "CleaningDays") of numbers from 1-7, checking boxes appropriately. Here's that code:
Dim ctl As Control
For Each ctl In Me.Controls
If TypeOf ctl Is CheckBox Then
ctl.Value = InStr(1, Me.CleaningDays & ",", Right(ctl.Name, 1) & ",")
End If
Next ctl
The idea is that if a pattern of "One or more times per week" is chosen, the specific days can then be selected. For reasons of visual consistency with the option buttons above (for the cleaning pattern), I added an option group control to group the checkboxes together visually. I added the checkboxes, then so that I could select multiple options (which obviously isn't possible if they're part of an Option Group, I cut the checkboxes from the form, pasted them elsewhere on the form and then dragged them back into position. This resulted in a set of "standard" checkboxes, with possible values of true or false, rather than option values of 1 - 7 or whatever, had they been part of the option group. Here's the property sheet for one of them:
I then created code which, on the Click event of the OK button, loops through the checkboxes, and by using the last character of their names (they're called chk1 - chk7) builds a comma-separated list of the days when cleaning happens.
Here's the code:
Dim ctl As Control
Dim Output As String
For Each ctl In Me.Controls
If TypeOf ctl Is CheckBox
If (ctl = True) Then
Output = Output & Right(ctl.Name, 1) & ","
End If
End If
Next ctl
If Output <> vbNullString Then
Debug.Print "String calculated was " & Left(Output, Len(Output) - 1)
ReadCheckBoxes = Left(Output, Len(Output) - 1)
Else
ReadCheckBoxes = vbNullString
End If
The form wasn't working as expected, so I did some testing. The checkboxes weren't seeming to return Booleans (or 1 and 0) as expected.
You can see from the screenshot above that in this particular test, I'd selected options for Monday - Friday (chk2 - chk6 should have a value of true).
However, here's what I found from doing some testing in the immediate window:
? chk1
0
?chk2
-1
?chk3
-1
?chk4
1
? chk5
-1
?chk6
3
?chk7
0
Now, I know that any non-zero value equates to true, and that therefore these values should work. But they weren't. I was finding that on click on OK, only changed values would be recorded correctly - so, if, when the form was loaded, Monday - Friday were ticked, and I then tick Saturday before clicking OK, only chk7 (Saturday) would be recorded as being selected.
Can anyone explain this behaviour to me? I can't see the OptionValue property which I'd expect to see if these checkboxes were still part of an option group, yet this seems to be the value being returned.
Thank you!
When you set the checkboxes values, you don't set True or False, because InStr() returns the string position.
I suggest this to convert the result into a boolean:
ctl.Value = (InStr(1, Me.CleaningDays & ",", Right(ctl.Name, 1) & ",") > 0)
And when reading them, to be on the safe side:
If (ctl.Value <> False) Then
Related
I have an Access 2016 database that stores a very large list of parts. On a form, the user can select options to mark a part as in stock, among other things.
Here I have 3 combo boxes. The first allows the user to select a batch - this has no impact on the part selection, it will be used to record where the part came from. Second is part category. Updating it triggers a refresh on the part type to filter the database for that specific category.
Updating the third combo box triggers a WebBrowserControl to change its SourceControl to display the image of that part. (There are tens of thousands of potential parts - I don't want to package their images with the db and thumbnails are available on the web)
It works, but the weird thing is that doing so resets the 2nd and 3rd combo box to null. That kinda messes up me getting that data into the database later. I can't figure out why. Here's the AfterUpdate code for cb 2 & 3:
Private Sub ChooseCatName_AfterUpdate()
Me.ChoosePartType = ""
Me.ChoosePartType.Requery
Me.ChoosePartNum = ""
Me.wb_partImg.Visible = False
End Sub
Private Sub ChoosePartType_AfterUpdate()
imgUrl = getImgUrl(Me.ChoosePartType)
If imgUrl = "" Then
Me.wb_partImg.Visible = False
Exit Sub
End If
imgUrl = imgUrl & "/85x85p." & Right(imgUrl, 3)
Me.wb_partImg.ControlSource = "=""" & imgUrl & """"
Me.wb_partImg.Visible = True
End Sub
Note: getImgUrl just returns a string - the url based on the part number
So - why would ChooseCatName and ChoosePartType change to null as soon as the wb_partImg.ControlSource is changed??
In my Access form I have a ComboBox that allows multiple selection. I would like to see if a certain item is selected. How to do?
It would be great if exists something like:
if Me.<ComboBox name>.Options.<Item_5>.Selected = True Then
msgbox "it is included"
End If
When the Control Source of the ComboBox points to a field which may contain multiple values, the Value property of the ComboBox returns an array.
Therefore, the task is reduced to testing whether the array contains the item in question, which may be achieved using the following (amongst other ways):
InStr(1, Join(<ComboBoxName>.Value, ","), <Item_5>) > 0
EDIT: Following Erik's comment, the below may be a more appropriate way to test for the presence of the item:
Dim itm As Variant
Dim rtn As Boolean
For Each itm In <ComboBoxName>.Value
If itm = <Item_5> Then
rtn = True
Exit For
End If
Next itm
If rtn Then MsgBox "Item is included"
Having a bit of trouble. I have a simple situation: 2 Radio buttons, Accept or Reject. Instead of doing IF statements I feel an obligation to do Select statements.
As I walk through my code, it gets to the Case rdbApprove.Value and complains that the value is null. I figure it isn't true, thus it should pass to the next Case. Nope - it hangs on the fact that it is null.
In an effort to try and get rid of the null value I tried the NZ(rdbApprove.Value, False) to try and tell it that it was false but that still isn't working.
Select Case True
Case rdbApprove.Value
Case rdbReject.Value
Case Else
MsgBox "ERROR!"
End Select
The usual way this is done is to include your radio buttons in an option group. Then your code can reference the option group .Value.
My form includes an option group named Frame15 which includes an "Approve" radio button whose Option Value is 1, and a "Reject" button whose Option Value is 2.
I also added a command button to inspect the option group .Value. Here is its click event procedure.
Private Sub cmdOptionValue_Click()
Dim strPrompt As String
Select Case Me.Frame15.value
Case 1
strPrompt = "approved"
Case 2
strPrompt = "rejected"
Case Else
If IsNull(Me.Frame15.value) Then
strPrompt = "Null"
Else
strPrompt = "this should not happen"
End If
End Select
MsgBox strPrompt
End Sub
I have a list box that I populate with a Table/Query and "select" multiple entries with a bit of VBA code. On Form_Current, I intend for the code to select whatever items in that listbox that are selected for the current record (saved in another table).
When I click to go to the next record, the previously selected list box items are still selected. How do I clear them? I would have thought a new record would do all of this for me automatically.
I'm just getting back into VBA for the first time in 12 years, so I'm no guru.
Thanks,
Hans
Try this (found here):
Function ClearList(lst As ListBox) As Boolean
On Error GoTo Err_ClearList
'Purpose: Unselect all items in the listbox.
'Return: True if successful
'Author: Allen Browne. http://allenbrowne.com June, 2006.
Dim varItem As Variant
If lst.MultiSelect = 0 Then
lst = Null
Else
For Each varItem In lst.ItemsSelected
lst.Selected(varItem) = False
Next
End If
ClearList = True
Exit_ClearList:
Exit Function
Err_ClearList:
Call LogError(Err.Number, Err.Description, "ClearList()")
Resume Exit_ClearList
End Function
Such a simple question, but I cannot find the answer (Google, MS help, SO):
How can I check by VBA whether an unbound checkbox on an Access form is checked by the user or not? Can't find the right property.
UPDATE:
I used this code after the suggestions of #HansUp and #RC:
Private Sub CmdTest_Click()
MsgBox "Check1.Value = " & Me.Check1.Value
MsgBox "Check2.Value = " & Me.Check2.Value
End Sub
Private Sub Form_Load()
Me.Check1.Value = 25
Me.Check2.Value = 50
End Sub
2nd UPDATE:
The code should be this (thanks to #David-W-Fenton):
Private Sub CmdTest_Click()
If Me.Check1 = True Then
MsgBox "Check1 IS CHECKED"
Else
MsgBox "Check1 IS NOT CHECKED"
End If
If Me.Check2 = True Then
MsgBox "Check2 IS CHECKED"
Else
MsgBox "Check2 IS NOT CHECKED"
End If
End Sub
Private Sub Form_Load()
' set first checkbox default checked
Me.Check1.Value = True
' set second checkbox default unchecked
Me.Check2.Value = False
End Sub
Checkboxes are a control type designed for one purpose: to ensure valid entry of Boolean values.
In Access, there are two types:
2-state -- can be checked or unchecked, but not Null. Values are True (checked) or False (unchecked). In Access and VBA, the value of True is -1 and the value of False is 0. For portability with environments that use 1 for True, you can always test for False or Not False, since False is the value 0 for all environments I know of.
3-state -- like the 2-state, but can be Null. Clicking it cycles through True/False/Null. This is for binding to an integer field that allows Nulls. It is of no use with a Boolean field, since it can never be Null.
Minor quibble with the answers:
There is almost never a need to use the .Value property of an Access control, as it's the default property. These two are equivalent:
?Me!MyCheckBox.Value
?Me!MyCheckBox
The only gotcha here is that it's important to be careful that you don't create implicit references when testing the value of a checkbox. Instead of this:
If Me!MyCheckBox Then
...write one of these options:
If (Me!MyCheckBox) Then ' forces evaluation of the control
If Me!MyCheckBox = True Then
If (Me!MyCheckBox = True) Then
If (Me!MyCheckBox = Not False) Then
Likewise, when writing subroutines or functions that get values from a Boolean control, always declare your Boolean parameters as ByVal unless you actually want to manipulate the control. In that case, your parameter's data type should be an Access control and not a Boolean value. Anything else runs the risk of implicit references.
Last of all, if you set the value of a checkbox in code, you can actually set it to any number, not just 0 and -1, but any number other than 0 is treated as True (because it's Not False). While you might use that kind of thing in an HTML form, it's not proper UI design for an Access app, as there's no way for the user to be able to see what value is actually be stored in the control, which defeats the purpose of choosing it for editing your data.
Check on yourCheckBox.Value ?