I have the below code to open a connection to another Access database and then open a recordset
Sub OpenTest()
Dim Acon As New ADODB.Connection
Dim rst As ADODB.Recordset
With Acon
.Provider = "Microsoft.ACE.OLEDB.12.0"
.ConnectionString = "C:\MyFolder\MyDb.accdb"
.Properties("Jet OLEDB:Database Password") = "OpenSesame"
.Open
End With
Set rst = New ADODB.Recordset
rst.Open "SELECT * FROM tblAdmin", Acon, adOpenDynamic, adLockReadOnly
If rst.EOF = False Or rst.BOF = False Then
rst.MoveFirst
Debug.Print rst!UserID
End If
Set rst = Nothing
Acon.Close
End Sub
The connections itself opens fine but then strangely the recordset fails to open and I get a run time error saying
Not a valid password
The password is definitely correct (as evidenced by the connection opening). When setting the password on the database I ensured that the legacy encryption option was selected for compatability. I have also used this code to open a different database and it works fine.
Does anybody have any idea why it may not be working?
For anyone that is interested. I found the problem. It was just because the table I was trying to use in the recordset was actually a linked table. I changed the file path to the one for the back end and it now works fine.
ヾ(`ヘ´)ノ゙
Related
I can connect to Oracle with a Passthrough query using ODBC to Oracle but the issue I have is because I have multiple databases that all use the same connections I want to store my credentials for the servers in an Excel encrypted file so nobody can see my passwords and only need to update in one place instead of every database but when I try and connect with my passthrough it doesnt work but does if I manually declare them in vba.
The Error Message is 3151 - ODBC - connection to '{Oracle in OraClientName}Server' failed
This is my code and dont know why it doesnt work? I tried with DSN and its the same result?
Function MyConnection()
On Error Resume Next
DoCmd.DeleteObject acQuery, "MY_TRANS"
Err.Clear
On Error GoTo 0
'''''GET EXCEL LOGIN DETAILS
Dim xlsApp
Set xlsApp = CreateObject("Excel.Application")
Dim WkBk As Excel.WorkBook
Set WkBk = xlsApp.WorkBooks.Open(FileName:="FILE LOCATION.xlsx", Password:="MYPASSWORD")
Dim LOGONNAME As String
Dim PWD As String
LOGONNAME = WkBk.Sheets(1).Range("B3").Value
PWD = WkBk.Sheets(1).Range("D3").Value
If Not (xlsApp Is Nothing) Then xlsApp.Quit
'end excel stuff
xlsApp.Quit
Set xlsApp = Nothing
'THIS WORKS IF I UNCOMMENT
'LOGONNAME = "MYNAME"
'PWD = "PASSWORD"
Dim db As DAO.Database
Dim ExtData As QueryDef
Dim strSQL As String
Set db = CurrentDb
strSQL = "SELECT * FROM TABLE"
Set ExtData = db.CreateQueryDef("MY_TRANS")
ServerName = "MYSERVER"
ExtData.Connect = "ODBC;DRIVER={Oracle in OraClientName};Server=" & ServerName & ";DBQ=DBQNAME;UID=" & LOGONNAME & ";Pwd=" & PWD & ""
ExtData.SQL = strSQL
DoCmd.OpenQuery "MY_TRANS"
DoCmd.Close acQuery, "MY_TRANS"
ExtData.Close
db.Close
Set db = Nothing
END FUNCTION
#Andre Your Comment fixed the issue The Answer is if you get false after typing Debug.Print LOGONNAME, (LOGONNAME = "MYNAME") and doing the same for the password then you will need to go into the excel and check the details are the same or retype and check again. This fixed the issue for me.
Please can somebody help me with this problem.
I have a Form in VBA and from this from I want to run some SQL queries and retrieve the data from my database and then place the result in a Text box in the Form(GUI)
I have about 20 tables in my Database but surprisingly to me I am only able to access the first table (InventoryCompleteList).
Every attempt to access another table returns an error saying for example (Invalidobject name 'functionalTestResults') whereas when I run the query for (inventoryCompleteList), it seems to be working. Note functionalTestResults and inventoryCompleteList are both tables in my sql server
Please can anyone help me figure out what the problem might be.
Below is the view of my DB
`Private Sub ENTER_Click()
Dim cn As Object
Dim rs As Object
Dim strFile As String
Dim strCon As String
Dim strSQL, strInput As String
strCon = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security
Info=True;Initial Catalog=KBOW;Data Source=10.23.30.8\KBOW;Use Procedure
for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation
ID=ULWW101;Use Encryption for Data=False;Tag with column collation when
possible=False;"
Set cn = CreateObject("ADODB.Connection")
cn.Open strCon
strSQL = "SELECT Date,Location FROM functionalTestResults;"
'Added the following four lines
Set rs = CreateObject("ADODB.RECORDSET")
rs.ActiveConnection = cn
rs.Open strSQL
Sheet1.Range("A1").CopyFromRecordset rs
Result.Text = "CopyFromRecordset rs"
'removed
'cn.Execute strSQL
rs.Close
cn.Close
Set cn = Nothing
End Sub
`
You need to be granted "Select" on those tables, as it seems you currently do not have this permission.
Speak with your dba about being granted access to this table.
Help please!
I've created a database for logging service calls, based on one of Microsoft's templates (Very loosely based now!)
I have a "Case Details" form, which is opened from a case list split form. Originally, this was opening the form with a filter - which I assume means that it is actually loading the whole recordset?
As I assume (hopefully correctly) that this will be quite inefficient as the database grows, I decided to change the form to open and ADO recordset, using a SQL statement, only selecting the record I want.
The code for this is as follows, and the form opens with the correct record, and I can update the fields.
Private Sub Form_Load()
On Error GoTo Form_Load_Err
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
If (IsNull(TempVars!currentid)) Then
Me.DataEntry = True
Else
'Use the ADO connection that Access uses
Set cn = CurrentProject.Connection
'Create an instance of the ADO Recordset class,
'and set its properties
Set rs = New ADODB.Recordset
With rs
Set .ActiveConnection = cn
.Source = "SELECT * FROM Cases WHERE ID = " & TempVars!currentid & ";"
.LockType = adLockOptimistic
.CursorLocation = adUseClient
.CursorType = adOpenStatic
.Open
End With
'Set the form's Recordset property to the ADO recordset
Set Me.Recordset = rs
Set rs = Nothing
Set cn = Nothing
End If
Call IntializeCollections
Select Case (Me.Status)
Case 7, 8
Call EnableControls(mcolgrpAllFields, False)
End Select
Form_Load_Exit:
Exit Sub
Form_Load_Err:
MsgBox Error$
Resume Form_Load_Exit
End Sub
However, here is the problem. What the blinking heck do I do to save my changes? I've done some googling, and looked at MS Access Form Bound to ADO Disconnected Recordset but I'm still absolutely stumped.
Is there as simple "save the updates" command? or do I have to iterate through each field, check for changes, then save those changes?
Can someone please point me in the right direction?
Thanks in advance
If you need to update one record at a time try this solution for disconnected recordsets: http://www.techrepublic.com/blog/how-do-i/how-do-i-pass-data-over-a-network-using-disconnected-recordsets/
I actually have 2 questions:
1. How might I see who is using my Access database?
E.g: There is someone with an Access database opened and it created the .ldb file, I would like to see a list of who opened that database (it could be more than one person).
2. How might I see who is using a linked table?
E.g: I have 10 different Access databases, and all of them are using a same linked table. I would like to see who is using that linked table.
I don't even know if it's really possible, but I really appreciate your help!
For you information: The main problem is that lots of people use the same Access in the same network drive, so when I need to change it I have to kick them all out, but I never know who is actually using it.
Update: Rather than reading and parsing the .ldb/.lacdb file, a better approach would be to use the "User Roster" feature of the Access OLEDB provider as described in the Knowledge Base article
https://support.microsoft.com/en-us/kb/285822
and in the other SO question
Get contents of laccdb file through VBA
Original answer:
I put together the following a while ago. It looked promising but then I discovered that computers are not immediately removed from the lock file when they disconnect. Instead, Jet/ACE seems to (internally) mark them as inactive: If ComputerA disconnects and then ComputerB connects, ComputerB overwrites ComputerA's entry in the lock file.
Still, it does provide a list of sorts. I'm posting it here in case somebody can offer some suggestions for refinement.
I created two tables in my back-end database:
Table: [CurrentConnections]
computerName Text(255), Primary Key
Table: [ConnectionLog]
computerName Text(255), Primary Key
userName Text(255)
A VBA Module in my back-end database contained the following code to read (a copy of) the lock file and update the [CurrentConnections] table:
Public Sub GetCurrentlyConnectedMachines()
Dim cdb As DAO.Database, rst As DAO.Recordset
Dim fso As Object '' FileSystemObject
Dim lck As Object '' ADODB.Stream
Dim lockFileSpec As String, lockFileExt As String, tempFileSpec As String
Dim buffer() As Byte
Set cdb = CurrentDb
cdb.Execute "DELETE FROM CurrentConnections", dbFailOnError
Set rst = cdb.OpenRecordset("SELECT computerName FROM CurrentConnections", dbOpenDynaset)
lockFileSpec = Application.CurrentDb.Name
If Right(lockFileSpec, 6) = ".accdb" Then
lockFileExt = ".laccdb"
Else
lockFileExt = ".ldb"
End If
lockFileSpec = Left(lockFileSpec, InStrRev(lockFileSpec, ".", -1, vbBinaryCompare) - 1) & lockFileExt
'' ADODB.Stream cannot open the lock file in-place, so copy it to %TEMP%
Set fso = CreateObject("Scripting.FileSystemObject") '' New FileSystemObject
tempFileSpec = fso.GetSpecialFolder(2) & "\" & fso.GetTempName
fso.CopyFile lockFileSpec, tempFileSpec, True
Set lck = CreateObject("ADODB.Stream") '' New ADODB.Stream
lck.Type = 1 '' adTypeBinary
lck.Open
lck.LoadFromFile tempFileSpec
Do While Not lck.EOS
buffer = lck.Read(32)
rst.AddNew
rst!computerName = DecodeSZ(buffer)
rst.Update
buffer = lck.Read(32) '' skip accessUserId, (almost) always "Admin"
Loop
lck.Close
Set lck = Nothing
rst.Close
Set rst = Nothing
Set cdb = Nothing
fso.DeleteFile tempFileSpec
Set fso = Nothing
End Sub
Private Function DecodeSZ(buf() As Byte) As String
Dim b As Variant, rt As String
rt = ""
For Each b In buf
If b = 0 Then
Exit For '' null terminates the string
End If
rt = rt & Chr(b)
Next
DecodeSZ = rt
End Function
The following code in the Main_Menu form of the front-end database updated the [ConnectionLog] table
Private Sub Form_Load()
Dim cdb As DAO.Database, rst As DAO.Recordset
Dim wshNet As Object '' WshNetwork
Set wshNet = CreateObject("Wscript.Network")
Set cdb = CurrentDb
Set rst = cdb.OpenRecordset("SELECT * FROM ConnectionLog", dbOpenDynaset)
rst.FindFirst "ComputerName=""" & wshNet.computerName & """"
If rst.NoMatch Then
rst.AddNew
rst!computerName = wshNet.computerName
Else
rst.Edit
End If
rst!userName = wshNet.userName
rst.Update
Set wshNet = Nothing
End Sub
Finally, the following form in the back-end database listed [its best guess at] the current connections
It is a "continuous forms" form whose Record Source is
SELECT CurrentConnections.computerName, ConnectionLog.userName
FROM CurrentConnections LEFT JOIN ConnectionLog
ON CurrentConnections.computerName = ConnectionLog.computerName
ORDER BY ConnectionLog.userName;
and the code-behind is simply
Private Sub Form_Load()
UpdateFormData
End Sub
Private Sub cmdRefresh_Click()
UpdateFormData
End Sub
Private Sub UpdateFormData()
GetCurrentlyConnectedMachines
Me.Requery
End Sub
Easy. Open the .ldb file in notepad (or any text editor) and you can see the machine names.
RE: How might I see who is using my Access database?
•E.g: There is someone with an Access database opened and it created the .ldb file, I would like to see a list of who opened that database (it could be more than one person).
Just happened across this while looking for something else, and I thought I might share what I do for this. Note that this assumes that the host computer (the computer on which the database file resides) uses file sharing to provide access to the file.
You will need to be on the host computer, or have authority to connect to that machine.
click Start
right-click My Computer and select Manage
if you're not on the host computer, right-click 'Computer Management' and enter the host's name
Expand 'Shared Folders' and click on 'Open Files'
At the right is the list of currently open files with the username for each current user
I agree with Gord's Original answer. I used this code on my database, it seems that there is a way around computers not being taken out of CurrentConnections upon exit of the DB.
I placed this on my main menu form because it is always open until the user exits. I used the unload event on my form to get this to work, and it works awesome! Here is my code
p.s. Ignore SetWarnings I just have that on so the user doesn't have to click through prompts.
Private Sub Form_Unload(Cancel As Integer)
Dim wshNet As Object
Dim deleteSQL As String
Set wshNet = CreateObject("WScript.Network")
DoCmd.SetWarnings False
deleteSQL = "DELETE tblCurrentConnections.* " & _
"FROM tblCurrentConnections WHERE[computerName] = '" & wshNet.computerName & "';"
DoCmd.RunSQL deleteSQL
DoCmd.SetWarnings True
End Sub
I am currently working on moving 100s of access databases from a variety of folders to another set of folders and need to update any references to linked tables that will be broken during the move. I have identified how to update the location of the linked database table by adding a macro to the access database itself by doing something like the following:
Dim tdf As TableDef, db As Database
Set db = CurrentDb
db.TableDefs.Refresh
For Each tdf In db.TableDefs
' My Logic for checking to see if it is is a linked
' table and then updating it appropriately
Next
Set collTables = Nothing
Set tdf = Nothing
Set db = Nothing
However, I do not want to have to add the code to each of the access databases so I was wondering if there was a way to create a VBS file which would execute the same type of logic. I tried the following code, but I am getting the following error when the line with the for each logic is executed: "Arguments are of the wrong type, are out of acceptable range or are in conflict with one another"
Set MyConn = CreateObject("ADODB.Connection")
MyConn.Open "Provider = Microsoft.Jet.OLEDB.4.0; Data Source = MyFile.mdb"
for each tblLoop in db.TableDefs
' business logic
next
set tblLoop = nothing
MyConn.close
set MyConn = nothing
I'm hoping that someone more familiar with doing this type of coding will be able to point me in the right direction. Is there a way to utilize the TableDefs table from outside of Access through a VBS file and if so, what would that code look like.
Thanks,
Jeremy
You cannot use tabledefs with ADO, but you can open the database in VBScript:
Dim db ''As DAO.Database
Dim ac ''As Access Application
''As noted by wmajors81, OpenDatabase is not a method of the application object
''OpenDatabase works with DBEngine: http://support.microsoft.com/kb/152400
Set ac = CreateObject("Access.Application")
ac.OpenCurrentDatabase("c:\test.mdb")
Set db = ac.CurrentDatabase
For Each tdf In db.TableDefs
Etc.
If you have start up code or forms, or database passwords, you will run into some problems, but these can be overcome, for the most part, by simulating the shift key press. This would be easier, I think, in VBA than VBScript, but AFAIK it is possible in VBScript. database passwords can be supplied in the OpenDatabase action.
I was able to expand upon the answer by #Remou to come up with some code that worked. Part of his answer included the following statement which threw an error "Set db = ac.OpenDatabase". As far as I can tell "OpenDatabase" is not a valid method, but OPenCurrentDatabase is. Also, I was getting an error when trying to set db equal to the value returned by OpenCurrentDatabase so I'm assuming that it is a sub and not a function. However, I was able to get access to the Current Database by utilizing ac.CurrentDB once I had established the connection to the the database utilizing OpenCurrentDatabase
Dim db ''As DAO.Database
Dim ac ''As Access Application
Set ac = CreateObject("Access.Application")
ac.OpenCurrentDatabase("D:\delete\UpdatingLinkedTableInAccess\GrpLfRsvs201108.mdb")
set db = ac.CurrentDB
For Each tdf In db.TableDefs
With tdf
If Len(.Connect) > 0 Then
If Left(.Connect, 4) = "ODBC" Then
' ignore these are connected via ODBC and are out of scope
Else
' biz logic
End If
End If
End With
next
set db = nothing
ac.Quit
set ac = nothing
Thanks again #Remou for your assistance.
You don't need to create an Access application instance. Use DBEngine and DAO.Workspace instead.
Option Explicit
Dim db
Dim dbe
Dim strDbPath
Dim tdf
Dim wrkJet
strDbPath = "C:\Access\webforums\whiteboard2003.mdb"
Set dbe = CreateObject("DAO.DBEngine.36")
Set wrkJet = dbe.CreateWorkspace("", "admin", "", 2) ' dbUseJet = 2
' exclusive = True and read-only = False '
Set db = wrkJet.OpenDatabase(strDbPath, True, False)
For Each tdf In db.TableDefs
If Left(tdf.Connect, 10) = ";DATABASE=" Then
WScript.Echo tdf.Connect
End If
Next
db.Close
Set db = Nothing
Set wrkJet = Nothing
Set dbe = Nothing
You would need "DAO.DBEngine.120" for ACCDB format database.
If you're using a database password, include it in OpenDatabase.
Set db = wrkJet.OpenDatabase(strDbPath, True, False, ";pwd=password")