How to get data from DBF using VBA in MS Access [duplicate] - ms-access

I have to import .DBF file int MS Access Table On button click.
The file name is SourceTable.dbf ; Access database is StudentDataBase.accdb and the table I want to insert it is named myTable.
First I want to ask: do I need to have the same fields in the table or it can just be a blank table. I have the following sample code:
DoCmd.TransferDatabase transfertype = acImport, databasetype = "dBase III", DatabaseName = "C:/SourceTable.dbf", objecttype = acTable, Source = "SourceTable", destination = "myTable"
Where in the code do I specify the database, where the table is (StudentDataBase)?
And when I run it like that, i get "Run-time error 2507 The 0 type isn't installed database type or doesn't support the operation you chose."
I'm new To Access and VB programming, so please add some guides on how to rewrite that code line.
Thanks!

A quick test suggests that "SourceTable.dbf" is problematic because it does not conform to the old 8.3 file naming convention. I just got Access 2010 to import "C:\Source.dbf" into an Access table named [FromDBF] via VBA using
DoCmd.TransferDatabase _
TransferType:=acImport, _
DatabaseType:="dBASE III", _
DatabaseName:="C:\", _
ObjectType:=acTable, _
Source:="Source", _
Destination:="FromDBF"

Related

VB does not see Table after DoCmd.TransferDatabase using OpenRecordset

I am using Do.CMD.TransferDatabase to copy in two tables from a second access database. The TransferDatabase command runs, and I see the table in the Access list of tables, but the VB code doesn't see it.
I suspect I've messed up the internal list of tables because I see the tables (
myTable
myTable1
myTable2)
If I leave a table there on purpose, Access seems to "see" the table enough to not over-write it and Access writes a copy, but then the same code does not see the existing table to openit.
Code snippets (sanitized):
{
Dim ws As Workspace
Dim myDB As Database
Set myDB = DBEngine.Workspaces(0).Databases(0)
DoCmd.TransferDatabase acImport, "Microsoft Access", filename, acTable,"myTable", "myTable", False
Dim OriginalInformation As Recordset
Set OriginalInformation = myDB.TableDefs("myTable").OpenRecordset
The code stops on the last line and give the error that the item is not found in the collection.
How do I copy in a table and then look at the contents within the same VB function?
The answer is to use myDB.TableDerrs.Refresh between the import and using the
myDB.TableDefs("myTable").OpenRecordset

Error while exporting a access recordset in .xlsx

I want to export record set "myTableRS" from Access 2010 into .xlsx file via VBA, but its showing the error as " The expression you entered is the wrong datatype for one of its argument". If I access any field value from the record set in msgbox using Msgbox(myTableRS![Field3]) so its working fine. Even when i export Access Table so the below code is working fine but not working for myTableRS record set.
I am using the code :
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, _
myTableRS, "D:\MAS.xlsx", True
Can anyone tell how to fix it?
How do I create a saved query? I have a table from which I want to search a particular record and save that particular record only at the same time of search in xlsx
If you look at TransferSpreadsheet, you will see that table name is a string.
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, _
"myTableRS", "D:\MAS.xlsx", True
This means that you cannot export a recordset using TransferSpreadsheet, however, you can create a saved query and export that.
Create a saved query
sSQL = "SELECT * FROM MyTable WHERE Id = " & thenumber
If Not IsNull(DLookup( _
"ExportQuery", "MSysObjects", "[Name]='ExportQuery' AND Type= 5")) Then
''Query exists, overwrite the sql permanently
CurrentDb.QueryDefs("ExportQuery").SQL = sSQL
Else
CurrentDb.CreateQueryDef "ExportQuery", sSQL
End If

Extracting Excel files from Multiple subfolders and load them into sql server table basing on city name

I have a folder which contain's Sub folders(City Names) and in those sub folders I have excel files. I have to take all the excel files from the sub folder and load them into a SQL Server table basing on the city name. The files are structured as below.
Dallas Folder contain's these files
DALLAS_Cars_2011.xls
DALLAS_Trucks_2011.xls
DALLAS_Bikes_2011.xls
My requirement is I have to load the cars data into cars table and Trucks data into Trucks tables, basing on their names and all the city file's should go into same table like cars's, trucks. And I have to create an ID column basing on the city name it can be based on the alphabetical order
can any of the guys help me in this.
First of all I am using SQL Server Express 2008 (R2) and with this I was able to export MS Excel File into my Database. I know at least three ways to do this:
1) Using Import and Export Data (whether 32 bit or 64 bit).
2) Using SQL per se
3) Programmatically like using C# or VB.net
In Import and Export Data just go to your MS SQL Server under All Programs and from there follow the direction. You specify the Data Source as MS Excel and then you Identify your Destination and make sure you Identity to which Database you want to put it.
In Using SQL you could simply use the following command just change accordingly to your own need.
SELECT * FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0','Excel 8.0;HDR=YES;Database=c:\CityName\DALLAS_Cars_2011.xls','select * from [sheet1$]')
However, if you encounter problem like :
OLE DB provider 'Microsoft.Jet.OLEDB.4.0' cannot be used for distributed queries because the provider is configured to run in single-threaded apartment mode.
Try to add this lines:
sp_configure 'show advanced options', 1;
GO
RECONFIGURE;
GO
sp_configure 'Ad Hoc Distributed Queries', 1;
GO
RECONFIGURE;
GO
SELECT * FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0','Excel 8.0;HDR=YES;Database=c:\CityName\DALLAS_Cars_2011.xls','select * from [sheet1$]')
Otherwise if you still encounter problem that probably means that your MS Excel is 32 bit and you are running on 64 bit SQL Server. So, you are better off doing the 1st method.
Finally if you know programming in VB.Net or C# then you could probably code it like this:
Dim cn As ADODB.Connection
Dim strSQL As String
Dim lngRecsAff As Long
Set cn = New ADODB.Connection
cn.Open "Provider=SQLOLEDB;Data Source=<server>;" & _
"Initial Catalog=<database>;User ID=<user>;Password=<password>"
'Import by using OPENDATASOURCE.
strSQL = "SELECT * INTO XLImport6 FROM " & _
"OPENDATASOURCE('Microsoft.Jet.OLEDB.4.0', " & _
"'Data Source=C:\test\xltest.xls;" & _
"Extended Properties=Excel 8.0')...[Customers$]"
cn.Execute strSQL, lngRecsAff, adExecuteNoRecords
See source here
Or you could also use a library from EPPlus like what I did in one of my program.
See its link here.
You can use SSIS to load the excel files into SQL Server.
Create 3 variables: File, City and Table
Create an expression for the City variable to retrieve the City part from File
Do the same for Table
Create a foreach file enumerator
Assign the fully qualified name to the File variable
Create a data flow task that contains an excel source and ole db destination
Create an excel connection which retrieves uses the File variable
Create an ole db connection, assign it to the ole db destination and choose the Table variable as destination table.
Example of expression for city:
If you're File variable contains: C:\temp\Dallas\Dallas_Trucks_2011.xls
SUBSTRING(#[User::File], FINDSTRING(#[User::File], "\\", 3) + 1, FINDSTRING(SUBSTRING(#[User::File], FINDSTRING(#[User::File], "\\", 3) + 1, 99), "_", 1) -1)
The expression should return Dallas. It retrieves the part betweent he third \ and the first _
The following expression returns Trucks by retrieving the part between the first _ and second _
SUBSTRING(#[User::File], FINDSTRING(#[User::File], "_", 1) + 1, FINDSTRING(SUBSTRING(#[User::File], FINDSTRING(#[User::File], "_", 1) + 1, 99), "_", 1) -1)
You can also add a derived column in the data flow task to add the City as a column.
EDIT: I'm actually not 100% sure this will work with a dynamic Excel file and Table definition.

Adding linked table to Access 2003 while keeping ODBC connection info in MDB

I have an Access 2003 database MDB where all of the tables exist as linked tables within SQL Server 2005. The MDB file contains all of the ODBC information that points to the correct SQL Server and log-on credentials (trusted connection).
What I would like to do is add a new linked table to the MDB file however I am not sure how to go about specifying the ODBC connection information. When I try to add a new linked table I keep getting prompted to locate or create a DSN file. I don't want to have to create a new DSN entry on every machine, rather I would like all that information stored within the Access MDB file itself.
In the existing database I can "hover" over the table names and see the ODBC connection info as a tool-tip. All I need to do is add another linked table using the same connection information.
I do have access to the SQL Server where the tables are linked to,. I have already created the new table I wanted to add. I just need to find a way to link to it.
For what it's worth, I'm lazy. I keep a DSN on my development machine, and use it to create new linked tables. I then run Doug Steele's code to convert the links to dsnless connections before distribution of the front end to the end users.
You can use the connection string from an existing table, or you can do something like:
''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;"
There are a few was to connect a table:
sLocalName = "TABLE_SCHEMA" & "_" & "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 = "TABLE_NAME"
.TableDefs.Append tdf
.TableDefs.Refresh
End If
End With
This will produce a message box if the table does not have a unique index
DoCmd.TransferDatabase acLink, "ODBC Database", cn, acTable, "TABLE_NAME", sLocalName
I was able to add the table successfully and wanted to detail the steps here.
I added the new table by clicking "New" within Access and chose "Link Table"
When prompted with the Link file dialog I chose ODBC from the file type list box
I created a new DSN item (only used for initial linking to table)
Proceed with creating DSN and you will follow process of linking to the table created in SQL Server
Table should show up in Access
I then created the following sub routine in the code module. It essentially loops through all your tables in Access that have ODBC connections and sets the proper ODBC connection info into the Table definitions. You can delete the DSN you created previously as it is no longer needed.
Public Sub RefreshODBCLinks()
Dim connString As String
connString = "ODBC;DRIVER=SQL Server Native Client 10.0;" & _
"SERVER=<SQL SERVER NAME>;UID=<USER NAME>;" & _
"Trusted_Connection=Yes;" & _
"APP=<APP NAME>;DATABASE=<DATABASE NAME>"
Dim db As DAO.Database
Dim tb As DAO.TableDef
Set db = CurrentDb
For Each tb In db.TableDefs
If Left(tb.Connect, 4) = "ODBC" Then
tb.Connect = connString
tb.RefreshLink
Debug.Print "Refreshed ODBC table " & tb.Name
End If
Next tb
Set db = Nothing
End Sub
NOTE ... To execute the above SubRoutine I just typed in it's name into the "immediate" windows within the Access code module. You could also create a macro that executes this routine and then whenever you create a new table you could just run the macro.
Thanks to "Remou" for his answer and assistance!
P.S. If you are interested in APP=<APP NAME> in the connection string and what it is for check out this article. http://johnnycoder.com/blog/2006/10/24/take-advantage-of-application-name/

Programatically link SQL Server tables in a new Access 2007 database

I manage an SQL Server 2005 Database and I would like to give read-only access to the necessary tables to a group of 20-30 networked users who are able to use the GUI in MS Access 2007 to write or modify their own queries to the database, with some help.
I would like to distribute an Access database with a single form that would create links to the necessary tables. All of these users are included in a group with read-only permissions to the SQL Server database. I can distribute a dsn file for the connection, but I haven't found a way to programatically create the links to the 50 or so tables they might need, with their network credentials from an otherwise empty Access database.
I found a line of VB code from answer to a similar question onstackoverflow (below), but I was wondering if there was any simpler way than running the modified command once for each of the 50 or so tables.
DoCmd.TransferDatabase acLink, "ODBC Database", "ODBC;DRIVER=Microsoft ODBC for Oracle;SERVER=myserver;UID=myuser;PWD=mypassword", acTable, "SCHEMA.TABLE", "TABLE", False, True
I just wrote an article last week detailing a way to quickly link all tables in an SQL Database to Access. Here are some Access methods that will help. Read the article for more instructions on using it.
You will need to reference the Microsoft ActiveX Data Objects library.
Sub LinkAllTables(Server As String, database As String, OverwriteIfExists As Boolean)
'Usage Example (link all tables in database "SQLDB" on SQL Server Instance SQO01, overwriting any existing linked tables.
'linkalltables "SQL01","SQLDB", true
'This will also update the link if the underlying table definition has been modified.
Dim rsTableList As New ADODB.Recordset
Dim sqlTableList As String
sqlTableList = "SELECT [name] as tablename FROM sysObjects WHERE (type = 'U')"
rsTableList.Open sqlTableList, BuildSQLConnectionString(Server, database)
While Not rsTableList.EOF
If LinkTable(rsTableList("tableName"), Server, database, rsTableList("tableName"), OverwriteIfExists) Then
Debug.Print "Linked: " & rsTableList("tableName")
End If
rsTableList.MoveNext
Wend
rsTableList.Close
Debug.Print "Done."
End Sub
Function LinkTable(LinkedTableAlias As String, Server As String, database As String, SourceTableName As String, OverwriteIfExists As Boolean)
'This method will also update the link if the underlying table definition has been modified.
'The overwrite parameter will cause it to re-map/refresh the link for LinktedTable Alias, but only if it was already a linked table.
' it will not overwrite an existing query or local table with the name specified in LinkedTableAlias.
'Links to a SQL Server table without the need to set up a DSN in the ODBC Console.
Dim dbsCurrent As database
Dim tdfLinked As TableDef
' Open a database to which a linked table can be appended.
Set dbsCurrent = CurrentDb()
'Check for and deal with the scenario ofthe table alias already existing
If TableNameInUse(LinkedTableAlias) Then
If (Not OverwriteIfExists) Then
Debug.Print "Can't use name '" + LinkedTableAlias + "' because it would overwrite existing table."
Exit Function
End If
'delete existing table, but only if it is a linked table
If IsLinkedTable(LinkedTableAlias) Then
dbsCurrent.TableDefs.Delete LinkedTableAlias
dbsCurrent.TableDefs.Refresh
Else
Debug.Print "Can't use name '" + LinkedTableAlias + "' because it would overwrite an existing query or local table."
Exit Function
End If
End If
'Create a linked table
Set tdfLinked = dbsCurrent.CreateTableDef(LinkedTableAlias)
tdfLinked.SourceTableName = SourceTableName
tdfLinked.Connect = "ODBC;DRIVER={SQL Server};SERVER=" & Server & ";DATABASE=" & database & ";TRUSTED_CONNECTION=yes;"
On Error Resume Next
dbsCurrent.TableDefs.Append tdfLinked
If (Err.Number = 3626) Then 'too many indexes on source table for Access
Err.Clear
On Error GoTo 0
If LinkTable(LinkedTableAlias, Server, database, "vw" & SourceTableName, OverwriteIfExists) Then
Debug.Print "Can't link directly to table '" + SourceTableName + "' because it contains too many indexes for Access to handle. Linked to view '" & "vw" & SourceTableName & "' instead."
LinkTable = True
Else
Debug.Print "Can't link table '" + SourceTableName + "' because it contains too many indexes for Access to handle. Create a view named '" & "vw" & SourceTableName & "' that selects all rows/columns from '" & SourceTableName & "' and try again to circumvent this."
LinkTable = False
End If
Exit Function
End If
On Error GoTo 0
tdfLinked.RefreshLink
LinkTable = True
End Function
Function BuildSQLConnectionString(Server As String, DBName As String) As String
BuildSQLConnectionString = "Driver={SQL Server};Server=" & Server & ";Database=" & DBName & ";TRUSTED_CONNECTION=yes;"
End Function
Function TableNameInUse(TableName As String) As Boolean
'check for local tables, linked tables and queries (they all share the same namespace)
TableNameInUse = DCount("*", "MSYSObjects", "(Type = 4 or type=1 or type=5) AND [Name]='" & TableName & "'") > 0
End Function
Function IsLinkedTable(TableName As String) As Boolean
IsLinkedTable = DCount("*", "MSYSObjects", "(Type = 4) AND [Name]='" & TableName & "'") > 0
End Function
In addition to what David proposed, you could have a local (client side) table listing the list of tables available through the SQL connection. You could then write a piece of VBA code that will browse this table to establish all corresponding connections:
Dim rsTable as DAO.recordset
set rsTable = currentDb.openRecordset("Tbl_Tables")
if rsTable.EOF and rsTable.BOF then
else
rsTable.moveFirst
Do while not rsTable.EOF
DoCmd.openDatabase .... 'enumerate here all needed paarmeters with rsTable.fields("tableName") in the string'
rsTable.moveNext
Loop
Endif
rsTable.close
set rsTable = Nothing
This piece of code was written on the fly, so I cannot garantee it will work 'as is'. This code could for example be launched at startup (through the autoexec macro) so that your users will have their links ready when they open their app.
The 'view-only' thing can be easily managed by listing corresponding users (or, if you have a Domain, the corresponding group of users) as 'data readers' on your SQL server.
Is there a special reason why you want to re-create the links every time?
It would be much simpler to create once the mdb with the linked tables, and distribute that mdb to your users.
You might also want to link SQL Server Views (instead of tables) to Access tables, in order to make sure it's read only, maybe pre-join some tables, and eliminate some fields they do not require.
Why not use an Active Data Project in Access?
Linked tables are really only useful if you also need local (unlinked) tables. If you can keep all the tables and views on SQL Server and leave the forms in Access, an ADP will work fine and won't require "linking" any tables manually or via scripting.
In response to Patrick below, if you don't want them mucking around creating queries in your real SQL Server store, create a second SQL Server database that they have rights to create and update queries in, and create VIEWs like the following:
CREATE VIEW mytable AS SELECT * FROM [real database].dbo.mytable
Thus, when you change your master data tables, you only have to make a change to the VIEW in their shared SQL Server database, not a change to each Access database.
Side advantage #1: the users can see each other's queries, thus giving a social aspect of easily sharing good queries.
Side advantage #2: since they are all in one place, you can use SQL Server to detect which user queries will break if you make a change to one of the read-only tables (by searching the view definitions created by Access).
If your SQL Server uses Windows security instead of SQL Server security, then you don't have to supply a username/password in your connect string.
Here's the standard way to do this:
on your development machine, create a DSN for your SQL Server database.
use FILE | GET EXTERNAL DATA | LINK TABLES to link to the tables via ODBC.
get Doug Steele's code to convert to DSN-less connect strings.
then just distribute the front end as is to your users.
The key to this scenario is using Windows security rather than SQL Server security -- Access silently passes the credentials when it requests the connection via ODBC. This is one reason I'd never use SQL Server security -- too much trouble!