- Local time
- Today, 10:55
- Joined
- Jul 9, 2003
- Messages
- 16,286
Thanks @Sodslaw - love the user name BTW
Ha! Hadn't spotted that!
Thanks @Sodslaw - love the user name BTW
If a subform has the focus, ActiveForm refers to the main form. If no form or subform has the focus when you use the ActiveForm property, an error occurs.
If a subform has the focus, ActiveForm refers to the main form. If no form or subform has the focus when you use the ActiveForm property, an error occurs.
Set mfrmCallingForm = fGetParentForm(ctrlActiveControl) 'Store the Form the Control is on, (not always/necessarily the active Form).
This was absolutely perfect for my application! I only used the "'lock" portion of the Private Sub. In the Public Sub, I used Case"" for the fields to remain unlocked so I didn't have to apply tags to all of my controls (there's a lot). Lastly I commented out the command button portion for later use. You rock!This is the code I use when I want everything on the same form. Since my apps have security, I check it in the form's current event and then lock or unlock the form based on what authorization the user has. In your case, use the call to lock or unlock from wherever you want to control the locking.
To make this work, I use the tag property of each control. The tag property needs to be set ONLY for exceptions. So, on a form where normally everything is going to be locked but you want the search fields to be unlocked, mark the search fields as "NoLock". In a form where normally everything is going to be unlocked but you want some fields to always be locked, then tag those fields with "Lock".
Code:Private Sub Form_Current() If Forms!frmLogin!txtLevel >= 8 Then Call LockControls(Me, False) 'unlock Else Call LockControls(Me, True) 'lock End If End Sub Public Sub LockControls(frm As Form, bLock As Boolean) Dim ctl As Control For Each ctl In frm.Controls Select Case ctl.ControlType Case acTextBox, acComboBox, acListBox, acCheckBox Select Case ctl.Tag Case "NoLock" ctl.Locked = False Case "Lock" ctl.Locked = True Case Else ctl.Locked = bLock 'toggle locks End Select Case acCommandButton Select Case ctl.Tag Case "NoLock" ctl.Enabled = True Case "Lock" ctl.Enabled = False Case Else ctl.Enabled = Not bLock 'toggle locks End Select End Select Next ctl Set ctl = Nothing End Sub
You need to review the logic again. The ONLY controls that require a Tag are those that you ALWAYS want to remain locked or unlocked so it is rarely more than a few no matter how many controls you have on the form.In the Public Sub, I used Case"" for the fields to remain unlocked so I didn't have to apply tags to all of my controls (there's a lot).
My apologies...To clarify per your previous response: All of my form fields are unlocked by default. OnCurrent, my code loops through the form fields and locks all of them, then unlocks one specific field by name, then based on higher level user security level, unlocks the fields that have the tag "QCLock" (referenced in the module code), then, based on highest level of user security, allows edits/deletions etc., which unlocks any fields that are still locked. At least that's how I was able to achieve my particular goal. I have multiple user security levels to get through, which is why I start by locking everything, then unlocking based on the user. I do have error handling, but I have more code after the one below, so I didn't include it here.@avincent61 Although likes are always welcome, they are not very useful in identifying whether a post solved a problem since there is no way to distinguish between a "thanks for trying" from a "that clarified the code for me and I'll fix my app to use the code correctly".
Dim intnewrec As Integer
intnewrec = Form.NewRecord
If intnewrec = False And IsNull(Me.CreatedRecord) Then
Me.CreatedRecord.Value = Forms!frmlogin!txtLogin
' MsgBox "You're in a new record." This was to test the code
Else
' MsgBox "This is NOT a new record" This was to test the code
End If
Dim LoginType As Integer
Dim User As String
Dim ctrl As Control
' set user = a value of the txtLogin textbox on the Navigation Form
User = Forms![frmlogin]!txtLogin
' Assign the UserSecurity from the user login to LoginType
LoginType = DLookup("UserSecurity", "tblPersonnel", "UserLogin = '" & User & "'")
' Lock all controls if user login type is less than allowed level
If LoginType < 5 Or LoginType = 10 Or LoginType = 11 Or LoginType = 8 Then
' Loop through all controls on form and lock them
On Error Resume Next
For Each ctrl In Me.Controls
ctrl.Locked = True
Next ctrl
On Error GoTo 0
ElseIf LoginType = 5 Or LoginType = 7 Or LoginType = 9 Then
' Lock controls meant only for Administrator
Call LockControlsQC(Me, True) 'lock
Else
Me.AllowDeletions = True
Me.AllowEdits = True
Me.AllowAdditions = True
End If
' Unlock one specific control
Me.SIR_Status.Locked = False
Considering I use public codes in my modules that check users security level, I'm disappointed that I didn't think to go the route you're suggesting for the forms themselves. The user security level isn't the same for all of my forms, but there are groups of forms that could use the same code. Thanks for this.I'm glad you have a solution. When you have to manage sets of controls based on login type, the solution is more complex.
I would rethink the LogInType concept so that each type belongs to a group. That means a table that defines all valid values of LogInType and for each, adds a groupID. That way, instead of hardcoding multiple type values in multiple forms, you can make a single procedure that you pass in a group in addition to the form reference. Over time, this will save you a lot of coding and also minimize future code changes if you end up having to add more types. If you notice, the code I posted is held in a standard module therefore it does NOT exist in every single form as your code needs to. If you have 50 forms, which isn't a lot, you have to repeat the code 50 times. If you have to change it, you have to change it in 50 places. In my app, I have to change the code in one, single module. HUGE difference.
Thank you so much Pat!It isn't too late to change Using the group concept going forward makes maintenance much easier.
I also assign a group to a form. Then the check is always the same for each form. You take the form's group and look it up in the user's groups.
For special cases, you might have to define a group that has only a single form. Users get to belong to multiple groups. A simple dCount() is the only code you need. I also separate view, add, change, delete. So the security check for each happens in a different event procedure. The view check happens in the Open event - the form doesn't open if the groups don't match. For Update, the code goes as the first statement in the form's BeforeUpdate event. If the user isn't allowed to update the form, the code uses me.Undo and Cancel = True to clear any changes and cancel the update. For add, you use the BeforeInsert event. Code is the same as the BeforeUpdate event. And for Deletes, you use the on Delete event and also Cancel = True.
Very little code to handle the whole thing. Handling new forms and new people just means updating the two groups.