What I am trying to achieve is for a combo box (Combo_sf) selection to dictate the form in the subform control (sf_record) I have about 10 forms, their names are in the combo box data. I am new to VBA and am not sure if my approach is right:
Private Sub Combo_sf_AfterUpdate()
Dim strLoadTable As String
strLoadTable = "Form." & Me.Combo_sf.Value
MsgBox strLoadTable
Forms![frm_Mnu_Manage Configuration Settings]!sf_record.Form.SourceObject = strLoadTable
End Sub
I have placed this in the combobox's after update event but when I make my selection nothing happens in the form. Am I approaching this right or would another way work better?
Your approach should work. I put a combo box named cbxSubform on my main form and added one line of code to its AfterUpdate() event handler...
Private Sub cbxSubform_AfterUpdate()
Me.mySubform.SourceObject = Me.cbxSubform.Value
End Sub
...and changing the selection in the combo box switches the subforms immediately. Are you sure that the AfterUpdate() code for your combo box is actually firing? (You could add a MsgBox or a Debug.Print to check.)
It could be this line which is tripping you up:
strLoadTable = "Form." & Me.Combo_sf.Value
What is your form object called? If your form is called Form.myTableName it could be the . that is throwing it out, try setting it to a form without a dot in its name.
In this line, it seems the code attempts to change the SourceObject property of a Form object.
Forms![frm_Mnu_Manage Configuration Settings]!sf_record.Form.SourceObject = strLoadTable
However, SourceObject is a property of a subform control, not the form contained in that control. So if the subform control is named sf_record, do it this way.
Forms![frm_Mnu_Manage Configuration Settings]!sf_record.SourceObject = strLoadTable
Also, if the after update procedure runs from [frm_Mnu_Manage Configuration Settings], you can use Me to refer to the form.
Me!sf_record.SourceObject = strLoadTable
Finally, if Me.Combo_sf.Value is the name of a form, you don't need to prefix its name with "Form.". It worked either way in my test, but I would just leave off "Form.".
strLoadTable = Me.Combo_sf.Value
Related
I have created A userform with few command buttons.
I can't seem to figure out how do I get the information from them.
I want to open this userform from another one and then I want the user to choose an option from one of the buttons which will change a specific cell in the table itself
the userform I created
I did not write anything on this userform therefor there is no code from it to show only the design.
how do get the information from the buttons to be written in A specific cell on a specific worksheet?
double click on one of the buttons, in the code menu a new sub should appear. this looks something like:
Sub CommandButton1_onClick()
End sub
Alongside this event method, it also has a few properties. The one that is usefull here is the CommandButton1.Value, this represents the state of the button (either true or false iirc).
So build for each button (I strongly advice giving them custom names to prevent getting lost in the trouble) as sub like this:
Sub CommandButton1_onClick()
if CommandButton1.Value then
ThisWorkBook.WorkSheets("WorksheetName").Range("YourRange").Value = "Some value"
else
ThisWorkBook.WorkSheets("WorksheetName").Range("YourRange").Value = ""
end if
End sub
I have a form with 3 textboxs and i want to change their properties values according to some events.
My idea is to set these properties to a global form's variables in order to use them whenever i want with a function or module (this depends on your suggestion).
Assuming that i want to change all textboxs.enabled property by pressing a button
and i want to change another different property if needed in the future (like bordercolor),
my example is this:
in the form VBA,
Option Compare Database
Option Explicit
Private Const AllTxtboxes = *** all txtboxes ***
in the VBA button
Private Sub button1_Click()
AllTxtboxes.enabled = True
End sub
Thanks in advance.
You need to loop trough all controls and identify those you want to change. The problem is that each control type got their own properties, so you need to make sure you are in the right one.
And for that, there is a property common to all controls named Tag
There, you can specify a value and check it. It's really helpful to select only what you want.
I made a simple form with 6 textboxes:
Note that in design view, properties panel at right, tab others, last property is Tag (sometimes it comes as aditional info or something like it).
There, I typed 99 but only on textboxes 2, 4 and 6, because those are the textboxes I want to handle (that would be kind of your array of textboxes)
I added a command button to change forecolor of those textboxes to red when clicked. My code is:
Private Sub CMD_CHANGE_FONT_COLOR_Click()
Me.Painting = False
Dim MyControl As Control
Dim MyTxt As TextBox
For Each MyControl In Me.Controls
If MyControl.Tag = 99 Then
'we set MyTxt to MyControl so we can use Intellisense, not really needed, but it makes coding easier
Set MyTxt = MyControl
MyTxt.ForeColor = vbRed
Set MyTxt = Nothing
End If
Next MyControl
Me.Painting = True
End Sub
When the form loads, you will see:
But after click on command button, the forecolor of those 3 textboxes will be red:
There you go. So everytime you want to do something with that array of textboxes, you can use this code to loop and change the properties you want.
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.
Imagine a form that, for demontration purposes, contains only a subform and a textbox that need to mirror each other.
I tried to accomplish this by setting the Control Source on the textbox to the value of the field in the subform and this worked to make them mirror each other, but the textbox isn't editable so this is an unsuitable solution.
The next thing I decided to try was using the AfterUpdate event on both controls to run code that sets the value of the other control.
This is easy for the textbox:
'Set value of Notes field on subform whenever value of the corresponding textbox
Private Sub Notes_Textbox_AfterUpdate()
Me.subform.Form![Notes] = Me.Notes_Textbox.Text
End Sub
However, this isn't as simple for the subform field. I don't know how to reference an event on a field in a subform in a way that will still allow me to reference controls outside that subform.
As a demonstration, I need a way to do this:
Private Sub subform_Notes_AfterUpdate()
Me.Notes_Textbox.Text = Me.subform.Form![Notes]
End Sub
I can access the subform fields AfterUpdate event within the scope of the subform but if I do that, then I can't access the Textbox because it is in the main form, not the subform.
So I either need a way to define an event function on a field in a subform from within the scope of the main form, or a way to make the textbox part of the subform while maintaining the subforms ability to open in datasheet view.
Not sure I get the whole problem (how does datasheet view come into play?), but this should do what you want:
(in the subform)
Private Sub Notes_AfterUpdate()
Me.Parent!Notes_Textbox.Value = Me![Notes].Value
End Sub
Edit from comment: By far the easiest solution would be a continuous form instead of a datasheet in a subform.
You can have two textboxes, a one-liner in the Details section, and a large one in the form header or footer. Both have the same control source and are automatically updated when the other one is edited. No code required.
If it must be a subform-datasheet, you can use a similar approach: bind the main form to the same recordsource, and in On Current of the subform, move the main form to the same current record.
I have a main form with a tab control containing multiple subforms. I need to be sure that the data in a subform is saved when the user switches tabs. The problem is that DoCmd.RunCommand acCmdSaveRecord seems only applies to the current form so it doesn't save the data in the subform.
I have tried different events on the subform such as deactivate, OnLostFocus etc but they don't fire until another field somewhere else gets the focus.
The ideal solution would seem to be to put something on the OnChange event of the tab control to be sure that all the data is saved. That is my question, how to do I save the record in a subform?
In Access, the default is to save, so unless you have done something pretty complicated to prevent this, moving the focus from a subform will automatically save the record. You can test this by adding a record, moving from the subform, and then checking the table.
You don't have to do anything at all, as the subform is saved as soon as it loses focus (when the tab control changes).
But as an exercise, I've outlined the code you'd write if you needed to.
You can save any form by setting it's .Dirty property to False. For something like this that's going to run a lot, I think I'd write a sub to walk through the subforms, check if any are dirty, and save the dirty ones. Something like this:
Public Sub SaveSubFormsOnTab()
Dim pge As Control
Dim ctl As Control
For Each pge In Me!ctlTab.Pages
Debug.Print pge.Name
For Each ctl In pge.Controls
If ctl.ControlType = acSubform Then
If ctl.Form.Dirty Then
ctl.Form.Dirty = False
End If
Debug.Print ctl.Name
End If
Next ctl
Next pge
Set ctl = Nothing
Set pge = Nothing
End Sub
Now, that's actually quite inefficient in cases where you have lots of controls on your tab control that aren't subforms. If your tab has nothing but subforms, it will be fairly efficient. In either case, it's much more efficient to use a custom collection populated in the form's OnLoad event, and then you'd walk that collection that includes nothing but your tab control's subforms, and save any that are dirty.
Either of these is preferable to using the OnChange event of the tab, because each time you add a tab page with a subform or change the name of a subform control, you'd have to alter the OnChange event.
I was having a similar issue where I needed various code to run in the subform and values in the main form - that were based on values in the subform - to be recalculated. Here is what finally worked:
This is an example with a main form named 'frmCustomers' containing a subform 'sfmTransaction', which in turn has a subform called 'sfmOrderLine'. The forms have a button 'cmdSave' that is only visible when the user clicks the 'cmdEdit' button (the purpose of which is to lock all the controls until the user clicks the edit button, and then to re-lock them when he clicks save):
On the main form ('frmCustomer') go the subform's exit event, and add 'me.recalc' twice, like this:
Private Sub sfmTransaction_Exit(Cancel As Integer)
If (Not Form_sfmTransaction.NewRecord And Form_sfmTransaction.cmdSave.Visible) Or (Not Form_sfmOrderLine.NewRecord And Form_sfmOrderLine.cmdSave.Visible) Then
'To save subforms
Me.Recalc
Me.Recalc
End If
End Sub
In the subform ('sfmTransaction') go the subform's subform's exit event, and add 'me.recalc' twice, like this:
Private Sub sfmOrderLine_Exit(Cancel As Integer)
If Not Form_sfmOrderLine.NewRecord And Form_sfmOrderLine.cmdSave.Visible Then
'To save subform
Me.Recalc
Me.Recalc
End If
End Sub
Hope this helps.
Setting the dirty property to false may force Access to save the data to the database, but it bypasses the before_update event. This means that if you've used this event for validation or other purposes, you can now have bad data in your database.