database search via username - ms-access

I'm developing a call log system, and for tracking purposes the manager wants each user to be logged in upon entry.
I have a module that displays the current logged on user with the code below. I would like for the system to search the table "TBL_Users" for the username and in the text boxes display all the information pertinent to that username. Should that user not be in the database i need to display an error and not allow the user to progress into the system. I'm aware i may need to use a Dlookup but I'm unsure how to code this.
Option Compare Database
Private Declare Function apiGetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Function fOSUserName() As String
' Returns the network login name
Dim lngLen As Long, lngX As Long
Dim strUserName As String
strUserName = String$(254, 0)
lngLen = 255
lngX = apiGetUserName(strUserName, lngLen)
If (lngX > 0) Then
fOSUserName = Left$(strUserName, lngLen - 1)
Else
fOSUserName = vbNullString
End If
End Function
After playing around with Dlookup for a while, I need the text-boxes to populate on form load. This is the Dlookup i used.
Private Sub Form_Load()
Windows_Logontxt = fOSUserName()
'agentname = DLookup("Agent_Name", "TBL_Users", "Windows_Logon=" & Windows_Logontxt)
End Sub

It seems Windows_Logon and Windows_Logontxt are text values, so enclose Windows_Logontxt in quotes when you create the string for the third argument to DLookup.
DLookup("Agent_Name", "TBL_Users", "Windows_Logon='" & Windows_Logontxt & "'")

Related

Microsoft Access - Get UserName and store in a table

I made a table to store which users open a database and when. I have a function to get the usernames in the VBA already since some forms are restricted.
How do I get all usernames stored in the new table along with a time stamp?
Thanks!
I want to track who uses a database, and when they login. That's it. I have a table set up to store the usernames and the timestamp for when someone opens the database
I have the code to get usernames when the database is opened, and it compares to an admin list I have in a table. That code is
Option Compare Database
Declare Function GetUserName& Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long)
Public Function UserName() As String
Dim str As String
Dim lng As Long
str = String$(200, 0)
lng = 199
If GetUserName(str, lng) Then
UserName = Left$(str, lng - 1)
End If
End Function
Create an empty form called "Splash" and make this the form that opens when you open the database (Options->Current Database->Display Form)
Put this code in the Form_Open Event. This will load the screen whenever someone opens the db, insert a record into a table called LoginRecord and then close the form. The action is invisible to the user. Adjust the table/field names in the code to fit your situation.
Private Sub Form_Load()
DoCmd.SetWarnings False
DoCmd.RunSQL "INSERT INTO LoginRecord (UserName, LoginTime) VALUES ('" & Environ("Username") & "','" & Now() & "')"
DoCmd.Close acForm, "Splash"
DoCmd.SetWarnings True
End Sub

Changing a linked table file path to OS username in VBA?

I have linked tables in an Access Database. I want to share this database and the associated excel workbooks with other users. I want to program a one-time use macro that the user will use the first time they use the database to relink the linked tables to the new user's local folder.
For example:
The linked table is current pulling the file from:
C:\Users\jane.doe\Desktop\Database Imports\Premier Account List.xlsx
When the new user (let's say their name is John Smith) relinks the table, it needs to read:
C:\Users\john.smith\Desktop\Database Imports\Premier Account List.xlsx
I basically want to change the file path from my OS Username to new user's OS Username. I already have the code to pull the OS Username, but I'm not sure how to code changing the file path. Here is the code to pull the OS UserName:
Private Declare Function apiGetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Function fOSUserName() As String
' Returns the network login name
Dim lngLen As Long, lngX As Long
Dim strUserName As String
strUserName = String$(254, 0)
lngLen = 255
lngX = apiGetUserName(strUserName, lngLen)
If (lngX > 0) Then
fOSUserName = Left$(strUserName, lngLen - 1)
Else
fOSUserName = vbNullString
End If
End Function
I am fairly new to VBA/Access, so if you could be as specific as possible with your answer, that would be great. Thanks in advanced!
The TableDef object has a Connect property that you need to change. It's a Read/Write String. You just need some string manipulation to make it how you want. Note that if they're moving the database file to the same path, you can just pull CurrentProject.Path rather than futzing with username APIs.
Sub ChangeTableLink()
Dim sNewPath As String
Dim lDbaseStart As Long
Dim td As TableDef
Dim sFile As String
Dim db As DAO.Database
'This is what we look for in the Connect string
Const sDBASE As String = "DATABASE="
'Set a variable to CurrentDb and to the table
Set db = CurrentDb
Set td = db.TableDefs("Fuel Pricing")
'Whatever your new path is, set it here
sNewPath = CurrentProject.Path & "\"
'Find where the database piece starts
lDbaseStart = InStr(1, td.Connect, sDBASE)
'As long as you found it
If lDbaseStart > 0 Then
'Separate out the file name
sFile = Dir(Mid(td.Connect, lDbaseStart + Len(sDBASE), Len(td.Connect)))
'Rewrite Connect and refresh it
td.Connect = Left(td.Connect, lDbaseStart - 1) & sDBASE & sNewPath & sFile
td.RefreshLink
End If
End Sub

VBA script in Access not working

I have a simply MS Access database (version 2010) with just 4 fields:
Name of DB: Test
test1 = Text
test2 = yes/no (tick boxes)
test3 = Text
test4 = Text
I then created a formular named Form_Test and assigned code to the tick box:
Option Compare Database
Option Explicit
Private Declare Function apiGetUserName Lib "advapi32.dll" _
Alias "GetUserNameA" (ByVal lpBuffer As String, _
nSize As Long) As Long
Function BenutzerName() As String
Dim lngLen As Long
Dim lngX As Long
Dim strBenutzerName As String
strBenutzerName = String$(254, 0)
lngLen = 255
lngX = apiGetUserName(strBenutzerName, lngLen)
If lngX <> 0 Then
BenutzerName = Left$(strBenutzerName, lngLen)
Else
BenutzerName = ""
End If
End Function
Private Sub test2_Click()
If test2.Value = True Then
test3 = BenutzerName()
Else
test3 = ""
End If
End Sub
I want to use this code to add the username to the field test3 once the user clicked the tick box in any of the rows. However, the script does not work and I do not understand why. Can anyone help please?
Make sure your code is in right place,
In the Design mode of the form
Right click the Check box and select Properties -> Event Tab->On Click->Code Builder
will open the code editor
That's where your on code must reside
Edit:
In addition, Follow this link to set Breakpoint(F9) in your code to see if your code is being triggered , the link also contains information about debugging.

Cannot pull value from user defined function in Access 2007

I have created this function GetSubName that I need to return the name that is saves from a pull down box. It does this just fine as the dialog boxes I have used shows that it sets the variable correctly. The problem is that when the SQL below runs in a query I get the error: "Undefined function 'GetSubName' in expression." I am new to VBA so any help would be much appreciated.
Here is the code:
Option Compare Database
Option Explicit
Private stSubName As String
Private Sub Command2_Click()
On Error GoTo Err_Command2_Click
Dim stDocName As String
Dim stSubName As String
SubcontractorCombo.SetFocus
stSubName = SubcontractorCombo.SelText
'Confirm that stSubName variable is holding correct value'
MsgBox "Name of Subcontractor Selected is " & stSubName
SetSubName stSubName
GetSubName
DoCmd.Close
stDocName = "Summary Asphalt Production for Subcontractor"
DoCmd.OpenQuery stDocName
Exit_Command2_Click:
Exit Sub
Err_Command2_Click:
MsgBox Err.Description
Resume Exit_Command2_Click
End Sub
Public Sub SetSubName(Value As String)
'Set the module variable to be the value passed in from externally'
stSubName = Value
End Sub
Public Function GetSubName() As String
'Returns the value of the module variable'
GetSubName = stSubName
'MsgBox "GetSubName Variable is " & stSubName'
End Function
And here is my SQL from inside of Access 2007:
SELECT DISTINCTROW Subs.Subcontractor, Counties.County, Projects.ContractID,
Sum(Project_Items.USTons) AS SumOfUSTons, Projects.PlanQuantity,
Max(Project_Items.EstDate) AS MaxOfEstDate, Project_Items.Sub
FROM Counties INNER JOIN (Subs INNER JOIN (Projects INNER JOIN Project_Items ON
Projects.ContractID = Project_Items.ProjectID) ON Subs.VendID = Project_Items.Sub) ON
Counties.ID = Project_Items.County
WHERE (((Projects.Completed)<>True) AND ((Subs.Subcontractor)=GetSubName()))
GROUP BY Subs.Subcontractor, Counties.County, Projects.ContractID,
Projects.PlanQuantity, Project_Items.Sub;
The reason the functions are not recognized is that you haven't fully specified the name. A public function in a form module needs to be specified with the form name:
Forms!MyForm.GetSubName()
But this is the wrong approach, and your code is way too convoluted. You can access the value of the combo box in your query directly:
Forms!MyForm!SubcontractorCombo
Now, the fact that you're using .SelText suggests to me either that you're doing something very very tricky, or you have your combo box set up wrong. Combo boxes can have a found field and a display value, such that a list of employees might display the employee LastName/FirstName while the combo box actually has as its bound field the EmployeeID.
If your combo box has a hidden bound field, but you want the displayed value, you don't need to use .SelText -- just use the appropriate .Column() of the combo box:
Forms!MyForm!SubcontractorCombo.Column(1)
(the column count is zero-based, so the hidden column would be column 0, assuming it's the first column that is hidden)
Also, there's an issue that if the user selects PART of the text in the combo box, you'd have an incomplete match, so you really don't want to use .SelText at all.
So, the WHERE clause of your SQL would end up being this (assuming I've diagnosed everything correctly):
WHERE Projects.Completed<>True
AND Subs.Subcontractor=Forms!MyForm!SubcontractorCombo.Column(1)
...and you can lose all of the marked code:
Option Compare Database
Option Explicit
<strike>Private stSubName As String</strike>
Private Sub Command2_Click()
On Error GoTo Err_Command2_Click
Dim stDocName As String
Dim stSubName As String
SubcontractorCombo.SetFocus
<strike>stSubName = SubcontractorCombo.SelText</strike>
'Confirm that stSubName variable is holding correct value'
<strike>MsgBox "Name of Subcontractor Selected is " & stSubName</strike>
<strike>SetSubName stSubName</strike>
<strike>GetSubName</strike>
DoCmd.Close
stDocName = "Summary Asphalt Production for Subcontractor"
DoCmd.OpenQuery stDocName
Exit_Command2_Click:
Exit Sub
Err_Command2_Click:
MsgBox Err.Description
Resume Exit_Command2_Click
End Sub
<strike>Public Sub SetSubName(Value As String)
'Set the module variable to be the value passed in from externally'
stSubName = Value
End Sub</strike>
<strike>Public Function GetSubName() As String
'Returns the value of the module variable'
GetSubName = stSubName
'MsgBox "GetSubName Variable is " & stSubName'
End Function</strike>
Would an alternative approach work?
Create a table (SubNameTable) with one field: SubName.
Add one record to it.
Then change your Sub to this:
Public Sub SetSubName(Value As String)
CurrentDb.Execute ("Update SubNameTable Set SubName = '" & Value & "'")
End Sub
Now you can Remove the function and modular variable.
Then, alter your SQL as such:
SELECT
*BlahBlahBlahFields*
FROM
*BlahBlahBlahTables*
INNER JOIN Subs
INNER JOIN SubNameTable ON Subs.SubContractor = SubNameTable.SubName
WHERE (((Projects.Completed)<>True)
GROUP BY
Subs.Subcontractor,
Counties.County,
Projects.ContractID,
Projects.PlanQuantity,
Project_Items.Sub
Not that this is the greatest solution, but should solve some future problems of trying to reference a function in a form. You could use a parameter on your query and set its value to the combo box.
You should put the public functions in a Module. I called this one Module2
Option Compare Database
Option Explicit
Private stSubName As String
Public Sub SetSubName(Value As String)
'Set the module variable to be the value passed in from externally'
stSubName = Value
End Sub
Public Function GetSubName() As String
'Returns the value of the module variable'
GetSubName = stSubName
'MsgBox "GetSubName Variable is " & stSubName'
End Function
Your form will reference the functions in the module:
Option Compare Database
Option Explicit
Private stSubName As String
Private Sub Command2_Click()
On Error GoTo Err_Command2_Click
Dim stDocName As String
Dim stSubName As String
SubcontractorCombo.SetFocus
stSubName = SubcontractorCombo.SelText
'Confirm that stSubName variable is holding correct value'
MsgBox "Name of Subcontractor Selected is " & stSubName
Module2.SetSubName stSubName
Module2.GetSubName
DoCmd.Close
stDocName = "Summary Asphalt Production for Subcontractor"
DoCmd.OpenQuery stDocName
Exit_Command2_Click:
Exit Sub
Err_Command2_Click:
MsgBox Err.Description
Resume Exit_Command2_Click
End Sub
The query will be able to find the public function in the module.

Replace Module Text in MS Access using VBA

How do I do a search and replace of text within a module in Access from another module in access? I could not find this on Google.
FYI, I figured out how to delete a module programatically:
Call DoCmd.DeleteObject(acModule, modBase64)
I assume you mean how to do this programatically (otherwise it's just ctrl-h). Unless this is being done in the context of a VBE Add-In, it is rarely (if ever) a good idea. Self modifying code is often flagged by AV software an although access will let you do it, it's not really robust enough to handle it, and can lead to corruption problems etc. In addition, if you go with self modifying code you are preventing yourself from ever being able to use an MDE or even a project password. In other words, you will never be able to protect your code. It might be better if you let us know what problem you are trying to solve with self modifying code and see if a more reliable solution could be found.
After a lot of searching I found this code:
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Function to Search for a String in a Code Module. It will return True if it is found and
'False if it is not. It has an optional parameter (NewString) that will allow you to
'replace the found text with the NewString. If NewString is not included in the call
'to the function, the function will only find the string not replace it.
'
'Created by Joe Kendall 02/07/2003
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Public Function SearchOrReplace(ByVal ModuleName As String, ByVal StringToFind As String, _
Optional ByVal NewString, Optional ByVal FindWholeWord = False, _
Optional ByVal MatchCase = False, Optional ByVal PatternSearch = False) As Boolean
Dim mdl As Module
Dim lSLine As Long
Dim lELine As Long
Dim lSCol As Long
Dim lECol As Long
Dim sLine As String
Dim lLineLen As Long
Dim lBefore As Long
Dim lAfter As Long
Dim sLeft As String
Dim sRight As String
Dim sNewLine As String
Set mdl = Modules(ModuleName)
If mdl.Find(StringToFind, lSLine, lSCol, lELine, lECol, FindWholeWord, _
MatchCase, PatternSearch) = True Then
If IsMissing(NewString) = False Then
' Store text of line containing string.
sLine = mdl.Lines(lSLine, Abs(lELine - lSLine) + 1)
' Determine length of line.
lLineLen = Len(sLine)
' Determine number of characters preceding search text.
lBefore = lSCol - 1
' Determine number of characters following search text.
lAfter = lLineLen - CInt(lECol - 1)
' Store characters to left of search text.
sLeft = Left$(sLine, lBefore)
' Store characters to right of search text.
sRight = Right$(sLine, lAfter)
' Construct string with replacement text.
sNewLine = sLeft & NewString & sRight
' Replace original line.
mdl.ReplaceLine lSLine, sNewLine
End If
SearchOrReplace = True
Else
SearchOrReplace = False
End If
Set mdl = Nothing
End Function
Check out the VBA object browser for the Access library. Under the Module object you can search the Module text as well as make replacements. Here is an simple example:
In Module1
Sub MyFirstSub()
MsgBox "This is a test"
End Sub
In Module2
Sub ChangeTextSub()
Dim i As Integer
With Application.Modules("Module1")
For i = 1 To .CountOfLines
If InStr(.Lines(i, 1), "This is a Test") > 0 Then
.ReplaceLine i, "Msgbox ""It worked!"""
End If
Next i
End With
End Sub
After running ChangeTextSub, MyFirstSub should read
Sub MyFirstSub()
MsgBox "It worked!"
End Sub
It's a pretty simple search but hopefully that can get you going.
additional for the function (looping through all the lines)
Public Function ReplaceWithLine(modulename As String, StringToFind As String, NewString As String)
Dim mdl As Module
Set mdl = Modules(modulename)
For x = 0 To mdl.CountOfLines
Call SearchOrReplace(modulename, StringToFind, NewString)
Next x
Set mdl = Nothing
End Function
Enjoy ^^