Passing a checkbox control to a function - vba

I am using Access 365 and VisualBasic. I have a number of checkboxes on a form that I want to display just a subset of these at a time, so I want to reposition the top of the checkboxes so that no matter which are currently displayed, I can make them line up nicely.
So, I have declared an array of checkboxes that I want to dynamically add those checkboxes to display:
' Array holding the checkboxes that will be displayed, depending upon species, sex, etc.
Dim arrCheckBoxes(cNumCheckboxes) As CheckBox
Then as I determine that a specific check box should be shown, I want to add it to the array at the next available position using this function (which will also update the next available position):
Private Sub AddCheckbox(ByRef arrCheckBoxes() As CheckBox, ByRef chkNew As CheckBox, ByRef intCurrentCheckbox)
intCurrentCheckbox = intCurrentCheckbox + 1
arrCheckBoxes(intCurrentCheckbox) = chkNew
End Sub
My problem is that in the code that calls the AddCheckbox function, I cannot figure out how to pass the check box. I am using the following code (CatNeuter is the checkbox from my form).
Call AddCheckbox(arrCheckBoxes, Me.CatNeuter, intCurrentCheckbox)
However, Me.CatNeuter is always 0, so I think I am getting just the value, and not the checkbox control itself. I've tried numerous different methods such as:
Me.Controls!CatNeuter
Me.Controls("CatNeuter")
But I just cannot figure out how to pass the actual checkbox so I can then go through the array and change the Top property for each checkbox.
Regards,
Lise

You need to use Set for objects:
Set arrCheckBoxes(intCurrentCheckbox) = chkNew

Related

How do I properly use if/then for a bolean value in order to make an object visible?

I want to display an endless access form. For each data set there is a yes/no value (PA). If yes, then a hidden object should be displayed. It seems very straight forward, but it doesn't work.
I have tried by changing the value of PA to 1, 0, -1. Either nothing happens, or the object will be displayed for all data sets.
The object is defined as hidden in the form.
Private sub form_current()
If PA.value = true Then
me.object.visible = True
End if
End Sub
I would be very happy for some advice. /LP
Handle the control's Change event, and then you can assign to its value:
Private Sub PA_Change()
Me.object.Visible = PA.Value ' TODO: give 'object' an actual name
End Sub
Find PA in the top-left codepane dropdown, then select the Change event in the top-right code pane dropdown if it's not automatically selected - the VBE will generate the event handler procedure for you.
As the object is unbound, you can't do this. When unbound, it will either be visible or not - for all records.
One workaround is to move the control to a tiny subform having a master/child relation to the main form.

How to get values from controls on tabstrip in VBA?

In different tabs of a tabstrip I have input values which are different in each tab. I need to write a code which takes all these values and do some work like sums up the values of each tab on button click.
Can anyone help me do this? In my code when I input value at a textbox of one tab it also changes the value of all other tabs and hence cannot receive different values of each tab. Any idea, please?
Multipages vs Tabstrips
A multipage is an object with "pages". Each page can hold it's own collection of controls which can then be referenced either directly or through the containing page object.
A tab strip is an object with "tabs". Unlike a "page" object, a tab does not have it's own controls. Instead, there are only the original controls, visible for all "tabs".
Programmatic differences
Since a multipage has a different set of controls for each page, there is very little housekeeping required. The selection of a page affects which controls are visible, and the controls automatically retain values assigned to them (as expected).
For a tabstrip, since there is only the initial set of controls, there is a lot of housekeeping required in the code. The selection of a tabstrip does not have any automatic effect on the values in the controls. Instead the controls act as would be expected if they were not in the tab strip at all.
Tabstrip Solution
Set up a variable (array, collection, dictionary) that can be used to hold the various values of the controls. Then, in the TabStrip_Change() event, store the previous value, and reset the control for the new tab (or fill in the value the new tab last held).
I recommend adding a userform level variable Dim old_tab as Long which you can set to the current page at the end of the TabStrip_Change() event. (This is useful for retrieving previously filled values for the correct tab).
For my sample code, I will be using an array. However, since arrays are not very flexible with changing lengths, you can also look into using either a dictionary or collection, if desired.
For the userform pictured below, the following code causes the single textbox to act as though there is a different textbox per tab. It also saves the values whenever the tabstrip changes. (Note: if you then use the saved values for the calculation, remember to update the value for the current tabstrip first.)
Option Explicit
Dim old_tab As Long
Dim textValues As Variant
Private Sub TabStrip1_Change()
textValues(old_tab) = TextBox1.Value 'Saves the old value
TextBox1.Text = textValues(TabStrip1.Value) 'Updates value to reflect tab change
old_tab = TabStrip1.Value 'updates tab # variable
End Sub
Private Sub UserForm_Initialize()
ReDim textValues(0 To TabStrip1.Tabs.Count - 1) 'tabs are zero-based, so count is always one more than the maximum tab value
old_tab = TabStrip1.Value 'Ensures that the first value will be saved to correct location at the tab change
End Sub

Number Picker in Access / VBA

I am trying to put a number picker in a form in MS Access 2007. Here's an example of what I am trying to make:
I cannot find this in the default form controls, and have tried to make one myself using a listbox. Listboxes can be modified to look just like the number picker above, however the arrows only change the view, of the list, and not the actual selection (that is the value). For example, with the list box, if I have it range from 1 to 3, and default at 1 - when I change it to 2 via the arrows, the value of the listbox does not change, and is still one.
Does anyone know how to get a number picker in Access?
So you want to create a list of numbers and allow users to change the value displayed (AND stored as the control's value) using up and down arrows, such that they select the next or previous in the list.
I would suggest creating a text box and two buttons. Populate an array with the list of values. When a button is clicked it would:
A. Find the position in the array of any value already entered into the text box (eg loaded from a database)
B. Get the next or previous item from the array.
The array is populated as required (probably when the form is opened).
If you just need to allow the user to enter a whole integer number (ie a number spinner) you would do as follows:
Create one using a (locked) textbox and two buttons. Just add a textbox (name it something like txtValue) and two buttons (btnUp and btnDown), then add code like this to the Click event of those buttons:
Private Sub btnUp_Click()
Me.txtValue = Nz(Me.txtValue, 0) + 1
End Sub
Private Sub btnDown_Click()
Me.txtValue = Nz(Me.txtValue, 0) - 1
End Sub
You could add if statements to limit the data being entered
Or you can use a 3rd party control.
http://www.fmsinc.com/microsoftaccess/controls/components/spin-button/index.html
There are probably more, but be aware that using these sorts of controls in Access is unsupported, and there is no guarantee moving forward that they will work in Access. You're far better off using the native methods described earlier.

How to pass the value (true/false) of checkboxes created run-time on a userform

I am trying to create a number of checkboxes on a UserForm after reading all the non-empty rows in an excel sheet. That means these checkboxes have to be created in run-time. I also want to put a CommandButton on the UserForm. What I want is that once the user presses this CommandButton, the code should be able to send to a subroutine the information on which checkboxes are checked and what their names are.
Could anyone help me with problem.
Instead of trying to dynamically create checkboxes on a userform (which I'm not even sure is possible) consider using a listbox with a ListStyle of fmListStyleOption and with MultiSelect turned on with fmMultiSelectMulti
Populate the Listbox using the AddItem Method
For i = 0 to 9
Me.lbxDivisions.AddItem
Me.lbxDivisions.List(i) = "Checkbox " & format(i)
Next i
And determine which items are checked via the Selected property:
For i = 0 To lbxDivisions.ListCount - 1
If lbxDivisions.Selected(i) Then
MsgBox "Item " & Format(i) & " is selected and has value " & lbxDivisions.List(i)
End If
Next i
You can programmatically add form controls (check boxes, listboxes, etc) to userforms. From within the form's code module,
Me.Controls.Add "Forms.CheckBox.1", "CheckBox1", True)
From any other code module, just reference the form by name, instead of Me, e.g.,
MyUserForm.Controls.Add "Forms.CheckBox.1", "CheckBox1", True)
Personally I would favor using a more dynamic control (like a list box or combobox) unless your task absolutely requires you to use check boxes. With dynamic controls you need to manage their size, location relative to other controls, resize the userform (if necessary), etc., and although it's kind of possible to add event handling to these controls (see here), that's really limited (e.g., if you expect you need to add 10 check boxes each of which do a different thing, you need to pre-write 10 check box subroutines. If you create 11 check boxes but only 10 pre-written routines, the last check box won't do anything. It would be easier to just create all the check boxes when designing the form, and then programmatically set them to Visible=True or Visible=False as circumstance requires.
So, I'd favor using a dynamic control like a listbox or combobox, but it is possible to add form controls like checkboxes at run-time, if you must.

Make a button have multiple uses

okay... How do I explain this without being totally confusing?... Alright, I have this form that has MenuScripts (top-levels and second-levels). The problem that I am having is one of the second-levels is "Add" which brings you to another form when clicked. This other form has a button ("Record") and text boxes. This other form allows the user to input data and when the record button is clicked, the inputted data is written into a text file. Ok, so back to the first form. Another second-level MenuScript is "Update" which also brings the user to the other form; but first, the user has to click an item within a listbox to proceed. How do I get the data from the selected item to appear in the appropriate textboxes and how do I get the record button to update data instead of being confused and thinking it is only a add-data button?
Is there a way to use an "if" statement to say something like "if mnuAdd is clicked then" "elseif mnuUpdate is clicked then". Would something like that work for giving the record button multiple uses?
Also, if someone can give me some pointers on making sure the user selects an item within the listbox would definitely be a plus! Thanks, guys!
Unfortunately, I cannot add images since my reputation is too low.
Here is a visual representation of my ultimate goal
Easiest way: before displaying the second form set it's Tag property to something distinct – say "Add" or "Update" – depending on which menu item is selected. Then you just test the Tag value in the button's Click event and proceed accordingly.
As for determining whether a list item is selected: well if there isn't the ListBox's SelectedIndex property will be set to -1.
You need to put a public property on the second form (Details) which specifies which mode it is in. For instance, you could create a mode enumeration like this:
Public Enum EntryModes
AddBook
UpdateBook
End Enum
Then, define a public mode property on the second form, like this:
Public Property EntryMode As EntryModes
Get
Return _entryMode
End Get
Set(ByVal value As EntryMode)
_entryMode = value
End Set
End Property
Private _entryMode As EntryMode
Then, when you show the second form from the menu, just set the property first, before showing it:
Private Sub mnuAdd_Click(sender As Object, e As EventArgs)
Dim dialog As New DetailsDialog()
dialog.EntryMode = EntryModes.AddBook
dialog.ShowDialog()
End Sub
Private Sub mnuUpdate_Click(sender As Object, e As EventArgs)
Dim dialog As New DetailsDialog()
dialog.EntryMode = EntryModes.UpdateBook
dialog.BookToUpdate = ListBox1.SelectedItem
dialog.ShowDialog()
End Sub
As you can see, in the Upate menu click, I also added a line that passes the information for which book should be updated.