很少由数据库设计器为自己和自己构建数据库。 它通常是根据客户的要求构建的。 很多时候,数据库将有多个用户,这些不同的用户可能(也可能不会)在数据库中执行不同的功能。
MS Access使用可以加密数据库(前端和/或后端)以限制谁可以打开数据库的密码来提供一些安全性。 但是,我们仍然面临这样的问题,即用户一旦访问数据库就可以访问,因为密码加密可以解锁整个数据库,而不仅仅是某些部分。
管理多个用户的选项之一是拥有一个可在数据库内执行的总机或活动菜单,并且用户将仅根据其在工作中心中的职责来选择适用于他们的那些项目。 但是,使用此选项的主要挑战是您向用户“探索”他们不应该浏览的数据库位置敞开大门。 在大多数情况下,这并不是真正的问题,因为普通员工不想破坏他们的工作地点。 但是,当涉及到个人,机密甚至医疗信息时,它应该让数据库管理员在其数据库中内置某些保护措施,以确保不受限制的信息不会偶然或偶然地出现。
另一种解决方案是为每种类型的用户创建单独的前端。 当一个用户需要访问一组特定的表单和报表时,可以将这些对象加载到链接到后端的一个前端中。 另一个用户需要一组不同的表单和报告,因此数据库管理员将构建另一个合适的前端。 然而,这种解决方案的明显挑战是不断扩展不同的有限元。 由于某些不同的用户(或不同的用户
类型的用户)可能需要使用相同的对象。 然后,每次更改这些对象之一时,还必须更新包含该对象的所有FE。我发现自己在工作中心处于这种情况。 我们只有10名定期使用数据库的员工,有时还有10多名在短期内访问非常有限的员工。 但是,这20名员工在数据库中的角色完全不同。 此外,由于我们接触的几乎所有内容都是《隐私法信息》(我在联邦政府工作),因此我们希望尽可能地控制访问权限。
随着时间的推移,我根据用户开发了一种限制对数据库访问的方法。 这样做的方法很简单:
- 创建一个用户表
- 建立公共常量和变量
- 确定谁访问了数据库
- 确定如何处理该用户
- 允许特定于用户的数据库访问
您的表可能具有不同的字段,但是我的表(tblUsers)根据我的要求具有某些字段。 随意列出自己的需求列表并适当构建表。 我的表的说明如下:
Field Name Data Type
UserKey Long (AutoNumber)
UserID Text
UserName Text
UserRights Integer
UserMachine Text
UserDirectory Text
UserSigBlock Memo
UserID是从OS环境返回的值,用于标识当前登录到计算机的人员。
我们所有的计算机都需要智能卡访问权限,因此安全性始终是双重身份验证。
只有经过验证的用户才能访问数据库。
下面将解释UserRights,但这是一个值,它指示用户将具有什么访问级别(或访问区域)。 这在最后的步骤中起作用。
由于我们的IT部门经常要求提供用户计算机名称的列表,因此我已将其包括在列表中,并且也可以从OS环境中轻松获得。
有时,我们的用户会从数据库中下载报告或电子表格,拥有用户建立的目录有助于确保他们的项目始终在一个地方。
我们的办公室经常从数据库发送电子邮件,因此我还包括了一个用户可自定义的电子邮件签名块。 这使数据库可以快速将签名块添加到外发电子邮件中。 这很方便。
现在,您的用户表已创建,我们需要弄清楚如何使用它!
我创建了一个模块,其中包含我的公共变量和公共函数列表,称为modSystem。 以下是我用来限制用户访问权限的列表:
Option Compare Database
Option Explicit
'User Rights Constants
Public Const UserAdmin As Integer = 1
Public Const UserOIC As Integer = 2
Public Const UserPromo As Integer = 3
Public Const UserRecords As Integer = 4
Public Const UserSrRecorder As Integer = 5
Public Const UserRecorder As Integer = 6
'User Variables
Public glngCurrentUser As Long
Public gstrUserID As String
Public gstrCurrentUser As String
Public gintUserRights As Integer
Public gstrUserDirectory As String
Public gstrUserMachine As String
我已经为各种类型的用户建立了常量,因为记住用户类型比记住用户权限的值容易。
此外,如果我在整个数据库中使用这些全局常量,并且需要对这些常量的实际值进行任何更改,则无需查找每个“用户权限”实例。
全球常数将解决这一问题。
为了解释我的公共变量,我希望允许数据库始终掌握某些数据。 例如,gstrUserID是从操作系统返回的系统用户ID。 变量gstrCurrentUser是用户的实际名称(例如“ Egbert Schmuckatelli”)。 当数据库管理员设置用户帐户时,将建立此值。 变量glngCurrentUser是tblUsers的主键。 其他变量是不言自明的。
每当我们想将某个用户标识为完成某项任务或必须提供特定于用户的信息时,我都会在整个数据库中使用这些变量。
这是最简单的步骤。 当数据库打开时,我使用启动表来自动确定谁登录了数据库以及数据库将对该用户执行的操作。 在表单的OnOpen事件中,我具有以下内容:
Private Sub Form_Open(Cancel As Integer)
On Error GoTo EH
Dim db As Database
Dim rst As Recordset
Dim strSQL As String
gstrUserID = Environ("USERNAME")
Set db = CurrentDb()
strSQL = "SELECT * FROM tblUsers " & _
"WHERE UserID = '" & gstrUserID & "';"
Set rst = db.OpenRecordset(strSQL, dbOpenDynaset)
If Not rst.EOF Then
With rst
.MoveFirst
glngCurrentUser = !UserKey
gstrCurrentUser = !UserName
gintUserRights = !UserRights
gstrUserMachine = !UserMachine
gstrUserDirectory = !UserDirectory
End With
Else
'This User does not exist in the Users Table
'Determine what to do--whether to Quit or set up new account
End If
rst.Close
db.Close
Set rst = Nothing
Set db = Nothing
Exit Sub
EH:
MsgBox "There was an error initializing the Form! " & _
"Please contact your Database Administrator.", vbCritical, "Error!"
Exit Sub
End Sub
因此,在这一点上,数据库知道数据库中用户的权利,但是我们只需要使系统适当地指导它们即可。
由于我的启动表单上没有可操作的对象,因此在后台完成其他操作(由OnTimer事件驱动)后,代码便告诉表单关闭。 在OnClose事件中,我放置了以下内容:
Private Sub Form_Close()
On Error GoTo EH
Select Case gintUserRights
Case UserAdmin
DoCmd.OpenForm "frmAdministrator"
Case UserPromo, UserOIC, UserSrRecorder
DoCmd.OpenForm "frmSwitchboard"
Case UserRecords
DoCmd.OpenForm "frmCommandRecords"
Case UserRecorder
DoCmd.OpenForm "frmPRFReview"
End Select
Exit Sub
EH:
MsgBox "There was an error Closing the Form! " & _
"Please contact your Database Administrator.", vbCritical, "Error!"
Exit Sub
End Sub
您会注意到,根据用户权利,将打开另一个表格。
这对用户是完全透明的,因为我们的“记录”人员仅使用命令记录表。
他们没有什么不同。
记录员无需访问我们的总机,而仅在PRF审核表上执行职责。
但是,您可能会注意到三种不同类型的用户(userPromo,UserOIC和UserSrRecorder)都打开了“配电盘”表单。 这似乎与整篇文章都不相称! 如果您建立了不同级别的用户权限,他们如何才能访问同一表格? 他们不是都可以访问相同的信息吗?
在这里,我对MS Access的经典功能做了一些改动。
许多年前,Microsoft Access开始引入Switchboard Manager。 我已使用该标准格式作为我的总机的基础,但是进行了一些更改以提供特定于用户的菜单项访问权限。 请记住,如果您当前使用的是内置在Switchboard Manager中的“ MS Access”,则此方法将
不工作,你也不会能够编辑使用内置的切换面板管理的配电盘。 这是对Tables以及运行Switchboard的VBA代码的全面检查,因此您可能希望从头开始。首先,我对配电盘的基础表进行了一些修改。 我已将表重命名为“ tblSwitchboards”(请注意复数,因为该表实际上保存了多个总机的数据)。 这是我的字段列表:
Field Name Data Type
User Integer
SwitchboardID Integer
ItemNumber Integer
ItemText Text
Command Integer
Argument Text
除了第一个字段(“用户”),我相信该表与自动生成的MS Acces总机表相同。
我要做的一件事是创建一个相关的表tblSwitchboard Commands,该表用作Command字段的行源。
其值如下:
ID Command
0 Page Title
1 Switch Page
3 Open Form
4 Open Report
6 Quit
在数据表视图中查看表格时,这只会使表格更加直观。
此外,我已将参数字段修改为查找字段,其中行源是以下查询:
SELECT MSysObjects.Name
FROM MSysObjects
WHERE (MSysObjects.Type=-32768 OR MSysObjects.Type=-32764)
ORDER BY MSysObjects.Name;
MSysObjects是MS Access中的一个系统表,因此不要四处尝试更改它!
此查询仅返回表单和报表的名称 ,这是我的用户有权访问的唯一对象( PERIOD! )。
通过一些研究,您可以扩展此查询以包括您想要的任何其他对象。
您可能还注意到,此查询将返回SubForms和SubReports(以及父表单和报表)。 如果您有标准的命名约定(据我所知)
在座的各位做......),你可以通过Where子句改变,以进一步限制查询:WHERE (MSysObjects.Name Like "frm*" AND MSysObjects.Type=-32768) OR (MSysObjects.Name Like "rpt*" AND MSysObjects.Type=-32764)
您可以根据需要进行尽可能多的实验,以获取此查询以返回正确的值列表。
将此字段的“限制到列表”属性设置为“否”非常重要。 其原因很快就会变得显而易见。
现在,我们已经创建了该总机表,让我们对其进行填充。 请原谅这份清单的长度,但我想更详细地说明一下。 请记住,此列表已被大幅削减,但仅用于说明(请原谅那些乱糟糟的列,但在将制表符转换为空格时我没有看到一点):
User ID No. Item Cmd Argument
Administrator 1 0 ACC Officer Promotions Page Title Default
Administrator 1 1 Task Management Switch Page 2
Administrator 1 2 Administrative Tasks Switch Page 6
Administrator 1 3 Quit Quit
Administrator 2 0 Task Management Menu Page Title
Administrator 2 1 Review Open Tasks Open Form frmTasks
Administrator 2 2 Overdue Tasks Report Open Report rptOverdueTasks
Administrator 2 3 Upcoming Tasks Report Open Report rptUpcomingTasks
Administrator 2 4 Task Template Open Form frmTaskTemplate
Administrator 2 5 Print Task Template List Open Report rptTaskTemplateListing
Administrator 2 6 Print Continuity Book Open Report rptContinuityBook
Administrator 2 7 Manage Projects Open Form frmProjects
Administrator 2 8 Return to Main Menu Switch Page 1
Administrator 6 0 Administrative Tasks Page Title
Administrator 6 1 Command Records Switch Page 10
Administrator 6 2 Release Actions Open Form frmPromotionRelease
Administrator 6 3 Recorders Switch Page 11
Administrator 6 4 Evaluation Timeliness Open Form frmEvaluations
Administrator 6 5 STEP Quotas Open Form frmSTEPQuotas
Administrator 6 6 Manage Users Open Form frmUsers
Administrator 6 7 Administrator Functions Open Form afrmAdministrator
Administrator 6 8 Return to Main Menu Switch Page 1
Administrator 10 0 Command Records Menu Page Title
Administrator 10 1 Screening Progress Open Form frmRecordScreening
Administrator 10 2 Send Missing Evals Open Form frmSendMissingEvals
Administrator 10 3 Command Records Database Open Form frmCommandRecords
Administrator 10 4 Return to Previous Menu Switch Page 6
Administrator 11 0 Recorder Actions Page Title
Administrator 11 1 Recorder Listing Open Form frmRecorders
Administrator 11 2 Recorder Scorecard Open Form frmRecorderScorecard
Administrator 11 3 Return to Previous Menu Switch Page 6
OIC 1 0 ACC Officer Promotions Page Title Default
OIC 1 1 Task Management Switch Page 2
OIC 1 2 Administrative Tasks Switch Page 6
OIC 1 3 Quit Quit
OIC 2 0 Task Management Menu Page Title
OIC 2 1 Review Open Tasks Open Form frmTasks
OIC 2 2 Overdue Tasks Report Open Report rptOverdueTasks
OIC 2 3 Upcoming Tasks Report Open Report rptUpcomingTasks
OIC 2 4 Task Template Open Form frmTaskTemplate
OIC 2 5 Print Task Template List Open Report rptTaskTemplateListing
OIC 2 6 Return to Main Menu Switch Page 1
OIC 6 0 Administrative Tasks Page Title
OIC 6 1 Command Records Switch Page 10
OIC 6 2 Recorders Switch Page 11
OIC 6 3 Evaluation Timeliness Open Form frmEvaluations
OIC 6 4 Return to Main Menu Switch Page 1
OIC 10 0 Command Records Menu Page Title
OIC 10 1 Screening Progress Open Form frmRecordScreening
OIC 10 2 Send Missing Evals Open Form frmSendMissingEvals
OIC 10 3 Command Records Database Open Form frmCommandRecords
OIC 10 4 Return to Previous Menu Switch Page 6
OIC 11 0 Recorder Actions Page Title
OIC 11 1 Recorder Listing Open Form frmRecorders
OIC 11 2 Recorder Scorecard Open Form frmRecorderScorecard
OIC 11 3 Return to Previous Menu Switch Page 6
Officer Promotions 1 0 ACC Officer Promotions Page Title Default
Officer Promotions 1 1 Task Management Switch Page 2
Officer Promotions 1 2 Quit Quit
Officer Promotions 2 0 Task Management Menu Page Title
Officer Promotions 2 1 Review Open Tasks Open Form frmTasks
Officer Promotions 2 2 Overdue Tasks Report Open Report rptOverdueTasks
Officer Promotions 2 3 Return to Main Menu Switch Page 1
Senior Recorder 1 0 Senior Recorder Actions Page Title Default
Senior Recorder 1 1 PRF Review Open Form frmPRFReview
Senior Recorder 1 2 Recorder Scorecard Open Form frmRecorderScorecard
Senior Recorder 1 3 Quit Quit
注意:“参数”字段可以具有以下四种类型之一:
同样,请注意,每种用户类型的“总机”选项明显不同。 现在,我们只需要设置我们的表格即可与此表格一起使用。
- “默认” –表示这是主配电盘(主页)
- 空白–表示这是总机页面标题(也由“命令”字段指示)或表示退出数据库
- 一个数字(保存为文本!),指示用户将被定向到的总机页面
- 表格或报告的名称
(图片1)
正如您可能无法从所附图片中看到的那样,我的总机有十个命令按钮和标签。 这些命令按钮和标签遵循特定的命名约定(因为我知道您
全部遵循相同的原则!)“ cmdOption1”,“ cmdOption2”等和“ lblOption1”,“ lblOption2”等。您可以忽略此表单中的某些内容,但是您可以看到它实际上只是一个修改旧的MS Access标准总机。 当我们深入研究时,就会发现:表单本身具有tblSwitchboards的记录源。 窗体的“允许添加”和“允许删除”的属性均设置为“否”。当用户浏览菜单时,窗体将过滤所需的特定记录(仅显示一个记录和一个记录)。 为了使此表格与表格配合使用,我们必须执行几个步骤:
注意:我的某些代码未显示,因为与此无关。
Option Explicit
Option Compare Database
Private Const intButtons = 10
Private Sub Form_Open(Cancel As Integer)
On Error GoTo EH
Me.Filter = "User = " & gintUserRights & _
" AND ItemNumber = 0 AND Argument = 'Default'"
Me.FilterOn = True
Exit Sub
EH:
MsgBox "There was an error initializing the Form! " & _
"Please contact your Database Administrator.", vbCritical, "Error!"
Exit Sub
End Sub
我们建立常量intButtons来指示此Form使用多少个按钮。
很高兴知道我们可以根据需要随时扩展。
然后,当表单打开时,我们将按该用户的“默认”总机页面进行过滤。 很简单,到目前为止,对不对?
当我们选择另一个配电盘页面移动时,代码将根据所选页面标题(根据适当的用户)过滤表单,因此当该过滤器完成时,我们需要显示此页面的配电盘选项:
Private Sub Form_Current()
On Error GoTo EH
FillOptions
Exit Sub
EH:
Exit Sub
MsgBox "There was an error moving to the current Record! " & _
"Please contact your Database Administrator.", vbCritical, "Error!"
End Sub
这必须放在窗体的OnCurrent事件中,否则初始页面将无法正确填充。
然后,相关的过程以填写表格的选项:
Private Sub FillOptions()
On Error GoTo EH
Dim dbOptions As Database
Dim rstOptions As Recordset
Dim strSQL As String
Dim intOption As Integer
Me.cmdOption1.SetFocus
For intOption = 2 To intButtons
Me("cmdOption" & intOption).Visible = False
Me("lblOption" & intOption).Visible = False
Next intOption
Set dbOptions = CurrentDb()
strSQL = "SELECT * FROM tblSwitchboards" & _
" WHERE User = " & gintUserRights & _
" AND ItemNumber > 0 AND SwitchboardID = " & Me.SwitchboardID & _
" ORDER BY ItemNumber;"
Set rstOptions = dbOptions.OpenRecordset(strSQL, dbOpenDynaset)
If rstOptions.EOF Then
Me.lblOption1.Caption = "There are no items for this Switchboard page"
Else
While Not rstOptions.EOF
Me("cmdOption" & rstOptions!ItemNumber).Visible = True
Me("lblOption" & rstOptions!ItemNumber).Visible = True
Me("lblOption" & rstOptions!ItemNumber).Caption = rstOptions!ItemText
rstOptions.MoveNext
Wend
End If
rstOptions.Close
dbOptions.Close
Set rstOptions = Nothing
Set dbOptions = Nothing
Exit Sub
EH:
MsgBox "There was an error listing the Options on the Form! " & _
"Please contact your Database Administrator.", vbOKOnly, "WARNING!"
Exit Sub
End Sub
您可能已经注意到,此代码起作用的关键子句位于此处:
" WHERE User = " & gintUserRights
仅显示适用于该特定用户的总机项目。
最后一件事。 我们如何确定单击菜单项时的操作?
首先,每个命令按钮和选项标签的OnClick EvenT中必须具有以下内容:
=SelectOption(x)
其中“ x”是命令按钮或选项标签的特定编号(1-10)。
这将执行以下功能:
Private Function SelectOption(intOption As Integer)
On Error GoTo EH
RestoreForm Me.Form.Name
Const optSwitchboard = 1
Const optFormAdd = 2
Const optFormBrowse = 3
Const optOpenReport = 4
Const optExit = 6
Const ErrCancelled = 2501
Dim dbOption As Database
Dim rstOption As Recordset
Dim strSQL As String
Set dbOption = CurrentDb()
strSQL = "SELECT * FROM tblSwitchboards" & _
" WHERE User = " & gintUserRights & _
" AND SwitchboardID = " & Me.SwitchboardID & _
" AND ItemNumber=" & intOption & ";"
Set rstOption = dbOption.OpenRecordset(strSQL, dbOpenDynaset)
If Not rstOption.EOF Then
Select Case rstOption!Command
Case optSwitchboard
Me.Filter = "User = " & gintUserRights & _
" AND ItemNumber = 0" & _
" AND SwitchboardID = " & rstOption!Argument
Me.FilterOn = True
Case optFormAdd
DoCmd.Close acForm, Me.Form.Name
DoCmd.OpenForm rstOption!Argument, , , , acAdd
GoTo SelectOption_Exit
Case optFormBrowse
DoCmd.Close acForm, Me.Form.Name
DoCmd.OpenForm rstOption!Argument
GoTo SelectOption_Exit
Case optOpenReport
DoCmd.OpenReport rstOption!Argument, acPreview
GoTo SelectOption_Exit
Case optExit
DoCmd.Quit
Case Else
MsgBox "Unknown option."
End Select
Else
MsgBox "There was an error reading the Switchboards Table."
GoTo SelectOption_Exit
End If
SelectOption_Exit:
On Error Resume Next
rstOption.Close
dbOption.Close
Set rstOption = Nothing
Set dbOption = Nothing
Exit Function
EH:
If (Err = ErrCancelled) Then
Resume Next
Else
MsgBox "There was an error executing the command. " & _
"Please contact your Database Administrator", vbCritical
Resume SelectOption_Exit
End If
End Function
如果您正确设置了总机表,则永远不会遇到任何错误。
但是,为了以防万一,有处理有错误了(因为我知道你们都包括错误所有的代码处理,对吧?)
就是这样! 它实际上并不太复杂,但是也许有些人可能认为它太艰巨而无法解决。 现在您有了一些选择。
我也希望对执行此代码的更好方法提供任何反馈。 我总是愿意学习!
希望这麻!