I have inherited responsibility for the management of our org's client management system. Data is in ms-sql, data entry is done via .net custom screens, and reporting is done via ms-access.
My predecessor (who never had much tech training) responded to user requests for data by building queries in ms-access, exporting the data and sending the data as an email attachment. What with various attempts to organize things over the years, .mdb's corrupting, and other issues, there are now around 100 .mdb files with his queries in them. Each of the mdbs may have around 100 queries.
Now, users will email me with the attachment he sent them and say "your predecessor created this report for me a few months ago. Can you run it again?" I can see the name of the query because it is the name of the exported excel file. I go and open the .mdb files he used most and look for the query name but am unable to find many of them.
Any ideas of how I could run something against the entire folder directory of .mdb files to get a list of all queries in the .mdb files?
Any ideas are welcome, thanks much.
You can use Dir to loop the filenames:
Public Function ListQueries()
Const Path As String = "C:\Test\"
Dim Workspace As DAO.Workspace
Dim Database As DAO.Database
Dim Query As DAO.QueryDef
Dim Filename As String
Set Workspace = DBEngine(0)
Filename = Dir(Path & "*.mdb", vbNormal)
While Filename <> ""
Debug.Print Filename
Set Database = Workspace.OpenDatabase(Path & Filename, , True)
For Each Query In Database.QueryDefs
If Asc(Query.Name) <> 126 Then
Debug.Print , Query.Name
End If
Next
Database.Close
Filename = Dir
Wend
End Function
Related
I have a front end DB, which needs to link to different back end DBs. To give you perspective, it relates to stand alone MDB files. The software in question builds a DB per company.
At the moment I am writing code within one of these MDB files.
For scalability I am now creating a new DB which will link to each MDB via code, and therefore my questions are as follows
How do I change the linked table location via code / VB so that the user can select the company / DB they want to work on
How do I do this with passing a username and password which is the same for all of the companies / DBs
And as per below we need to verify the username and password via the systemDB for it to open successfully.
As an FYI, this is how we open the DB on a standalone basis-
"C:\Program Files (x86)\Microsoft Office\root\Office16\MSACCESS.EXE" "C:\temp\SAMPLE.mdb" /WRKGRP "C:\ProgramData\SOFTWARE\SYSTEM.mdw" /user:username /pwd:password
This is not a problem at all and is absolutely able to be accomplished given the clarification that you are using a single MDW file.
To clarify Microsoft Access Workgroup Security is essentially a "session" security model that applies directly to the front-end MDB file as you open it.
Your example command line means that Microsoft Access will open the SAMPLE.MDB front-end file using the workgroup file you specified.
Once Microsoft Access has opened SAMPLE.MDB under that workgroup file, you cannot change to another workgroup file within that "session" without closing Microsoft Access and re-opening under the new workgroup file.
FYI - it IS possible to open via code, a table in another MDB using another workgroup file within that connection, but in this manner, the table is only usable in code as a RecordSet (for example), you can't make it a linked table.
Anyway, back to your real issue. How to link a different back-end set of tables for each Company.
My recommendation would be to add a few fields to your Company table that defines the filename and location of each back-end file. For example:
Notice that the location can be a UNC path, or a mapped drive path. Or maybe you don't need to define a location in the table explicitly. Maybe all of the back-ends are in the same folder, or in a definable dynamic location like \Dallas\Dallas.mdb, \NewYork\NewYork.mdb, etc. As long as you can determine the location of each back-end in some manner, then you are fine.
Now, since you will likely have "global" front-end tables, maybe also some "global" linked back-end tables i.e. Common.mdb, and your company-specific back-end tables, I would recommend having a front-end table that defines the name of each of the tables that is involved only in the company-specific files. That way, we can easily loop through just those table names and make the link changes.
For the linking code, let's say that you have prompted the User for which Company they want, and you pass the CompanyID to a re-linking function:
Public Function ChangeCompanyLinks(CompanyID As Long) As Boolean
Dim db As DAO.Database
Dim ldb As DAO.Database
Dim tdf As DAO.TableDef
Dim rstCompany As DAO.Recordset
Dim rstTables As DAO.Recordset
Dim mssql As String
Dim dbFullPath As String
Dim retVal As Boolean
Set db = CurrentDb()
retVal = False
mssql = "SELECT * FROM [tblCompany] WHERE [CompanyID] = " & CompanyID
Set rstCompany = db.OpenRecordset(mssql, dbOpenSnapshot)
If Not rstCompany.BOF Then
dbFullPath = rstCompany("DBLocation") & "\" & rstCompany("DBName")
If Dir(dbFullPath) = rstCompany("DBName") Then
'NOTE: By opening a temporary constant link to the back-end during
' relinking, the relinking runs faster
Set ldb = OpenDatabase(dbFullPath)
mssql = "SELECT * FROM [tblLinkedTables] WHERE [FileType] = ""Company"""
Set rstTables = db.OpenRecordset(mssql, dbOpenSnapshot)
Do While Not rstTables.EOF
Set tdf = db.TableDefs(rstTables("TableName"))
tdf.Connect = ";DATABASE=" & dbFullPath
tdf.RefreshLink
rstTables.MoveNext
Loop
rstTables.Close
ldb.Close
retVal = True
Else
MsgBox "Unable to Locate Company File"
End If
End If
rstCompany.Close
ChangeCompanyLinks = retVal
Set rstCompany = Nothing
Set rstTables = Nothing
Set ldb = Nothing
Set tdf = Nothing
db.Close
Set db = Nothing
End Function
Obviously you will want to add error handling, and customize this a bit to fit your situation, but this code will re-link the specified tables to a new back-end.
Please note that if you eventually change to have your back-end tables in SQL Server (which I highly recommend), the re-linking code would need to be modified a bit. See this answer for more details on that.
I need to create copies of the CurrentDB using VBA (approx. 12 copies). The copies need to be clones of the master database containing all the same forms, queries, etc. except only a limited dataset.
DoCmd.CopyDatabaseFile seems to be made for this, but only works if you are using it to copy the DB to an MS SQL Server. As MS states on their website:
Copies the database connected to the current project to a Microsoft
SQL Server database file for export.
docmd.TransferDatabase only exports the data itself, but not the structure, forms, etc.
Code I have found on the web and adapted doesn't work and throws an error on the .CopyFile line saying:
Run-time error 52: Bad file name or number
This is the code
Sub CopyDB()
Dim external_db As Object
Dim sDBsource As String
Dim sDBdest As String
sDBsource = "\\group\bsc\groups\L\BDTP\Compliance\ComplianceData\Compliance Group Reporting.accdb"
sDBdest = "\\group\bsc\groups\L\BDTP\Compliance\ComplianceData\Compliance Group Reporting_2.accdb"""
Set external_db = CreateObject("Scripting.FileSystemObject")
external_db.CopyFile sDBsource, sDBdest, True
Set external_db = Nothing
End Sub
How can I fix the above line? Alternatively is there a direct command in Access to create a copy? The "create backup" function would be tailor made for this, but I can not find it in VBA.
Looks like you have an extra quote in sDBdest accdb"""
And for database copy you can also use
FileCopy sDBsource, sDBdest
Instead of Scripting object
I'm playing around with splitting access databases. It appears that each table contains a hard link to the backend file in the linked table manager.
But if I wanted to send the file pair to someone through email to look at, the hard links will break. Right now we're at separate offices just testing changes to the program. This isn't in production. I don't want them to get into the development mode and edit the linked table manager because it would be too hard.
Is there a way to tell access to simply look in the front end file's directory for the backend file? Is there a way to force a prompt on the front end to let them choose the location of the backend file?
Thanks!
The simple solution is to on startup check if the table link(s) point to the current directory, and if not, then you run re-link code. That way the pair of files will work if you move the pair to a different folder or re-name the folder.
The above is a common setup and EVEN recommend for single user applications that SHOULD be split and benefit by being split.
So on startup, check the path of a linked table. I use the following code to return the path of currently linked tables.
Function strBackEndPath() As String
' returns the path name to the back end
' and includes tralinig \
Dim mytables As TableDef
Dim strTempBack As String
Dim strFullPath As String
strFullPath = ""
For Each mytables In CurrentDb.TableDefs
If Left(mytables.Connect, 10) = ";DATABASE=" Then
strFullPath = Mid(mytables.Connect, 11)
Exit For
End If
Next mytables
strBackEndPath = Left(strFullPath, InStrRev(strFullPath, "\"))
End Function
With above, then on startup I can go:
If CurrentProject.path & "\" <> strBackEndPath Then
' call re-link code
End If
And there are TONS of re-link code examples floating around but here is a link to some re-linking code.
http://access.mvps.org/access/tables/tbl0009.htm
Thus if the links don’t point to the back end database in the same folder, then re-linking will ONLY occur once and after that only the above “test” to ensure that front end and back end are are linked.
If the folder is renamed or as noted a user moves the files to a different location then again the re-link will occur.
Right-click on the front-end tables and select Linked Table Manager. From there, you can browse for the location of the back-end tables
I have an old Access db with a plethora of lookup tables. Supposedly it was a warehouse of sorts for a bunch of other dept-made access apps to link to. We want to kill it. But, id there a way to find out if any app is currently linked to it?
You need the full path and filename of all the Access apps; this may not be possible.
For those you can, loop through all the files:
connect to each database to test for link.
Loop through all the tables in TestForLinkDatabase.TableDefs
Check to see if there is a .SourceTableName and the .Connect = YourLookupTableWarehouse for each table. I think the SourceTableName is an empty string for local tables.
Keep track of #3. You can optionally stop checking the rest of the tables if you find a single instance in the other file.
Again, it is not foolproof, but would be a good exercise to get a grip on all the Access apps floating around your company.
*Code does not exclude system tables.
Private Sub CheckToSeeIfLinked()
Dim Dbs As DAO.Database
Dim Tdf As DAO.TableDef
Dim Tdfs As TableDefs
Dim wrk As DAO.Workspace
Set wrk = DBEngine.Workspaces(0)
Dim TestDatabaseForLinks As String
TestDatabaseForLinks = "C:\FileNameToCheck.mdb"
Set Dbs = wrk.OpenDatabase(TestDatabaseForLinks)
Set Tdfs = Dbs.TableDefs
For Each Tdf In Tdfs
If Tdf.Connect <> "" Then
Debug.Print "Table: " & Tdf.Name & " - Is Linked To: " & Tdf.Connect
Else
Debug.Print "Table: " & Tdf.Name & " is not linked"
End If
Next
If Not (Dbs Is Nothing) Then
Dbs.Close
Set Dbs = Nothing
Set Tdfs = Nothing
End If
End Sub
Move it to another directory. Linked tables have hard-coded paths.
Not while the database isn't in use. When it is in use you should see an LDB/LACCDB file. You can open it with Notepad to see the workstation name.
If you are using Access security you will also see the Access userid. Otherwise you will see "Admin"
Opening the .ldb/.laccdb file using notepad will show you both who's currently in the database and some of the workstations which were in the database. When a person exits Access their workstation name and Access login id, Admin unless you are using Access security, are left in a "slot" or record in the ldb file. This slot or record may get overwritten the next time someone enters the MDB depending on what slot or record is available previous to it in the ldb file.
Determining the workstation which caused the Microsoft Access MDB corruption
At work we have this reporting tool. It is distributed to everyone as a MDE tool that is locked up pretty good (VBA is unviewable, cannot import any of the table, query, forms, etc). When each person fills out their applicable portion there is a button that conslidates it into a text file, and then sends it to Outlook. Then everyone emails it to one person.
So I have come up with need to use this in my own database:
Remote Employees fill out a form that creates a power point presentation for them, and this part I think I have nailed down. This helps us track metrics on these presentations, rather than the employee manually creating a the ppt, and then we coming behind and manully entering the data from the brief into a form. Makes sense right.
Here is my problem, at the office, this is solved, but for those out in the field I need a similiar tool like the one mentioned above; where they get the benefit of the autogenerated ppt, and then I can have them send me the text file through email I can add to the db.
Here are my questions because I am just getting into the beginning of this:
-The form is pretty long because there is A LOT of info going into a ppt, so I use one form with tabs for different sections, but it all becomes on record in the table, and one ppt. How do I turn all this information, this one record, into a text file, and how do I use the Send to Outlook, all with one button click??
-When the user emails em the text file, how do I import it into the database table?
-How do you lock up a MDE so that the VB is unviewable, and the object cannot be imported into another application?
any other advice, tips, "your crazy man!"s, are welcome! thanks as always!
Have you considered replication rather that a text file? The data would be stored in a replicated back-end file with Access Security, which could be returned to you. CDO should suit for emailing.
Text
Access has DoCmd.TransferText, which will allow you to both export and import a text file.
CDO
Private Sub SendEmailCDO()
'Requires reference to Microsoft CDO for Windows 2000
Dim cdoConfig As Object
Dim strSubject As String
Dim strBody As String
Dim strFile As String
Dim cdoMessage As Object
'Set up detail of the mail server
Set cdoConfig = CreateObject("CDO.Configuration")
With cdoConfig.Fields
.Item(cdoSendUsingMethod) = 2 ''cdoSendUsingPort
.Item(cdoSMTPServerPort) = 25
.Item(cdoSMTPServer) = "smpt.themailserver.com"
.Item(cdoSendUserName) = "abc#themailserver.com"
.Item(cdoSendPassword) = "password"
.Update
End With
''This is the subject line for the email.
strSubject = "Membership List"
''This is the message with a little HTML.
strBody = "<P>Here is the membership list for <FONT color=#ff0000>" _
& Format(Date, "mmmm yyyy") & "</FONT>.</P><P>Regards, LTD</P>"
''Location of Attachment
strFile = "C:\Docs\MembershipList.rtf"
''Set up the email message
Set cdoMessage = CreateObject("CDO.Message")
With cdoMessage
.Configuration = cdoConfig
.Subject = strSubject
.From = "me#here.com"
.To = "someone#there.com"
.HTMLBody = strBody
.AddAttachment strFile
.Send
End With
End Sub
Further information: http://wiki.lessthandot.com/index.php/Access_and_Email
#Justin asks:
-How do you lock up a MDE so that the VB is unviewable, and the object
cannot be imported into another
application?
The question makes no sense, unless the person asking it has failed to grasp what an MDE is. THERE IS NO VIEWABLE CODE LEFT IN AN MDE. It has been stripped out and all that remains is the compiled p-code. For an a helpful article on VBA compilation in Access that incidentally explains the relationship between canonical code and compiled p-code, see Michael Kaplan's "The real deal on the /Decompile switch."
Keep in mind that this applies only to code-bearing objects (forms/reports/modules) and not to tables and queries.