Перед тем, как начать, я хотел бы поблагодарить всех, кто предлагает какие-либо предложения, так как это будет длинный пост. Я включу все подробности в свой код, чтобы кто-нибудь мог помочь мне заметить, что я упускаю и / или делаю неправильно. Я создаю книгу Excel, которая будет использоваться для регистрации продаж и расходов с использованием различных макросов, работающих через userforms
. Чтобы защитить документированное и определить, кто что добавил, я разработал систему входа, используя это видео в качестве руководства, но с некоторыми уточнениями кода, которые я сделал сам.
So this is basically how the login system works. On a worksheet
named Users
I created two tables. The first one is named LoginRegistry
(the blue one in the image) and the second one is named Users
(the green one in the image). The headers in the table Users
from the column HOME
to USERS
have the exact same name as the worksheets on the workbook do. They are also in the exact same order. When you double click on any of the cells within that range they loop through three icons (that are just using the Webdings
font colored accordingly). The green icon makes the sheet visible and editable, the blue one makes it visible but protected and the red one hides it and protects it (a bit overkill but I liked to do this just in case there are any vulnerabilities). The ALL
column changes all of the permissions at once. The code for this is the following:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'Change icons when double clicking
Set UserPermissions = Worksheets("Users").Range("Users[[ALL]:[USERS]]")
UserPermissionsRange = UserPermissions.Address(0, 0)
If Not Intersect(Target, Range(UserPermissionsRange)) Is Nothing Then
'Change from empty to unlocked
If Target.Value = Empty Then
Target.Font.Color = RGB(0, 176, 80)
Target.Value = "Ð"
Cancel = True
'Change from unlocked to read only
ElseIf Target.Value = "Ð" Then
Target.Font.Color = RGB(48, 84, 150)
Target.Value = "N"
Cancel = True
'Change from read only to locked
ElseIf Target.Value = "N" Then
Target.Font.Color = RGB(255, 0, 0)
Target.Value = "Ï"
Cancel = True
'Change from locked to unlocked
ElseIf Target.Value = "Ï" Then
Target.Font.Color = RGB(0, 176, 80)
Target.Value = "Ð"
Cancel = True
End If
Else
Exit Sub
End If
'Modify all of the permissions at once
If Target.Column = 10 Then
AllWorksheetPermissions = "K" & Target.Row & ":" & "R" & Target.Row
Range(AllWorksheetPermissions) = Target.Value
Range(AllWorksheetPermissions).Font.Color = Target.Font.Color
End If
End Sub
The userform
that captures the information when logging in is named frmLoginForm
. Each time the workbook opens the following code is executed:
Private Sub Workbook_Open()
'Hide anything other than the form from the user
Application.Visible = False
'Show the worksheet that has all the information of the user permissions
Sheets("Users").Visible = -1
'Show login form to capture the user information
frmLoginForm.Show
End Sub
This way the user can not do anything before authenticating. The form has two textboxes, two buttons and three labels. It is the following:
введите описание изображения здесь
Код формы:
Private Sub UserForm_Initialize()
'Set custom colors to the form objects
frmLoginForm.BackColor = RGB(240, 235, 215)
cmdLogin.BackColor = RGB(201, 34, 23)
cmdExit.BackColor = RGB(201, 34, 23)
cmdLogin.ForeColor = vbWhite
cmdExit.ForeColor = vbWhite
End Sub
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
'Close the workbook whether the user closes the form with the "Exit button" or
'clicking the "X" icon in the top right corner
If CloseMode = vbFormControlMenu Then
Cancel = True
Unload frmLoginForm
ThisWorkbook.Close
End If
End Sub
Private Sub cmdLogin_Click()
'Look for the valid user range
Set UserRangeLookUp = Worksheets("Users").Range("Users[[USER]:[PASSWORD]]")
On Error Resume Next
'Find correct password
CorrectPassword = Application.WorksheetFunction.VLookup(tbxUser.Value, UserRangeLookUp, 2, 0)
If Err.Number = 1004 Then
MsgBox "The user you entered does not exist."
Err.Clear
Else
If StrComp(tbxPassword.Value, CorrectPassword, vbBinaryCompare) = 0 Then
'Make worksheet visible
Application.Visible = True
'Only add a new row to the LoginRegistry table if it is empty
If (Range("Users!B3").Value) = "" Then
Else
Worksheets("Users").ListObjects("LoginRegistry").ListRows.Add
End If
'Find the last row of the LoginRegistry (adding +2 to get the absolute reference)
Set LoginRegistryRange = Worksheets("Users").Range("LoginRegistry")
LoginRegistryLastRow = LoginRegistryRange.Rows.Count + 2
'Last row of each column
UserLastRow = "Users!" & "B" & LoginRegistryLastRow
DateLastRow = "Users!" & "C" & LoginRegistryLastRow
TimeLastRow = "Users!" & "D" & LoginRegistryLastRow
'Save the information of the current login to the LoginRegistry
Range(UserLastRow).Value = tbxUser.Value
Range(DateLastRow).Value = Format(Date, "dd/mm/yyyy")
Range(TimeLastRow).Value = Format(Time, "hh:mm:ss")
'Protect/unprotect/hide/show worksheets according to the user permissions
Set UserListRangeLookup = Worksheets("Users").Range("Users[USER]")
ActiveUserRow = Application.WorksheetFunction.Match(tbxUser.Value, UserListRangeLookup, 0) + 2
'Loop through the columns `HOME` to `USERS` in the table `Users`. The headers containing
'the worksheet names to reference are in the second row of this worksheet
'Ð means unlocked and visible, N means locked and visible, Ï locked and not visible
For i = 11 To 18
If Cells(ActiveUserRow, i).Value = "Ð" Then
Sheets(Cells(2, i).Value).Unprotect "123456"
Sheets(Cells(2, i).Value).Visible = -1
ElseIf Cells(ActiveUserRow, i).Value = "N" Then
Sheets(Cells(2, i).Value).Protect Password:="123456"
Sheets(Cells(2, i).Value).Visible = -1
ElseIf Cells(ActiveUserRow, i).Value = "Ï" Then
Sheets(Cells(2, i).Value).Protect Password:="123456"
Sheets(Cells(2, i).Value).Visible = 2
End If
Next i
'Show "HOME" worksheet first always
Sheets("HOME").Activate
'Close login form
Unload frmLoginForm
Else
MsgBox "Incorrect password. Try again."
End If
End If
End Sub
Private Sub cmdExit_Click()
'Code for the exit button on the form
Unload frmLoginForm
ThisWorkbook.Close
End Sub
Итак, как только я объясню все это, я могу сосредоточиться на своей проблеме. Дело в том, что разрешения не всегда правильные. Я не могу найти точную ситуацию, когда код получает ошибку, но иногда при входе в систему учетные данные пользователя проверяются, но в книге ничего не обновляется. Пользователь, который должен видеть только несколько листов, остается со всеми правами администратора, например, если он ранее входил в систему. И в большинстве случаев после взлома кода он не будет работать снова, пока я не изменю одно из разрешений зарегистрированного пользователя в таблице Users
. Независимо от того, сколько раз я пытаюсь войти в систему, если не будет внесено никаких изменений в разрешения, они не изменятся, и рабочие листы останутся с разрешениями последнего пользователя, который смог правильно войти в систему.
Сначала я думал, что проблема заключалась в том, что рабочий лист с разрешениями был установлен на очень скрыт , и макрос не мог прочитать данные, но даже если я положу его в конец и снова сделаю видимым каждый раз, когда книга открывается проблема продолжает происходить.
Прямо сейчас я считаю, что l oop - моя проблема, но я просто не могу понять, что не так. L oop выглядит следующим образом (это именно то, что я показал в предыдущем фрагменте кода, я просто копирую его снова, чтобы вы могли сосредоточиться на этой части кода):
'Loop through the columns `HOME` to `USERS` in the table `Users` (col 11 to 18). The headers
'containing the worksheet names to reference are in the second row of this worksheet
'Ð means unlocked and visible, N means locked and visible, Ï locked and not visible
For i = 11 To 18
If Cells(ActiveUserRow, i).Value = "Ð" Then
Sheets(Cells(2, i).Value).Unprotect "123456"
Sheets(Cells(2, i).Value).Visible = -1
ElseIf Cells(ActiveUserRow, i).Value = "N" Then
Sheets(Cells(2, i).Value).Protect Password:="123456"
Sheets(Cells(2, i).Value).Visible = -1
ElseIf Cells(ActiveUserRow, i).Value = "Ï" Then
Sheets(Cells(2, i).Value).Protect Password:="123456"
Sheets(Cells(2, i).Value).Visible = 2
End If
Next i
Я бы очень признателен за любое ваше предложение.