String comparison functions are not working properly - vba

So I have a program that I have three groups of users, and I am storing user names, permission levels, usernames and passwords in a veryhidden/protected sheet. (Yes I know this is not particularly secure but it is not to prevent malintent it simply will avoid people stumbling upon things they shouldnt. Nobody is going to be able to uncover very hidden sheets or get into the code.)
The function below is what I have been using. The for each loop is going into the users sheet and finding the username, but for some reason it says that the password is wrong no matter what. I do not know a ton about string comparison and I suspect that one of my conversions or the way I am comparing the passwords is not doing it's job. I have tweaked this a bunch of different ways, but I am missing something basic I think.
Function getSecurityLevel(user As String, pw As String) As Single
Dim userNames As Range
Dim thisUser As Range
Dim uName
Dim userWS As Worksheet
Set userWS = Worksheets("Users")
Application.ScreenUpdating = False
Module4.unprotectUsers
Set userNames = userWS.ListObjects("userTable").ListColumns(3).DataBodyRange
For Each thisUser In userNames
If LCase(CStr(thisUser.Text)) = LCase(user) Then
uName = thisUser.Address
Range(uName).Offset(0, 1).Select
If CStr(ActiveCell.Text) <> pw Then
MsgBox "Your password is incorrect", vbOKOnly
Exit For
Else
ActiveCell.Offset(0, 1).Select
getSecurityLevel = ActiveCell.Value
Exit For
End If
End If
Next thisUser
Module4.hideAll
Application.ScreenUpdating = True
MsgBox "Your username could not be found, please try again", vbOKOnly
End Function
I just need it to properly compare the input password from the userform to the cell next to the matching username, then offset one more and read the security level

This isn't the answer you want but you need to know this.
"Nobody is going to be able to uncover very hidden sheets or get into the code." That is a bold statement and also very untrue.
Setting aside the fact that password protection offered by the VB editor is easily broken.
Anyone with access to the file can change the extension to ZIP. From there, everyone's password is visible as plain text in xl\sharedstrings.xml and your vaunted very hidden worksheet is plainly visible in the file structure and can be unhidden by removing state="veryHidden" in xl\workbook.xml then rezipping and replacing ZIP with the appropriate Excel extension.
Do your users a favor. If you're not going to encrypt passwords and insist on storing them as plain text - then at the very least, do not save them in a file that is distributed to all of your users.
What happens if that file is sent to someone outside the organization or if anyone in your company caught whiff of you sending unencrypted passwords to your users... Think man! This is not the way forward!!!

Related

How to declare a public variable for a specified user login?

I have a login system that works well, using XML files to store logins, and then I can read the users and passwords, see if it matches, if it does, move to the next form, if it doesn't, error message.
However, when the form switches over, I want to be able to display the username in the to left corner, so the user knows who they are displayed as. But I don't know how to memorise the specific user that logged in on the previous form onto the new form now?
I tried making a "public variable" (sort of hard to do for me, not sure if i even did it right), which will read the textbok that the user inputs their name in if the username was correct, and gets dipaslayed for the next form. I don't thin the public vairable worked very well.
If BlnUserFound = True Then
'ActiveUser is the "public vairable"
ActiveUser = tbxUser.Text
'Open the main screen
Me.Hide()
Home.Show()
Else
MessageBox.Show("User Details Not found" & vbCrLf _
& "Please Try Again", "Login Error")
End If
What am I doing wrong?!
Just simply connect it to another new variable name and use it in form 2 e.g
dim ActiveUser2 as string
ActiveUser2 = Form1.ActiveUser then just simply easiest way would be have a label or something on your form, set it to not visible and then just apply ActiveUser2.text to the Label.Text

how to use environ function to avoid other from using my Access DB

I manage an Access DB (accdb) and it contains some information about my company that I don´t want others to access it out of my company´s server.
I thought to use Environ (5)=computername or Environ (12)=path to retrieve some references such as LEN(environ(path)). With this function, I could, for instance, make sure that the accdb file only works if LEN(environ(path))/2+15=55 (the lenght at my company´s server divided by 2 plus 15 = 80/2+15=55 = algorhytm).
So, on opening the db, it should prompt for a number/code. If the user inserts 55 and the filepath = 80, it will open. If filepath=100 (filepath out of my company´s server), must be prompted 100/2+15=65 to open the db.
Unfortunelly, I don't know how to programe it neither I know how to block the use of SHIFT (that breakes the VBA code on opening) because I'm a rookie.
So, if you please, can you help me to solve these huge problems (1. algorhytm using Environ, 2. avoid using SHIFT on opening).
Thanks in advance.
Bruno
Add this code to your startup form. When the form opens it will check for the username and computername, and if both match the form will open.
Private Sub Form_Open(Cancel As Integer)
If Not (Environ("username") = "santosh" And Environ("computername") = "ABC-CAP1-093") Then
Cancel = True
Application.Quit
End If
End Sub
Avoid using shift key - I have already answered see this link

Update an excel file by multiple users at same time without opening the file

Scenario
I have an excel file that contains data. There are multiple users accessing the file at the same time.
Problem
There will be problem if multiple users tried to input data to that excel file at the same time due to only one user is allowed to open the file at one time
Question
Is there any way whereby I can update the excel file (Eg: add a value to a cell, delete a value from a cell, find a particular cell etc) without opening it so that multiple users can update it at the same time using excel VBA?
I went to the direction of using shared files. But later found out to be excel shared files are very buggy. If use shared file, excel/macro can be very slow, intermittent crashes and sometime the whole file may get corrupted and could not be opened or repaired afterwards. Also depends on how many users use the file, the file size can grow quite big. So it is best not to use shared workbook. Totally not worth trying. Instead if need multiple users to update data simultaneously, it is better to use some database such as MSAccess, MSSql (Update MSSQL from Excel) etc with excel. For my situation since number of users are less, I didn't use any database, instead put a prompt for the user to wait until the other user close that file. Please see the codes below to check if a file is opened and if so, to prompt user. I got this code from stack overflow itself and I modified to suit my needs.
Call the module TestFileOpened as below.
Sub fileCheck()
Call TestFileOpened(plannerFilePathTemp)
If fileInUse = True Then
Application.ScreenUpdating = True
Exit Sub
End If
End Sub
Here plannerFilePathTemp is the temporary file location of your original file. Whenever an excel file opened, a temp file will be created. For example, your original file location is as below
plannerFilePath = "C:\TEMP\XXX\xxx.xlsx"
Thus your temporary file location will be
plannerFilePathTemp = "C:\TEMP\XXX\~$xxx.xlsx"
or in other words, temporary file name will be ~$xxx.xlsx
The following codes will be called upon Call TestFileOpened(plannerFilePathTemp)
Public fileInUse As Boolean
Sub TestFileOpened(fileOpenedOrNot As String)
Dim Folder As String
Dim FName As String
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(fileOpenedOrNot) Then
fileInUse = True
MsgBox "Database is opened and using by " & GetFileOwner(fileOpenedOrNot) & ". Please wait a few second and click again", vbInformation, "Database in Use"
Else
fileInUse = False
End If
End Sub
Function GetFileOwner(strFileName)
Set objWMIService = GetObject("winmgmts:")
Set objFileSecuritySettings = _
objWMIService.Get("Win32_LogicalFileSecuritySetting='" & strFileName & "'")
intRetVal = objFileSecuritySettings.GetSecurityDescriptor(objSD)
If intRetVal = 0 Then
GetFileOwner = objSD.Owner.Name
Else
GetFileOwner = "Unknown"
End If
End Function
I encountered Out of memory issues also when used shared files. So during the process, I figured out the following methods to minimize memory consumption
Some tips to clear memory

Ask for password when opening Database - LotusNotes/DominoDesigner

My task is, when opening a database in Lotus Notes, the current user will be ask to input his/her password that was given by his superior. Is there a way how to do that? Just a simple prompt or form that will ask for your password before viewing the database.
Please understand that I do not intend this answer to be disrespectful, but this is really not a task for a beginner at Notes and Domino, as you have stated that you are. You should tell that to your boss. This is a task for someone who has deep understanding of the principles of security and of the mechanisms Notes and Domino provide for it. If you do not understand my comments on #Thomas Adrian's answer, then that applies to you. Again, no disrespect intended.
As security guru Bruce Schneier said, "if you ask amateurs to act as front-line security personnel, you shouldn't be surprised when you get amateur security".
Yes you can put code in queryopendatabase which is located in database script.
Create a button for your superior to store the password in a general profile document within the database
2 when users open the database use the queryopendatabase script to present a password prompt. You can use inputbox in lotus script. Verify the password against the profile document. If a wrong password is entered close the database.
You can use the following code as an embryo, This code use a "real" document but you can easily modify this to be a profile document.
Remember when you test this to close Domino Designer as the NSF is cached as long as DDE is open
Sub Postopen(Source As Notesuidatabase)
Dim db As NotesDatabase
Set db = source.Database
Dim d As NotesDocument, flag As Integer, upw As String, pw As String
upw = InputBox("Enter Password")
Set d = db.getView("Main").getFirstDocument()
If Not d Is Nothing Then
pw = d.password(0)
If pw = upw Then
flag = 1
End If
End If
If flag <> 1 Then Call source.Close()
End Sub

Adding Images into Forms from External Sources using Paths

I've been searching around on Google to find a better way to show images in Access without actually inserting the image into the database.
I found this article 'http://support.microsoft.com/kb/285820' via this thread 'Is there a way to get ms-access to display images from external files' which goes into great detail on how to set paths to pictures through folders/files, and it works great, for a 'set' picture. However, I want a different picture to display when I switch to a different record.
Here is the code from the article:
Option Compare Database
Option Explicit
Public Function DisplayImage(ctlImageControl As Control, strImagePath As Variant) As String
On Error GoTo Err_DisplayImage
Dim strResult As String
Dim strDatabasePath As String
Dim intSlashLocation As Integer
With ctlImageControl
If IsNull(strImagePath) Then
.Visible = False
strResult = "No image name specified."
Else
If InStr(1, strImagePath, "\") = 0 Then
' Path is relative
strDatabasePath = CurrentProject.FullName
intSlashLocation = InStrRev(strDatabasePath, "\", Len(strDatabasePath))
strDatabasePath = Left(strDatabasePath, intSlashLocation)
strImagePath = strDatabasePath & strImagePath
End If
.Visible = True
.Picture = strImagePath
strResult = "Image found and displayed."
End If
End With
Exit_DisplayImage:
DisplayImage = strResult
Exit Function
Err_DisplayImage:
Select Case Err.Number
Case 2220 ' Can't find the picture.
ctlImageControl.Visible = False
strResult = "Can't find image in the specified name."
Resume Exit_DisplayImage:
Case Else ' Some other error.
MsgBox Err.Number & " " & Err.Description
strResult = "An error occurred displaying image."
Resume Exit_DisplayImage:
End Select
End Function
I have a feeling that I need to place a line of code that states something like, show image where Image.ID = "ID", but I can't figure out where to put it without getting errors. Am I over-looking something perhaps, or am I approaching this the wrong way? I just don't want to clutter my database, memory-wise, with .bmp images, but I feel like I am going to have to.
SOLVED: A much easier solution is as Gord Thompson has described below in the comments. And from my own experience, using this method for .bmp images leaves the picture distorted and out of contrast. I tested the image for .jpg and it worked perfectly! I hope this helps others who are having trouble with similar problems finds this post helpful.
The Microsoft Support article you cited applies to Access 2003. In Access 2010 (and later) there is a much simpler way to do it. All you need to do is place an Image control on the form and bind it to the field in your table that contains the path to the image file.
For example, with an [Employees] table like this
EmployeeID FirstName LastName PhotoPath
---------- --------- -------- ---------------------------------
1 Gord Thompson C:\Users\Public\Pictures\Gord.jpg
2 Hank Kingsley C:\Users\Public\Pictures\Hank.png
you could use an Image control whose Control Source is the [PhotoPath] field ...
... and the image will automatically be retrieved from the file specified
No VBA required.
Note also that the image files do not have to be .bmp files.
Added by an anonymous user:
For users of the Microsoft Office 365 version of MS Access (c. 2020), here is what you may need to know in order to get this terrific solution to work:
The [PhotoPath] field in its data table needs to be "Long Text" data type, if using long paths or long file names. The [PhotoPath] field format "Is Hyperlink" may need to be set to "No." I was getting additional, unwanted coding from Access on my text inputs. The [Image3] control may need to specify "Linked" rather than "Embedded."