Hide a Form tab depending on the value of a field - vba

pretty simple question here in scope.
Question:
Wondering If I would be able to hide the tabs of a form based off the values of a table's fields.
I have been reading the 2019 Access Bible and so far it is still unclear to me how I would write the VBA module to constantly be running. Im asking the question a little early in my attempts, but hoping I can ask this well enough to get a head start.
I dont quite understand the execution model of VBA for access yet. I have prior expierence coding but this will be my 1st time in access. Just looking for a little help on how to write the function scope. You see below that I think it should be "Main" something, as I want it to run whenever in form view. Like I know how to write Private sub functions to respond to a button click. But not for a function that just runs in the background of the form.
I guess the real question is when to execute? Right? Any suggestions?
I was thinking something along the line of this below.
Main function()
If Me.FieldProcess_Water = "1" Then
Me.TabProcess_Water.Visible = True
Else
Me.TabProcess_Water.Visible = False
End If
End Sub

This requires some setup to reduce redundant code but should do what you want.
First you'll need your checkbox names and page names to be similar. In my example I have the page names as Tab_Name and the checkboxes as just Name. eg. Tab_Process Water and Process Water.
Then Create a sub called Form_Current() in the form's code-behind.
Private Sub Form_Current()
Dim chk As Control
For Each chk In Me.Controls
If chk.ControlType = acCheckBox Then
If chk = False Then
'Change TabCtl0 to whatever your's is called
Me.TabCtl0.Pages("Tab_" & chk.Name).Visible = False
Else
Me.TabCtl0.Pages("Tab_" & chk.Name).Visible = True
End If
End If
Next
End Sub
This will iterate through the current record's checkboxes and toggle it's respective tab's visibility.
To have the CheckBox update the tabs as they are clicked:
Private Sub Form_Load()
Dim chk As Control
Dim prop As Variant
For Each chk In Me.Controls
If chk.ControlType = acCheckBox Then
chk.OnClick = "=Check_Click()"
End If
Next
End Sub
This will assign a command to each checkbox.
Dim caller As String
caller = Me.ActiveControl.Name
If Me.ActiveControl.Value = False Then
Me.TabCtl0.Pages("Tab_" & caller).Visible = False
Else
Me.TabCtl0.Pages("Tab_" & caller).Visible = True
End If
This will hide the relevant tabs.

Related

How do I hide/unhide a subform based on the input from two comboboxes?

I have a mainform, called TrainingsSU
In it I am calling subform qry_TrainingSU (built from the query of the same name)
I have it set up so that the records auto populate the subform based on the two comboboxes in the main form.
But what I need to do is hide the subform, and have it display only when the two comboboxes are populated and records are loaded.
Here's the current VBA (of which I am not really even a novice at)
Private Sub cbo_EmployeeLookup_AfterUpdate()
Me!qry_TrainingsSU.Requery
If Me.cbo_EmployeeLookup.Value = "" Then
Forms!qry_TrainingsSU.Visible = False
Else
Forms!qry_TrainingsSU = True
End If
End Sub
Private Sub cbo_TrainingName_AfterUpdate()
Me!qry_TrainingsSU.Requery
If Me.cbo_TrainingName.Value = "" Then
Forms!qry_TrainingsSU = False
Else
Forms!qry_TrainingsSU.Visible = True
End If
End Sub
I found the general form of this code in another answer, here: MS Access: Hide and Unhide subform based on drop down in Main Form
However the code doesn't seem to be working for me.
Currently the subform is set to Visible:No
So nothing shows up at all.
If I change that, it doesn't disappear and the empty subform is still visible.
This wouldn't be a problem, except I need to use this form for another query and want to layer them over eachother when the second subform is ready to be used.
Later this form will be used to push an UPDATE SET to a table based on the different subforms.
Is there something that is obviously wrong with the code, or did I miss a setting somewhere?
You can try this:
Private Sub updateStates()
Me!qry_TrainingsSU.Form.Requery
If (Me.cbo_EmployeeLookup.Value <> "" AND Me.cbo_TrainingName.Value <> "") Then
Me!qry_TrainingsSU.Visible = True
Else
Me!qry_TrainingsSU.Visible = False
End If
End Sub
Private Sub cbo_EmployeeLookup_AfterUpdate()
updateStates
End Sub
Private Sub cbo_TrainingName_AfterUpdate()
updateStates
End Sub
Forms!qry_TrainingsSU searches form opened as main form, not a subform.

Disable TextInput Object

I have a checkbox and if the checkbox.Value = False I want to disable my TextInput-Object. On the internet there where some suggestions, but the methods which were used are not working for me, because the methods are not found.
I tried it with the .Valid-method:
Dim tf As TextInput
Dim checkbox As CheckBox
Sub checkbox_click()
Set checkbox = ActiveDocument.FormFields("checkbox").CheckBox
Set tf = ActiveDocument.FormFields("textfield").TextInput
If checkbox.Value = False
tf.Valid = False
End If
End Sub
But that doesn't work for some reason. I found tf.Enabled = False on the internet, but this method is unknown in my case.
You need something more like this:
Dim ff As FormField
Dim checkbox As CheckBox
.
.
Set checkbox = ActiveDocument.FormFields("checkbox").CheckBox
Set ff = ActiveDocument.FormFields("textfield")
If checkbox.Value = False
ff.Enabled = False
End If
With legacy FormField objects, some of the properties you need are associated with the FormField itself, and others are associated with child objects of the FormField such as the FormField.Checkbox
So the problem here is that tf is a FormField.TextInput object, but .Enabled is a property of the FormField object.
Not relevant to your question, but just as an observation, FormFields do not have Word events associated with them in the normal sense of VBA Events. The settings of each field tell Word to run a named Sub "on entry" and/or "on exit" - that's it. No actual click events. No problem with using names that makes those things look like events but I just thought I'd mention it.
Whilst the internet can be helpful you should also use the Object Browser in the VBE along with Help. 5 seconds spent doing a search for FormField would have given you the answer.
Dim tf As TextInput
Dim checkbox As CheckBox
Sub checkbox_click()
Set checkbox = ActiveDocument.FormFields("checkbox").CheckBox
If checkbox.Value = False
ActiveDocument.FormFields("textfield").Enabled = False
End If
End Sub

Checking and Unchecking Checkboxes in Access

I have a form in MS Access with multiple checkboxes which I want to use to fill up one textbox. If one of the checkboxes gets unchecked, I want its value to be deleted from the textbox without deleting other values. I'm new at using Access and coding in VBA (been reading ebooks for the past 3 weeks) and although I've tried to do research online it's been difficult for me to find the right code.
This is what I have so far:
First code found
Private Sub cb_click()
If Me.cb1 = True Then
Me.txtComentarios.Value = "INACTIVO;"
Else
Me.txtComentarios.Value = Null
End If
End Sub
Second code found
Private Sub cb2_Click()
If Me.cb2 = -1 Then
Me.[txtComentarios] = [txtComentarios] & "DISCREPANCIA"
Else
Me.[txtComentarios] = ""
End If
Exit Sub
End Sub
Also I would like for the checkboxes to fill the textbox in the same order the chechboxes are displayed.
Ex.
cb1; cb2; cb3
If, cb2 gets unchecked and its value gets deleted, I should have "cb1; cb3" but if I re-check cb2 I should get "cb1; cb2; cb3" again.
I just hope someone could guide me in. Thank you in advance.
Luz
You don't need events for each checkbox. Just create one procedure, which creates full text depending on checkboxes state and puts this text to the textbox. To call this function after each click on checkbox set After Update property of all checkboxes to =MyFunctionToUpdateTextbox instead of [Event Procedure]
Private Function MyFunctionToUpdateTextbox()
Dim strText As String
If Me.cb1 = True Then
strText = strText & "INACTIVO;"
End If
If Me.cb2 = True Then
strText = strText & "DISCREPANCIA;"
End If
If Me.cb3 = True Then
strText = strText & "Text for cb3"
End If
Me.txtComentarios = strText
End Function

Call a sub after this one has finished

I have a userform looping through a range with 2 settings; manual and automatic.
When I have an option button on my form set to manual, and click a next command button, I check the next cell in the range, change the contents of the form accordingly, then wait for the next button press.
However if I find the option button is set to automatic then instead of finishing up my code and waiting for the next button press, I have to call the next button press programmatically. That means that the previous subs each calling the next code slowly build up in the call stack, and I worry this will have some memory implications if I'm looping over a large range.
In code:
Private Sub nextItem()
Dim willShow As Boolean
returnResults 'return details from the form to the sheet
clearMemory 'clear out previous items on form
itemNo = itemNo + 1 'iterate over the range
SetupParts 'place new items on form
'do what next
Select Case displaySetting 'this variable holds the result from my option button in a custom enum "dispMode"
Case dispMode.Manual 'always show form
willShow = True
Case dispMode.SemiAutomatic 'show form based on condition
willShow = (Data.Count = 0) 'if SetupParts returns no data, display form, otherwise keep hidden
Case dispMode.Automatic 'don't show form
willShow = False
End Select 'there are actually a few more options here, but I've simplified
If willShow = False Then
If Me.Visible = True Then 'if needs to hide, and currently visible, then hide the form
Me.Hide
nextItem 'this is the problem, I call this code again, so the call stack grows
Else
'form is already hidden, do nothing
End If
ElseIf Me.Visible = False Then 'willShow must be True
Me.Show 'then wait for button click
End If
End Sub
Private Sub commandBtnNext_Click()
nextItem
End Sub
To avoid this problem, is there any way of getting nextItem to run immediately after the previous call of nextItem has run; ie. to tell a sub to run immediately after this one has finished (without introducing time delays). Or maybe this isn't an issue; if so, please explain why.
UPDATE
There is also a SemiAutomatic check to see which mode to use based on the contents of the userform. This is fine when calling recursively, but I can't see how to incorporate it into a looping approach.

Copy record from previous field if specific combobox value

I have an access form that needs filling in daily by various people.
It's to document changes to a website and I currently have a combobox box set up for the various sections to state whether they are AMENDS, REVERTS or NO CHANGE.
I have set conditional formatting to then highlight these sections but am also trying to get it to work so that if the user chooses "NO CHANGE" then the data for that field copies over from the previous record.
I have set this up in the AfterUpdate code for the combobox, but nothing is happening, not even an error... can anyone help?
Private Sub COMBOBOX1_AfterUpdate()
If Me.COMBOBOX1 = 3 Then
Me.[FIELD_TO_CHANGE] = DLookup("[FIELD_TO_CHANGE]", "tb_TABLE", "[ID]=Forms![form_FORM]![ID]-1")
End If
End Sub
(Where 3 is the value of NO CHANGE in the combobox, and FIELD_TO_CHANGE, tb_TABLE and form_FORM being the names of the various elements)
Thanks!
First you should define your control COMBOBOX1, enter in Properties Window, define
COMBOBOX1.AfterUpdate = "[Event Procedure]"
then your Private Sub COMBOBOX1_AfterUpdate() will be taken into account. Error may occur and popup to you.
Then change the event handler like this to start:
Private Sub COMBOBOX1_AfterUpdate()
If Me.COMBOBOX1 = 3 Then
Me.[FIELD_TO_CHANGE] = DLookup("[FIELD_TO_CHANGE]", "tb_TABLE", "[ID]=" & (Me.[ID] - 1))
End If
End Sub
There will be many errors to correct before your form works...