I'm working with some old VB6 code and have a scenario I'm trying to correct. I have a form that allows you to enter a person ID (use renters this in a textbox at the top) and click "show" it lists the appointment in the textbox on the same form. There is also a button that loads a new form that allows the user to edit the displayed data and save the change.
E.g. Change persons age from 65 to 64. I make this change, and save it. The save is successful and I unload the form to return to Form1. However, I must click "show" again to refresh the displayed data in the textbox to ensure the change is visible. I cannot figure out how to refresh this form, so the user doesn't have to click "show" to repopulate the textbox with the new value. Can anyone assist? I can't just create a new instance of Form1, because if I did that the person ID field would be blank.
Thanks!
Short version: How do I refresh a form to get latest data while still obtaining the relevant person ID.
There's not enough information here to answer your question. The general pattern you'd use in this situation is as follows:
SearchForm launches ViewForm.
ViewForm launches EditForm. When ViewForm constructs its instance of EditForm, it passes Me to EditForm (perhaps by setting EditForm.Parent).
When EditForm's Save button click event fires, it calls Parent.ReloadData (where Parent is the ViewForm that launched the EditForm).
Here is the approach that should work. In the editor have a public property that returns whether the form was cancelled or not. (.Cancelled). You'll have an object that carries attributes of the person that you are trying to change the age of. Then it's pretty simple. Code in the main form:
dim oPerson as clsPerson
dim oFrm as frmAgeEditor
set oPerson = GetCurrentPerson()
set oFrm = new frmAgeEditor
with oFrm
set .Person = oPerson
.Show vbModal
if not .Cancelled then
' Update Main form with the contents of oPerson
end if
end with
You can just call in "Show" function right after updating.
Call Me.frmParent.Refresh
I used this to refresh the screen without losing data.
I had to dig through a lot of old code to figure it out. This section had been written a long time ago, and worked well.
Public Sub Refresh()
Call cmdDetails_Click
If tvwScreeningSchedule.Nodes.Count > 0 Then
tvwScreeningSchedule.SelectedItem = tvwScreeningSchedule.Nodes(1)
Call tvwScreeningSchedule_Click
End If
End Sub
It's quite a specific function, and "cmdDetails_Click" contains alot of custom validation, but it's not too dis-similar to AngryHackers answer.
Related
I have been asked to create a field(FORM) in access that get the USERNAME who has logged in . I created the string VBA Me!EmployeeID = Environ("USERNAME") which is on load. However, I noticed when I click on next record it goes way and wont get updated. I am not VBA expert that why I am here. What string should I write and where should I put it?
Should it be on form properties or the Employee ID field properties and also which part Before update or After?
Use form Current event. This event occurs both when a form is opened and whenever the focus leaves one record and moves to another
Private Sub Form_Current()
Me!EmployeeID = Environ("USERNAME")
End Sub
I would like to ask for your help on the following issue in MS Access.
I had created a form "CustomerListF", filled with command buttons for each client. For each button, I had created the following code:
Private Sub cmd_outlets_ABC_Click()
DoCmd.OpenForm "OrderFormF"
Forms!OrderFormF!Outlets = "ABC"
End Sub
The button would then open another form "OrderFormF" and enter "ABC" in the textbox named "Outlets". However, I realized the second line of code (Forms!OrderFormF!Outlets = "ABC") would always create a phantom record in my subform, which is located in "OrderFormF", and this record would travel to other clients' forms. This phantom record is usually created when the commandbutton is clicked twice (double clicks or subsequent clicks). It is a headache when the record starts to shift around.
enter image description here
I would like to seek your advice for vba code to edit the second line of code.
Thank you.
This approach for filling the field in opened form is not good. OrderFormF initialization and second line of your code with assigning value to the field may be executed in different sequence, they are not synchronized.
In order to avoid this, you should pass the argument to OrderFormF by another way. I would recommend to use OpenArgs parameter:
DoCmd.OpenForm "OrderFormF",,,,,,"ABC"
And then in Load event of OrderFormF assign the value to textbox:
Me.Outlets = Me.OpenArgs
In this case the "ABC" value will be assigned to first row in the form or to new record, if form is empty. Before assigning you can select the row if you need to assign value not to the first row. Also this way will protect you against double click on button, Load event executed only once during first form opening
I have a form that I open to have the user select data from. Then I want to send that data back to the form that was spawned that data. Here is my code from the parent form:
Private Sub bttn_AW_SelectUnits_Click(sender As Object, e As EventArgs) Handles bttn_AW_SelectUnits.Click
'TODO: Capture output from next menu
Dim changeUnits As New AuditWizardUnits
changeUnits.ShowDialog()
End Sub
I could have it spawn a new form, but I have multiple forms that I want to collect data from, so I don't want to lose the data that has been collected already. I tried to google this, but all I can find is how to send data, not receive it. I also couldn't find how to do this beyond a binary "OK" or "cancel."
Does know how to do this?
The DialogResult portion simply allows you to determine if the User selected "OK" (or your equivalent of "OK"), or simply cancelled the dialog by clicking the "X" in the top right (in which case there might not be any valid "selections" in the dialog to retrieve).
If the User clicked "OK", then you can retrieve any desired values from the form reference that you already have. Conceptually, we are "pulling" from the main form, not "sending" from the child form. This is easier because the main form already has a reference to the child form (you used that reference to display the dialog!).
To do the opposite, and "send" from the dialog to the main, you'd have to pass a reference to the main form into the dialog form. There are cases where you'd want to do this, such as if you needed something to change in main, in real-time and possibly multiple times, before the dialog is closed by the user. Sometimes you need to only "pull", sometimes you need to "send", and sometimes you might need to do both. You'll have to decide which approach is best for your situation.
Assuming you only need to pull after the dialog is dismissed by the user, check the returned DialogResult, then use that form reference to retrieve the values:
Private Sub bttn_AW_SelectUnits_Click(sender As Object, e As EventArgs) Handles bttn_AW_SelectUnits.Click
'TODO: Capture output from next menu
Dim changeUnits As New AuditWizardUnits
If changeUnits.ShowDialog() = DialogResult.Ok Then
' Access something directly from a Control:
Dim value As String = changeUnits.TextBox1.Text
' ...or use a property that YOU created in changeUnits:
Dim values As List(Of String) = changeUnits.SelectedValues
End If
End Sub
In the dialog, you return "OK" when the user clicks on your OK/Save/Continue type button:
Private Sub btnOK_Click(...) Handles btnOK.Click
Me.DialogResult = DialogResult.Ok
End Sub
For the List aspect, you'd have to make that List accessible from outside the class so it can be retrieved like in my snippet above:
Public Class AuditWizardUnits
Public SelectedValues As New List(Of String)
End Class
You'd either populate that list before setting DialogResult, or populate it as the user interacts with the dialog.
I've created a form in which a user can double click on a list box entry to open another form for info. When the user closes the new form I want the existing data on the original form to remain. In my current code, however, the original data is not retained if the user clicks "X" to close the new form.
Code:
Private Sub lstServiceHistory_DblClick (ByVal Cancel As MSForms.ReturnBoolean)
frmJobDetails.Show
End Sub
How can I get the data to remain on the original form?
I solved the problem by adding a boolean check in the form_Activate event to see if the form had already been initialised.
I'm back again with what I hope is a fairly easy question.
I'm attempting to create a user form in VBA. The user will enter certain bits of information into the form, and then close the form. I'd like the user form to retain the data entered after it is closed by the user. I'm treating it as a class module, since techinically they are, or at least that is how I understand it. Here is the code I'm using:
In the main sub that displays the user form:
Sub NonACATMemo()
Dim UserInput As MemoReasons
Set UserInput = New MemoReasons
UserInput.Show
... And then in the user form itself to close it...
Private Sub UserForm_Terminate()
MemoReasons.Hide
End Sub
I also call this sub from a command button on the form. The issue I'm running into is that when I use this method, I get an error "Run-time error '402': Must close or hide topmost modal form first." If I use unload me, when I try to get data out of the form it is cleared and I get a "server not available" error or something to that effect.
So, any ideas on hiding a user form but retaining the data inside?
Final couple of notes: This is the only user form in the project, and here is an example of how I'm trying to get data out of it using the Public Property Get method:
Debug.Print UserInput.EmailFlag
Debug.Print UserInput.ContraFirm
Debug.Print UserInput.MemoReason
Well, I'm all ears if anyone has any suggestions.
It's an old topic... hopefully someone will need a help on this.
You can do the following :
1-Place a Close/Cancel button (you can set Cancel property to True)
2-Attach following code to Click event
Private Sub btnClose_Click()
'Do some stuff if necessary
Me.Hide
End Sub
3-Attach this code to QueryClose event
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
If CloseMode = 0 Then 'vbFormControlMenu = 0 ([X] button on top right), see MSDN
Cancel = True 'Don't fire Terminate event...
btnClose_Click '...instead, call my close event handler
End If
End Sub
You can check the result by placing a debugger breakpoint in UserForm_Initialize event and it should be fired only for the first time showing the UserForm and thus, granting UserForm state preservation.
I've not seen this approach before. Normally, I would just instantiate the form by:
MemoReasons.Show
Indeed the _Terminate() event is wiping out the data held in the form. So the solution is to not call the _Terminate() event from the button-click. Instead, simply hide the form, e.g.:
Sub ShowMemoReasons()
'In a normal code module, this calls the form
' could be run from the macros menu or attached to
' a shape/button/etc on the worksheet.
MemoReasons.Show
End Sub
Put these in the MemoReasons code module:
Private Sub CommandButton1_Click() '<-- Rename to handle your button's click event
MemoReasons.Hide '## Hides the form but does not release it from memory
End Sub
Private Sub UserForm_Terminate()
'Any events pertaining to the termination of the form object
' otherwise, all form control data will be wiped out when
' this object releases from memory
End Sub
After you do these, if you use the button to HIDE the form, you can call the ShowMemoReasons() and it should re-display the form, while preserving data that was previously entered in the form.
If you use the red "X" button or some other event triggers the Terminate event, you will lose the form data. There are ways to do validation and prevent this with the QueryClose event if necessary.
Update
I don't think you need to Dim an instance of the user form (an exception would be if you will be potentially displaying multiple forms at the same time). Otherwise, declaring UserInput as a public variable is redundant and confusing.
Inicidentally, this is why you're getting the error: Must close or hide topmost modal form first. If you must implement it this way, instead of doing MemoReasons.hide you should use Me.Hide.
As long as you are only displaying one instance of the form, you can always refer to MemoReasons.property because MemoReasons is a public object, just like ThisWorkbook or ActiveWorksheet, etc.
Instead, you should be able to refer to this object (MemoReasons is an object) in any subroutine, for example create another one that is not called from the previous subs. Run the sub to show the form, enter in some data, and then hide the form. With the form hidden, then run this subroutine, and you should see the resulting data from the form.
Sub Test2()
Debug.Print MemoReasons.EmailFlag
End Sub