Yesterday I had to run a query in MS Access 2010. One field I needed was not in the tables I usually use (already linked through the ODBC Database) and I didn't know what table it was a part (there are several hundred tables in the Machine Data Sources). Aside from manually importing all the tables and looking in each one for this field is there a way I can search for a field without knowing the table either 1. without importing any tables from the ODBC Databases, or if not 2. importing a handful of possible tables and searching once those tables have been linked into my active MS Access 2010 session?
Install Access Dependency Checker, link all tables and search for column name (enable checkbox for search in linked tables)
You could do this in a Function using ADO schema's.
Try this function in a standard module:
Function ListTablesContainingField(SelectFieldName) As String
Dim cn As New ADODB.Connection
Dim rs As ADODB.Recordset
Dim strTempList As String
Set cn = CurrentProject.Connection
'Get names of all tables that have a column called <SelectFieldName>
Set rs = cn.OpenSchema(adSchemaColumns, _
Array(Empty, Empty, Empty, SelectFieldName))
'List the tables that have been selected
While Not rs.EOF
'Exclude MS system tables
If Left(rs!Table_Name, 4) <> "MSys" Then
strTempList = strTempList & "," & rs!Table_Name
End If
rs.MoveNext
Wend
ListTablesContainingField = Mid(strTempList, 2)
rs.Close
Set cn = Nothing
End Function
Related
I have many Access database files that contain linked tables to a SQLServer database. Now the database server has changed and I have to edit the links, possibly without recreating them.
it's possible to do it? I use Access 2013.
Yes it is possible to do with VBA but the way you'll do it really depends on how you linked the tables.
Here are 2 example of connection strings I use for SQL server tables
Direct connection:
Driver=SQL Server Native Client 10.0;Server=server_name;Address=server_address,1433;Network=network_name;Database=database_name;Trusted_Connection=Yes
DSN connection (with an entry in the ODBC control panel)
ODBC;Provider=SQLNCLI10;Server=server_name;DSN=name_of_DSN_entry_in_ODBC_control_panel;Database=database_name;Trusted_Connection=Yes
So the first thing to do is to determine how your tables are linked.
You can use this code (pay attention to the comments):
Public Sub Check_ODBC_tables()
Dim tdef As TableDef
' First loop on all tables to determine the connection strings
For Each tdef In CurrentDb.TableDefs
' only print the constring if the database name is your old database (adapt accordingly)
If InStr(tdef.Connect, "Database=old_database_name") Then
Debug.Print tdef.Connect
End If
Next
End Sub
Run this code (F5) and check the output in the immediate window. You'll find how the table are linked and what are the connection strings.
You should prepare a connection string based on that, and adapt in them the database name to use your new DB.
Once you are ready, you can adapt and run the following code that will delete the old table and recreate them with the new database names (some tweaks might be necessary), so go thought it in debug mode !
Public Sub Change_ODBC_tables()
Dim tDef As TableDef
Dim tDefNew As TableDef
Dim strTable As String
Dim strCOnString As String
' examples of constrings - ADAPT!!!!
strCOnString = "Driver=SQL Server Native Client 10.0;Server=server_name;Address=server_address,1433;Network=network_name;Database=database_name;Trusted_Connection=Yes"
strCOnString = "ODBC;Provider=SQLNCLI10;Server=server_name;DSN=name_of_DSN_entry_in_ODBC_control_panel;Database=database_name;Trusted_Connection=Yes"
For Each tDef In CurrentDb.TableDefs
If InStr(tDef.Connect, "Database=old_database_name") Then
' We find a match, store the table name
strTable = tDef.Name
' delete the linked table
DoCmd.DeleteObject acTable, strTable
' recreate the linked table with new DB name
Set tDef2 = CurrentDB.CreateTableDef(strTable)
tDef2.Connect = strCOnString
tDef2.SourceTableName = strTable
tDef2.Name = strTable
CurrentDb.TableDefs.Append tDef2
End If
Next
End Sub
If you don't fully understand the second piece of code I posted, I urge you to backup your mdb prior to run it because it will delete objects which can cause serious issues.
Right now I'm downloading data from a database using ADODB to an Excel table. However I want users to be able to refresh the table so it's updated from my database.
I've been experimenting with creating a new table from an external source and arrived to this code:
Public Sub CreateLiveTable(sql As String, Location As Range, TableName As String)
With Location.Parent.ListObjects.Add(SourceType:=xlSrcExternal, Source:="OLEDB; " & DB_CONNECTION, Destination:=Location).QueryTable
.CommandType = xlCmdSql
.CommandText = sql
.BackgroundQuery = True
.ListObject.DisplayName = "asdfas"
.SourceConnectionFile = "C:\Users\lisandro.h.vaccaro\Documents\My Data Sources\172.19.179.43 Forecasting CostRates.odc"
.Refresh BackgroundQuery:=True
End With
End Sub
However I haven't been able to connect my existing table to SQL Server. I can't just delete and create it again as there are a lot of formulas and named ranges pointing to it that would be broken if I deleted it.
How can I connect my existing table to my database?
I'd like to know, how to create a database table in Excel, so that it may be used with ODBC
I want to use ODBC, and I have two options, either MS Access or Excel,
As you probably know, in order to indicate some MS Access file or Excel file as an ODBC source, you need to follow:
Administrative Tools -> Data Sources (ODBC) -> Choose User DSN -> Choose either 'Excel Files' or 'MS Access Database' from the list -> Press 'Configure' -> finally choose the file (MS Access or Excel) as ODBC source
Well, it works fine with MS Access, I can connect to the file and see all tables that I've created inside
But when it comes to Excel, although I can connect to the file, I can't see the table that I've created inside
I just used 'Table' in 'Insert' tab, added some headers as column names, and gave the table
a meaningful name. Is that the way to do it?
There are several ways you can reference "table" data in an Excel workbook:
An entire worksheet.
A named range of cells on a worksheet.
An unnamed range of cells on a worksheet.
They are explained in detail in the "Select Excel Data with Code" section of the Microsoft Knowledge Base article 257819.
The most straightforward way is to keep the data on a separate sheet, put column names in the first row (starting in cell A1), and then have the actual data start in row 2, like this
To test, I created a User DSN named "odbcFromExcel" that pointed to that workbook...
...and then ran the following VBScript to test the connection:
Option Explicit
Dim con, rst, rowCount
Set con = CreateObject("ADODB.Connection")
con.Open "DSN=odbcFromExcel;"
Set rst = CreateObject("ADODB.Recordset")
rst.Open "SELECT * FROM [Sheet1$]", con
rowCount = 0
Do While Not rst.EOF
rowCount = rowCount + 1
If rowCount = 1 Then
Wscript.Echo "Data row 1, rst(""LastName"").Value=""" & rst("LastName").Value & """"
End If
rst.MoveNext
Loop
Wscript.Echo rowCount & " data rows found."
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
The results were
C:\Users\Gord\Documents\__tmp>cscript /nologo excelTest.vbs
Data row 1, rst("LastName").Value="Thompson"
10 data rows found.
I hope that helps your Excel connection issue.
As a final comment I have to say that if you are doing something that takes "several seconds" to do in Excel but "takes around 20-25 min" to do in Access then I strongly suspect that you are using Access in a very inefficient way, but that's a topic for another question (if you care to pursue it).
EDIT
If you want to INSERT data into an Excel workbook then that is possible, but be aware that the default setting for an Excel ODBC connection is "Read Only" so you have to click the "Options>>" button and clear that checkbox:
Once that's done, the following code...
Option Explicit
Dim con
Set con = CreateObject("ADODB.Connection")
con.Open "DSN=odbcFromExcel;"
con.Execute "INSERT INTO [Sheet1$] (ID, LastName, FirstName) VALUES (11, 'Dumpty', 'Humpty')"
con.Close
Set con = Nothing
Wscript.Echo "Done."
...will indeed append a new row in the Excel sheet with the data provided.
However, that still doesn't address the problem of no "Tables" being available for selection when you point your "sniffer" app at an Excel ODBC DSN.
One thing you could try would be to create an Excel sheet with column headings in row 1, then select those entire columns and create an Excel "Defined Name". Then, see if your "sniffer" app recognizes that as a "table" name that you can select.
FWIW, I defined the name myTable as =Sheet1!$A:$C in my Excel workbook, and then my original code sort of worked when I used SELECT * FROM [myTable]:
C:\Users\Gord\Documents\__tmp>cscript /nologo excelTest.vbs
Data row 1, rst("LastName").Value="Thompson"
1048576 data rows found.
As you can see, it retrieved the first "record" correctly, but then it didn't recognize the end of the valid data and continued to read the ~1 million rows in the sheet.
I doubt very much that I will be putting any more effort into this because I agree with the other comments that using Excel as an "ODBC database" is really not a very good idea.
I strongly suggest that you try to find out why your earlier attempts to use Access were so unsatisfactory. As I said before, it sounds to me like something was doing a really bad job at interacting with Access.
I had a similar problem with some data recently. The way I managed to get around it was to select the data as a range A1:XY12345, then use the Define Name tool to name the range. When you connect to the Excel workbook via ODBC, this named range will appear as a "table," while ranges that you actually defined (per Excel) as a table, do not.
You just need to select as many as required columns from first row of your excel file and then give a name to it on the edit box left to the formula bar. Of course you give a name to each column of the file too!
I have a database with a few multi-valued lookup fields. When i split my database, there is a repeated error that the junction table is not found. I know Access makes shadow tables when you use the lookup wizard. How do i link these tables?
I tried the following code:
Sub refresh()
Dim db As Database
Dim rs As Recordset
Set db = CurrentDb
Set rs = db.OpenRecordset("SELECT [Name] FROM [MSysObjects] WHERE ([Type] = 6);", dbOpenSnapshot, dbForwardOnly)
Do While (Not rs.EOF)
db.TableDefs.Delete rs.Fields("Name").Value
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
db.Close
Set db = Nothing
End Sub
but when I ran it it still gave me the same error message, that the hidden junction table "in this case called "TblAudienceTblProg"" was not found.
Is there any way to get around this or do I have to restructure the whole back end to include the actual junction tables?
I think the multivalued datatype is only really useful when the backend is going to be in SharePoint or you do not plan to split a local database.
Basically what a multivalued field type is is a many to many relationship without the hassle of creating a bridge table yourself.
Please click here for more information
We need to find a way to programatically ****link all the tables in a SQL Server database to an access db. We will be invoking this access database from a program that uses .net/SQL Server 2008.
While invoking the application we would like to add the linked tables so that the users can just run the reports/modules from access without having to worry about linking the tables. Is there a way we can do this?
Here are some notes.
Dim sLocalName As String
Dim tdf As TableDef
Dim rs As dao.Recordset
''This is a basic connection string, you may need to consider password and so forth
cn = "ODBC;DSN=TheDSNName;Trusted_Connection=Yes;APP=Microsoft Office 2010;DATABASE=TheDatabaseName;"
''All fields from tables
strSQL = "SELECT TABLE_CATALOG, " _
& "TABLE_SCHEMA, " _
& "TABLE_NAME, " _
& "TABLE_TYPE " _
& "FROM [" & cn & "].INFORMATION_SCHEMA.tables " _
& "WHERE TABLE_TYPE = 'BASE TABLE'"
Set rs = CurrentDb.OpenRecordset(strSQL)
Do While Not rs.EOF
sLocalName = rs!TABLE_SCHEMA & "_" & rs!TABLE_NAME
With CurrentDb
If DLookup("Name", "MSysObjects", "Name='" & sLocalName & "'") <> vbNullString Then
If .TableDefs(sLocalName).Connect <> cn Then
.TableDefs(sLocalName).Connect = cn
.TableDefs(sLocalName).RefreshLink
End If
Else
''If the table does not have a unique index, you will neded to create one
''if you wish to update.
Set tdf = .CreateTableDef(sLocalName)
tdf.Connect = cn
tdf.SourceTableName = rs!TABLE_NAME
.TableDefs.Append tdf
.TableDefs.Refresh
''This will produce a message box if the table does not have a unique index
''DoCmd.TransferDatabase acLink, "ODBC Database", cn, acTable, rs!TABLE_NAME, sLocalName
End If
End With
rs.MoveNext
Loop
You'll need an ODBC connection to the SQL database. Once this connection ready, you can use it for all tables that you want to link:
DoCmd.TransferDatabase acLink, _
"ODBC Database", _
myODBCconnection, _
myDatabaseName, _
acTable, _
myTableName
I guess you can declare your ODBC connector "on the fly", as proposed here for example.
To enumerate your tables, you have the following options:
Enumerate them in the code: one transferDatabase line per table
Save the table names in a local table, and browse the table
Save the table names in a file (text, xml) anywhere on the network and browse the file
Access the system table on the server that holds the table list, and browse the table
Use the ADOX object to browse all tables in your database server: be carefull not to include system tables. This solution might be also quite confusing because you'll have to first open an ADODB connection to your database, and you'll then use an ODBC connection to open the tables
In all cases, this procedure shall be launched with the autoexec macro, meaning that links will be created\updated each time the user opens the mdb client.
You would use ADOX to do the actual linking.
As far as enumerating the tables in a database you are connected to, you could do something as simple as running this query against your SQL Server, but there are a lot of ways to skin that cat:
SELECT * FROM INFORMATION_SCHEMA.TABLES
You can achieve the equivalent by using a Linked Server in SQL Server that points to the Access db. This will give you access to all the tables in the Access db so that you can reference them like:
Select ..
From [LinkedServerName]...[AccessTableName]
Btw, a linked server may be overkill for what you want. Look into the OPENROWSET function which effectively let's you pass a connection string.
EDIT: I originally read the question to literally mean "link tables in SQL Server to access" which I translated to mean from SQL to Access. So, given that, my solution would apply. However, if the desire is to go from Access to SQL, then that is different and other solutions presented would be more appropriate.