Acess support please - ms-access

Access Docment scanned with Macfee and Microsoft on a server platform One drive so completly safe.
I want a user login page which has different levels so that different users will have access to different objects or functionality.
Please have a look at the coding below I have also attached a link to onedrive for the access 2013 document.
code:
Private Sub Form_Load()
Dim Security As Integer
Me.txtLogin = Environ(“userName”)
Me.txtUser = DLookup(“userName”, “tblUser”, “Username = ‘” & User & “‘”)Then
If IsNull(DLookup(“userSecurity”, “tblUser”, “UserLogin = ‘” & Me.txtLogin & “‘”)) Then
MsgBox (“No User security set up for this user. Please contact the Admin”, vbOKOnly, “Login Info”
Me.NavigationButton13.Enabled = False
Else
Security = DLookup(“userSecurity”, “tblUser”, “UserLogin = ‘” & Me.txtLogin & “‘”)
If Security = 1 Then
Me.NavigationButton15.Enabled = True
Else
Me.NavigationButton15.Enabled = False
End If
End If
End Sub

I am guessing you have a main login page for the entire app, which is the startup form. Keep in mind that a user can hold down the Shift key when opening your app to bypass any startup code, but you can disable that. You can also hide the database container. Users can always use another DB to link your tables, or import objects, so you will also want to lock the entire database with a password.
The form startup code can check your custom security table and then you can use Cancel = True to short-circuit the opening event. It seems like you are trying to accomplish that by disabling navigation buttons, but you may want to disallow the opening of the form.
As HansUp and Tim have suggested, tt would be helpful if you can describe your situation a bit more so that we can respond more concisely. If you have a situation where you need true security that is hard to breech, you may want to consider moving your tables into SQL Server (or SQL Express) and linking them to your Access container. Ultimately, there's nothing you can do in Access that I could not get around.

Related

Access: 2 roles on the same DB with different roles

I have an Access Database on the SharePoint and two user's roles that have to work on it:
Role1 is given to a single user. He can manage all the forms of the DB with the possibility to change all the tables. These forms will require many future releases.
Role2 is given to many users. They can manage only one form that is effective only on a single table of the DB. He doesn't (and mustn't) need to see/manage the others forms/tables (they are a lot). The form used for this role will not require future releases.
What it the best practice to manage this? I thought about the following 2 solutions but probably there is a third one that is better.
Solution #1
Having 2 different Access files linked to the same DB: one with all the forms (that I give to Role1) and one with only one form (that I give to Role2).
Solution #2
Having a single Access file that I give to both the users. Role1 has read/write access to all forms. Role2 can see only a specific form and has no read/write access to other forms.
I would recommend solution #2 otherwise if you change the logic in the front end you have to change it always twice and this is really annoying. Also, if you forget to change both versions and you had a huge change in the logic, you have people working with the old version and people working with the new version.
What I normally do is the following. I have a table tblDeveloperAccess with the ID of your Role1. At the start of the first form load event I have the following code:
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("tbDeveloperAccess", dbOpenSnapshot)
rs.FindFirst "ID = '" & Environ("USERNAME") & "'"
If rs.NoMatch Then
DoCmd.NavigateTo "acNavigationCategoryObjectType", "acNavigationGroupTables"
DoCmd.SelectObject acForm, vbNullString, True
DoCmd.RunCommand acCmdWindowHide
DoCmd.ShowToolbar "Ribbon", acToolbarNo
End If
Basically I am hiding the ribbon and the object navigation. You can go even further and disable the context menu and the "Shift + DblClick"-Trick (on your database file). And of course I disable the possibilty on the start form to get into the design view.

Is there a way to protect a field so that only certain users can edit?

I have an Access 2010 DB that I need to update a field in. Right now I have a button on one of my forms that will duplicate the selected row. I know that I can make a field not duplicate by setting the Locked property to Yes on that field.
What I need to do is find a way to make a field not duplicate, but still be editable to certain people. I don't want to set the Locked property as that will lock it for everyone.
I've no idea how to do this except to change the working of the Duplicate record button. Right now it simply makes a copy of the row that is selected and pastes it into the New Record row. This takes all fields that are not Locked.
I read about possibly using a bunch of variables and setting them to the values of each of the fields, but this seems cumbersome since I have 160+ fields that I would have to setup. And then pasting them into the New Record row. I would prefer not to have to do this.
I have used VBA just not with Access very much. A VBA solution is fine with me, I have not tried anything as I don't know where to even start.
I suggest a sub to lock / unlock the controls, like this:
Private Sub SetControlsLocked(ForceLocked As Boolean)
Dim bLocked As Boolean
Dim sUser As String
If ForceLocked Then
' Always lock before copying
bLocked = True
Else
' More secure method than Environ("USERNAME")
sUser = CreateObject("WScript.Network").UserName
' Lock for everyone except some users
' If the list is longer or changes regularly, lookup the Username in a table instead
bLocked = Not (sUser = "jane" Or sUser = "bob" Or sUser = "mike")
End If
' do the locking
Me!Control1.Locked = bLocked
Me!Control2.Locked = bLocked
End Sub
(refer to comments on https://stackoverflow.com/a/32565953/3820271 for "more secure" claim).
and apply in your copy button routine...
Private Sub cmdCopy_Click()
' Lock before copying!
Call SetControlsLocked(True)
' ... your existing copy routine
' Unlock for special users
Call SetControlsLocked(False)
End Sub
... and when opening the form:
Private Sub Form_Load()
' Lock for non-special users
Call SetControlsLocked(False)
End Sub
What I do is have a table of users and their permissions level and Windows login username. I capture username with Environ("USERNAME") and match with the users record and set up forms appropriately, usually just disable/hide particular buttons.
But really have to do a lot more setup of the database to prevent users from accessing restricted data. Like hide navigation pane, disable ribbon, disable right click shortcut menu, disable function keys, maybe even publish as executable.
But if they know where the backend is, what stops them from just opening it? Unless you go to something like SQLServer database, really nothing.

Edits getting lost

Background:
Split access database, maximum two users. The back end is located on one of the two computers on a mapped drive and the front end is local. The computers are connected to the router by wifi. (I am trying unsuccessfully to get them to connect the computers via cable)
Edit: This problem is now happening in a single user environment.
Problem:
This is happening on one specific form only. Its underlying table has a multi-value field.
Issue 1: We have a situation where a field will be edited, but as soon as the focus moves to another field the edit reverts back to its original value.
Issue 2: When editing one field, some of the other fields are getting the values of the previously shown record.
Note: Navigation from one record to the other is done as follows:
Me.RecordsetClone.FindFirst "ID = " & cmbLocateRecipientID
Me.Bookmark = Me.RecordsetClone.Bookmark
The issues only happen occassionaly.
This is an extremely weird behaviour on the part of Access, so when the users first reported the issues I was convinced that they were entering information mistakenly into another record. However, they have since shown me the issue happening live.
Closing and reopening the form solves the issue. However, they can obviously not work in such a fashion.
I cannot reproduce the problem on my development machine.
Me would think you have to specify and use the recordset object:
Dim rs As DAO.Recordset
Set rs = Me.RecordsetClone
rs.FindFirst "ID = " & Me!cmbLocateRecipientID.Value & ""
If Not rs.NoMatch Then
Me.Bookmark = rs.Bookmark
End If
Set rs = Nothing
A similar change may be needed in other parts of your code.
You can't use MS Access on a wireless network as "wireless" does not keep a continuous link between the frontend and backend. There are occasional dropouts which you don't notice with most things, however MS Access is very sensitive to this and you will have all sorts of problems over wireless. You must use a physical cable as the connection.

Re-map linked tables in Access 2010

I am a relative novice with Access and starting from scratch with coding, so be gentle.
I have an Access 2010 database with dozens of linked tables based on .txt files. Sometimes the database moves, the source files move or the file server just gets re-named. In these events I am looking for a simple way for a user of the database to remap and refresh the linked tables. Ideally, it would be user prompted, i.e. the user pushes a button to refresh from a navigation form or something. Then, the system prompts for the new folder location. The folder location would house all of the necessary files, so it only needs to be selected one time. Once selected, all linked tables should remap and refresh with the user getting an error or success message.
I have seen a lot of these questions asked, but they seem to be in older versions of Access or it is not asking for a user prompt or for a user to browse for the new path.
Thanks.
While I agree with Marc B that this seems like a very oddly constructed database you could use the following code the manually link the tables again to the proper location. You would need to work this into a system that can loop through all tables and do them all one by one or adjust this code to do that automatically. But you may want to just rethink your system.
Function SetTableLinkPath(strTableName As String, strTablePath As String)
If Nz(strTableName, "") <> "" And Nz(strTablePath, "") <> "" Then
Dim cdb As DAO.Database
Set cdb = CurrentDb
cdb.TableDefs(strTableName).Connect = ";DATABASE=" & strTablePath
cdb.TableDefs(strTableName).RefreshLink
MsgBox "Table link for " & strTableName & " has been successfully set to the path: " & strTablePath & "."
Else
MsgBox "You must enter a valid Table path and name!"
End If
End Function

User management in Microsoft Access 2013 databases

I am building a system using Microsoft Access 2013 that uses MySQL as a backend. I am trying to figure out a way to do some kind of basic user management, ideally in such a way that users would have to "log in" when they launch the database, and then their username would be easily accessible by the system while they are using it. I've tried searching for solutions, but most of them just tell me to use Office 365 or sharepoint, which are not options at the moment. Does anyone have an idea of how to accomplish this? Thanks in advance!
I recommend building your own user storage and login system. You'll basically need to create your own users table (in MySQL in your case), make forms to manage users, make a Login form, and write code to control the login process.
Logging in usually consists of checking some kind of credentials they type in against existing data in your users table. You can usually do this in Access with DLookup or DCount statements but I usually end up using a DAO or ADO recordset instead since I like to pull out more than one value from the User's table and I also like to write things back to it right away, like the LastLogin datetime, LastLogin computername, etc.
I actually wrote an example database which you can download here. It needs a rewrite. I've changed quite a few of my practices since Jan, 2011. But give me another year and it would need another rewrite.
I usually program the login form so that the user enters their initials and then a password. If you go this route you need to have a unique index setup on the Initials field to prevent duplicates. If you're going to have a lot of users you need to use a Username instead, which could still theoretically be the users initials.
Here's what my code would look like to authenticate a user. Be aware that this is far from truly secure. This assumes that passwords are stored in plain text. Users could theoretically try to do SQL Inject from here because I'm not use a parametrized query or stripping out special characters from their input such as # or ;.
Private Function AuthenticateUser() As Boolean
Dim sInitials As String
Dim sPassword As String
sInitials = Trim(Nz(Me.txtInitials, ""))
sPassword = Trim(Nz(Me.txtPassword, ""))
If sInitials = "" Or sPassword = "" Then
'Logging in with blank passwords is not allowed
AuthenticateUser = False
Exit Function
End If
If DCount("EmployeeID", "tblEmployees", "[Initials] = '" & Replace(sInitials, "'", "''") & "' AND Password = '" & Replace(sPassword, "'", "''") & "'", True) = 0 Then
MsgBox "Invalid Credentials."
AuthenticateUser = False
Exit Function
Else
Dim rs As New DAO.Recordset
Dim sSQL As String
sSQL = "SELECT * FROM tblEmployees WHERE initials = '" & Replace(sInitials, "'", "''") & "'"
Set rs = CurrentDb.OpenRecordset(sSQL)
If Not (rs.EOF And rs.BOF) Then
'Config is an instance of a User Defined Type. It could also be a class object.
Config.UserInitials = rs("Initials")
Config.UserFullName = rs("EmployeeName")
Config.UserID = rs("EmployeeID")
rs.Edit
rs("LastLoginDateTime") = Now()
rs("LastLoginComputer") = "Function Required to Get Computer Name"
rs("ProgVersion") = "Your Program Version Number"
rs("CurrentDbPath") = Left(CurrentProject.path & "\" & CurrentProject.Name, 254)
rs.Update
End If
rs.Close
Set rs = Nothing
AuthenticateUser = True
End If
End Function
In my applications I use a global object, in this case an instance of a User Defined Type, which I call Config. I store any kind of application runtime related settings in there for the duration of the runtime of the application. Of course this object gets destroyed when the user closes out of the application or when a code reset happens (which cannot happen in Access runtime, but does happen frequently during development). You could use a class object instead of a User Defined Type. Or you could use individual global variables for everything, which I don't recommend (that's what I used to do). A User Defined Type simply allows you to group global variables together and gives you an easy way to refer to them in your code during design time by typing in Config., which then brings up every option using Intellisense (assuming you have it enabled).
If you want your settings to survive a code reset, you need to use TempVars. TempVars became available with Access 2007. I do not use them now (contrary to my example database) because they are not strongly typed. There's no Intellisense to help you get the correct TempVar and you can technically refer to a TempVar that doesn't even exist and Access won't throw an error. I think TempVars is really just a Dictionary object with all of it's shortcomings, and the single benefit of surviving a code reset. I can imagine storing a Connection String in there, but I wonder if it's worth using TempVars for anything at all. If a code reset happens, my entire application needs to be reloaded anyway since I setup a lot of global objects and variables when the application first opens and the user first logs in.
FYI, in previous versions of Access there was user security built in. I think Microsoft discontinued that starting in 2007. I never really used it so I didn't miss it when it got discontinued.