I have a userform with several textboxes, radio buttons, dropdowns, etc. When a user creates a new entry, the data is saved on the Data sheet, with one record occupying one row.
I'd go like follows:
use Tag
property of the UserForm
object to store a "calling parameter" that will tell UserForm whether to run an InitializeValues()
Sub or a FillValues()
one
use UserForm_Activate
event handler to have UserForm decide which action is to be taken
so, assuming you attach an Edit()
sub to your sheet "edit" buttons, the former would be
Sub Edit()
With UserForm3
.Tag = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row '<~~ tell the UserForm there's something to bring in so that it'll fill controls from the sheet instead of initializing them
.Show
.Tag = "" '<~~ bring Tag property back to its "null" value
End With
Unload UserForm3
End Sub
then in you UserForm code pane place this
Private Sub UserForm_Activate()
If Me.Tag = "" Then '<~~ if there's no info from Tag property...
InitializeValues '<~~ ... then Initialize controls values
Else
FillValues '<~~ ...otherwise fill controls with sheet values
End If
End Sub
Private Sub InitializeValues()
With Me
.ComboBox1.RowSource = "initRange"
.serial.Value = "actText1"
.created_on.Value = "actText2"
.created_by.Value = "actText3"
' and so on...
End With
End Sub
Private Sub FillValues()
With Me
.serial.Value = Cells(.Tag, 2).Value
.created_on.Value = Cells(.Tag, 4).Value
.created_by.Value = Cells(.Tag, 5).Value
'.. and so on
End With
End Sub
You can write a sub like loadDataIntoForm(rowNum As Long)
that fills the fields of the form to your liking and put it into the code of the userform.
e.g.
Public Sub loadDataIntoForm(rowNum As Long)
me.somecontrol.Value = Sheets("Data").cells(rowNum,1).Value
'...
End Sub
Then if the edit button is clicked execute
Details.loadDataIntoForm(rowNum) 'where rowNum is something like ActiveCell.Row. This calls UserForm_Initialize and THEN loadDataIntoForm
Details.Show 'UserForm_Initialize won't get executed again
UserForm_Initialize
is executed before loadDataIntoForm
is so the fields get cleared first by the UserForm_Initialize
function and then re-populated by loadDataIntoForm
. To be sure you could also load the form first
Load Details
Details.loadDataIntoForm(ActiveCell.Row)
Details.Show
So you can be sure UserForm_Initialize
is not called after loadDataIntoForm
.
To get a sense of what is called when you can go through the code line by line using F8.
edit: A nicer way would probably be to write two subs, one for initializing the form for an edit (populate the fields) and one for initializing the form for a new record (clear the fields)
It could look something like
Public Sub ShowNew()
'clear all the controls
me.Show
End Sub
Public Sub ShowEdit(rowNum As Long)
'populate the controls
me.Show
End Sub
Then instead of using Details.Show
use Details.ShowNew
and Details.ShowNew(rowNum)
If you have one Button on your sheet to call the form, then just use something like this:
me.TextBox1.value = Cells(ActiveCell.Row, 2).Value 'ActiveCell.Row returns the row number of the current cell
So the only command the button has is UserForm1.Show