Copy a ODBC-linked SQL-Table to an Access table with VBA - sql-server

I have some ODBC-linked SQL-Server tables in my Access DB, which are the production environment. For testing I want to copy all the data from the SQL-Server into structure-identical Access tables so that I have an identical set of tables in a dev or test-environment. To make it difficult: All of these tables have autoincrement IDs and I want the copies to have the same values and of course the copied ID field also as autoincrement long.
So, a set of these tables:
- dbo_tbl_Abcd
- dbo_tbl_Efgh etc.
should be copied to:
- Dev_Abcd
- Dev_Efgh etc.
or to:
- Test_Abcd
- Test_Efgh etc.
When I do a manual copy and paste for each single table this will work without problems. A dialog "Paste Table As" appears where you have the options:
Linked Table
Structure Only
Structure and Data
Append Data to Existing Table
When you set the name correctly and choose Structure and Data, you will have a proper copy as Access table with the same values in the Auto-ID field. I just want to do this by code and for all ODBC-Tables at once (in a loop). When Access provides this manual copying, there must be a way to do this by code.
I have already tried this:
DoCmd.CopyObject , "Dev_Abcd", acTable, "dbo_tbl_Abcd"
but this only will create more ODBC-links to the same SQL-Server tables.
I also tried this:
DoCmd.TransferDatabase acExport, "Microsoft Access", CurrentDb.Name, acTable, "dbo_tbl_Abcd", "Dev_Abcd"
This led to the following error:
The Microsoft Access database engine could not find the object . Make sure the object exists and that you spell its name and the path name correctly. (Error 3011)
I experimented a lot with DoCmd.TransferDatabase, but cound't find a working setting.
I did not test any "SELECT INTO"-Statements because of the autoincrement field.

What you are asking can be done like
CurrentDb.Execute "select * into localTable from dbo_serverTable" , dbFailOnError
And to do this to all the tables use this sub
Sub importSrverTables()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Set db = CurrentDb
For Each tdf In db.TableDefs
If Left(LCase(tdf.Name), 4) = "dbo_" Then
'CurrentDb.Execute "select * into localTable from dbo_serverTable", dbFailOnError
db.Execute "select * into " & Mid(tdf.Name, 5) & " from " & tdf.Name, dbFailOnError
' the next if is to make the loop wait until the transfer finish.
If db.RecordsAffected > 0 Then
' do nothing
End If
End If
Next
Set tdf = Nothing
Set db = Nothing
End Sub

I've done something similiar. Change the ConnectionString to your environment. Maybe you have to extend the TranslateDatatype function.
Function TranslateDatatype(value As Long) As String
Select Case value
Case 2: TranslateDatatype = "INT" ' adSmallInt
Case 3: TranslateDatatype = "LONG" ' adInteger
Case 200: TranslateDatatype = "STRING" ' adVarChar
Case 202: TranslateDatatype = "STRING" ' adVarWChar
Case 17: TranslateDatatype = "BYTE" ' adUnsignedTinyInt
Case 11: TranslateDatatype = "BIT" ' adBoolean
Case 129: TranslateDatatype = "STRING" ' adChar
Case 135: TranslateDatatype = "DATE" ' adDBTimeStamp
Case Else: Err.Raise "You have to extend TranslateDatatype with value " & value
End Select
End Function
Sub CopyFromSQLServer()
Dim SQLDB As Object, rs As Object, sql As String, i As Integer, tdf As TableDef
Dim ConnectionString As String
Set SQLDB = CreateObject("ADODB.Connection")
ConnectionString = "Driver={SQL Server Native Client 11.0};Server=YourSQLServer;Database=YourDatabase;trustedConnection=yes"
SQLDB.Open ConnectionString
Set rs = CreateObject("ADODB.Recordset")
Set rs.ActiveConnection = SQLDB
For Each tdf In CurrentDb.TableDefs
rs.Source = "[" & tdf.Name & "]"
rs.Open
sql = "("
i = 0
Do
sql = sql & "[" & rs(i).Name & "] " & TranslateDatatype(rs(i).Type) & ", "
i = i + 1
Loop Until i = rs.Fields.Count
rs.Close
sql = "CREATE TABLE [Dev_" & tdf.Name & "] " & Left(sql, Len(sql) - 2) & ")"
CurrentDb.Execute sql, dbFailOnError
sql = "INSERT INTO [Dev_" & tdf.Name & "] SELECT * FROM [" & tdf.Name & "]"
CurrentDb.Execute sql, dbFailOnError
Next
End Sub

Related

Select data from mssql using excel vba and where statement

I need select data from database, using Excel. I want to select only one column from database and I need use where statement (to select only data which have the same unique value as data in Excel sheet)
I tried this
Sub DB_RTVresult()
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim myRes As ADODB.Recordset
Server_Name = "123" ' Enter your server name here
Database_Name = "DBName" ' Enter your database name here
User_ID = "UserName" ' enter your user ID here
Password = "Pass" ' Enter your password here
Set myCon = New ADODB.Connection
Worksheets(2).Select
LastRow = GetRowCnt
For bl = LastRow To 5 Step -1
myCon.ConnectionString = "Driver={SQL Server};Server=" & Server_Name & _
";Uid=" & User_ID & ";Pwd=" & Password & ";Database=" & Database_Name & ";"
myCon.Open
SQLStr = "SELECT [RTV_RESULT]" & _
"FROM [WSCZWMS].[WSCZWMS].[OMEGA_E2E_REPORT] WHERE [SME_TRACK_NO] ='" & Cells(bl, "CC").Value & "'"
Set myRes = myCon.Execute(SQLStr)
Worksheets("HelpTables").Range("E2" & Rows.Count).End(xlUp).Offset (1)
StrQuery = "OMEGA_SPEQ_REPORT"
myCon.Close
Set myRes = Nothing
Set myCon = Nothing
Next
End Sub
But when I run it, it writes Application-define or object-define error.
and colored this line
Worksheets("HelpTables").Range("E2" & Rows.Count).End(xlUp).Offset(1).CopyFromRecordset myRes
This line dave the select data into first empty row in column E, (start on 3rd row)
Do you have any idea how to solve this?
The reason for your issue is, that you are already referring to the Row in your .Range("E2" & Rows.Count) .
If you modify the mentioned line to the following, it should work properly:
Worksheets("HelpTables").Cells(Rows.Count, 5).End(xlUp).Offset(1).CopyFromRecordset myRes
The 5 in .Cells(Rows.Count, 5) is for the fifth column ('E').
I am not sure, but it seems that your excel objects Cells dans Rows should be affected and your sheets selected.
I would have writen
For b1=...
Worksheets(2).select
...
... Worksheets(2).cells(b1,"CC").value
...
Worksheets("HelpTables").select
Worksheets("HelpTables").Range("E" & _
Worksheets("HelpTables").Range("E:E").Rows.Count).End(xlUp).Offset(1) ...
...
NB :
"CC" is the name of a Excel value ?
Do you want Range("E2" & rows.count) to go to E2100 if there are 100 rows ? That's why I wrote "E" and not "E2" in my proposition. But may be you wanted (... rows.count+2) ?
Hope it helps.
Pierre.

Reading over 254 columns from an Excel 2010 file using ACE SQL server

I am using the connection string
szConnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & fpath & fname & ";" & _
"Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1;"";"
Set rsData = New ADODB.Recordset
'Run the query as adCmdText
rsData.Open szSQL, szConnect, adOpenForwardOnly, adLockReadOnly, adCmdText
'Check if data exists for query
If Not rsData.EOF Then
rtnArr = rsData.GetRows 'if the recordset contains data populate the array
Else
dEmp = True 'no data flag true
ReDim rtnArr(0 To 0, 0 To 0)
End If
to run SQL queries in VBA from an external Excel 2010 file. The file has over 40 sheets and each sheet is approx. 369 columns wide, currently the SQL is only returning the first 255 columns of data as per the SQL server limitations. A number of forums discussing this problem suggest transforming the workbook into a flat (.csv) however this wouldn't be ideal. Does anyone have an alterative solution to this? Or a way of forcing through the extra columns?
Thanks!
ADO has a limit of 255 fields when connecting to Excel. (see here for limitations - ACE/JET/Access are intricately linked)
Your best bet would be to try opening the excel file as an excel file, and reading the cells to create an insert statement
Dim xlApp As Object
Dim OWorkbook As Object
Set xlApp = CreateObject("Excel.Application")
Set OWorkbook = xlApp.workbooks.Open("MyFile.xlsx")
With OWorkbook.Worksheets(1)
c1 = .Cells(RowCount, 1).value
...
c290 = .Cells(RowCount, 290).value
Then construct the Insert
strInsertSQL = "INSERT INTO [MyDB].[dbo].[MyTable] ([Val1],[Val2],...,[Val290])"
strSQLValues = " VALUES (" & c1 & ", '" & c2 & "'," & ... & c290 & ")"
cmd.ActiveConnection = "Provider=SQLNCLI11;Server=MyServer;Database=MyDB"
cmd.CommandText = strInsertSQL & strSQLValues
cmd.CommandTimeout = 0
cmd.Execute 'strInsertSQL & strSQLValues
Increment RowCount as needed

Why does this vba table relink code result in error 3219?

I'm trying to relink tables in an MS Access database separate from the one the code below runs in; this way I can use the repairing db as "patch" of sorts...
I've modified the code I found here, so that it relinks the tables in a database opened by the "repairing / patch database"
Before I run the code I make sure both databases are open so that one can repair the other to make it easier to automate the application of the fix.
However when I run the code, when I get to the line reads tdfLinked.RefeshLink, which refreshes the linked table, I get an Runtime error '3219' Invalid Operation error.
Sub FixDB()
Call LinkTable("somelinkedTble", "SOMESERVER\NAMED_SQL_INST32", "Database1", "Some_Schema.somelinkedTble", True)
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.
' Begin: Bit that I modified to access the database that needs fixed.
Dim objAccess As Access.application
Dim loginInfo As New AuthInfoz
loginInfo.workgroup = "E:\Tickets\Fix\SEC\Secured.mdw"
loginInfo.username = "someuser"
loginInfo.password = "********"
loginInfo.dbs = "E:\Tickets\Fix\Report.mdb"
Set objAccess = GetObject(loginInfo.dbs).application
'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 = objAccess.CurrentDb
' END: Bit that I modified to access the external database.
'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
Here's a proven example you should be able to adopt:
Public Function AttachSqlServer( _
ByVal Hostname As String, _
ByVal Database As String, _
ByVal Username As String, _
ByVal Password As String) _
As Boolean
' Attach all tables linked via ODBC to SQL Server or Azure SQL.
' 2016-04-24. Cactus Data ApS, CPH.
Const cstrQuery1 As String = "_Template"
Const cstrQuery2 As String = "_TemplateRead"
Const cstrQuery3 As String = "VerifyConnection"
Const cstrDbType As String = "ODBC"
Const cstrAcPrefix As String = "dbo_"
Dim dbs As DAO.Database
Dim tdf As DAO.TableDef
Dim strConnect As String
Dim strName As String
On Error GoTo Err_AttachSqlServer
Set dbs = CurrentDb
strConnect = ConnectionString(Hostname, Database, Username, Password)
For Each tdf In dbs.TableDefs
strName = tdf.Name
If Asc(strName) <> Asc("~") Then
If InStr(tdf.Connect, cstrDbType) = 1 Then
If Left(strName, Len(cstrAcPrefix)) = cstrAcPrefix Then
tdf.Name = Mid(strName, Len(cstrAcPrefix) + 1)
End If
tdf.Connect = strConnect
tdf.RefreshLink
Debug.Print Timer, tdf.Name, tdf.SourceTableName, tdf.Connect
DoEvents
End If
End If
Next
dbs.QueryDefs(cstrQuery1).Connect = strConnect
dbs.QueryDefs(cstrQuery2).Connect = strConnect
dbs.QueryDefs(cstrQuery3).Connect = strConnect
Debug.Print "Done!"
AttachSqlServer = True
Exit_AttachSqlServer:
Set tdf = Nothing
Set dbs = Nothing
Exit Function
Err_AttachSqlServer:
Call ErrorMox
Resume Exit_AttachSqlServer
End Function

Deleting Records in SQL server table prior to insert

I have a excel workbook that is a project plan template, that the PM fills in information and it gets loaded into a sql database. Currently the process if via a batch process that loads two tables(1 with 1 row of data and the other with multiple records). I am changing it to be a direct insert from excel into sql server via vba. I have the insert working but each table has a project id column which is the PK. The pm may update and save this file multiple times. The tables get updated with the most recent save information. I have solved this by adding a delete statement into my code and then inserting the updated record. This works great for the table with 1 record but I can't get the table with multiple records to work. It deletes the records and goes through the first loop of the insert but then goes back to the delete and removes the records.
I have attached the code for the multiple table delete and insert. Can someone tell me what I am doing wrong?
Public Sub exportprojdetaildata()
Dim stSQL As String
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim iRowNo As Integer
Dim targetedFieldNames As Variant
Dim rowData As Variant
Dim lastrow As Long
Dim sql As String
Dim i As Integer
Dim cvt As Double
Dim aField As String
Dim compare As Variant
Dim value As Variant
Dim dvalue As Long
With Sheets("Data")
lastrow = .Range("A:A").Find(what:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByRows).Row
'Open a connection to SQL Server
conn.Open _
"Provider=SQLOLEDB;Data Source=PWIRTPAUDD1HV8;Initial Catalog=STAR;User Id=STAR_USER;Password=dcistarrtp"
'Skip the header row
iRowNo = 2
targetedFieldNames = Join(WorksheetFunction.Transpose(wks_TargetFieldNames.Range("targetedFieldNames").value), "," & vbNewLine)
Do While iRowNo <= lastrow
rowData = wks_BackgroundData.Range("A" & iRowNo & ":AV" & iRowNo).value
compare = wks_BackgroundData.Range("AV2").value
'Generate and execute sql statement to import the excel rows to SQL Server table
With rs
.ActiveConnection = conn
.Open "Select proj_id from dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy where proj_id = " & compare
wks_BackgroundData.Range("BA2").CopyFromRecordset rs
.Close
End With
value = wks_BackgroundData.Range("BA2").value
If compare = value Then
sql = "delete from dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy where proj_id = " & value
conn.Execute sql
Else
sql = "insert into dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy ("
sql = sql & targetedFieldNames
' Debug.Print sql
sql = sql & ") values (" & vbNewLine
' Debug.Print sql
'couldn't do transpose since rowData represents a row, not a column
For i = 1 To UBound(rowData, 2)
aField = Replace(rowData(1, i), "'", "''")
'escape single quotes
Select Case i
Case 1, 6, 16, 17, 23 To 47
' cvt = CDbl(aField)
If aField = vbNullString Then
sql = sql & "Null," & vbNewLine
Else
sql = sql & aField & "," & vbNewLine
End If
Case 2 To 5, 7 To 15, 18 To 22
sql = sql & "'" & aField & "', " & vbNewLine
Case 48
If aField = vbNullString Then
sql = sql & "Null"
Else
sql = sql & aField
End If
End Select
Next i
sql = sql & ");"
'sql = sql & "');"
' End If
conn.Execute sql
iRowNo = iRowNo + 1
Loop
End If
conn.Close
Set conn = Nothing
End With
End Sub
It's difficult to be sure without seeing the data that you're trying to save, but I suspect you have a logic error.
The value for rowData is built up dynamically in a loop. which is correct.
rowData = wks_BackgroundData.Range("A" & iRowNo & ":AV" & iRowNo).value
but the values for compare and value are always read from the same location inside the loop. So the delete statement will be executed over and over again.
compare = wks_BackgroundData.Range("AV2").value
value = wks_BackgroundData.Range("BA2").value
Should compare and value not also be read dynamically?
compare = wks_BackgroundData.Range("AV" & iRowNo).value
value = wks_BackgroundData.Range("BA" & iRowNo).value
Or
you should move the delete statement outside of the loop, to ensure that it's only executed once
Or
you should keep a flag that will indicate that the delete has already been executed, and not execute it again.
hasExecuted = false <- OUTSIDE THE LOOP
...
...
If compare = value and hasExecuted = false Then
sql = "delete from dbo.STAR_DC_INITIAL_ProjectDetails_ExcelDevCopy where proj_id = " & value
conn.Execute sql
hasExecuted = true
...
...
Also, I don't think you should have a IF x=y THEN delete ELSE INSERT. Should it not be IF x=y THEN delete, and always INSERT. With the else, it will only insert if the record didn't exist, but if it deleted the record, it will never insert the new one.
Hope that helps a bit
Avoid using VBA for new development work. If you need to constantly take this Excel document and insert it into a SQL Server database, then use SSIS and some C# to easily make it a scheduled task via the SQL Agent, or simply do as the screen shot below suggests, which is a no-code and easily configurable import of flat files / database tables into SQL Server. Lastly, from a usability standpoint, There are many better methods to track Excel sheets or forms data (SharePoint, Excel 2013, Access, cloud/on premise drives) or using an internal WordPress distribution with some plugins like WP-document revisions.
As noted above I used Spock addition of dynamic lookup of values for the compare and value variable. Once I did that I added the hasExecuted flag.
Public Sub exportprojinfodata()
Dim stSQL As String
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim strConn As String
Dim iRowNo As Integer
Dim targetFieldNames As Variant
Dim rowData As Variant
Dim lastrow As Long
Dim sql As String
Dim i As Integer
Dim aField As String
Dim compare As Variant
Dim value As Variant
Dim hasExecuted As String
hasExecuted = False
With Sheets("Data2")
lastrow = .Range("A:A").Find(what:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByRows).Row
'Open a connection to SQL Server
conn.Open _
"Provider=SQLOLEDB;Data Source=PWIRTPAUDD1HV8;Initial Catalog=STAR;User Id=STAR_USER;Password=dcistarrtp"
'Skip the header row
iRowNo = 2
targetFieldNames = Join(WorksheetFunction.Transpose(wks_TargetFieldNames.Range("TargetFieldNames").value), "," & vbNewLine)
Do While iRowNo <= lastrow
rowData = wks_ProjDescription.Range("A" & iRowNo & ":AO" & iRowNo).value
compare = wks_ProjDescription.Range("B"& iRowNo).value
'Generate and execute sql statement to import the excel rows to SQL Server table
With rs
.ActiveConnection = conn
.Open "Select proj_id from dbo.STAR_DC_INITIAL_ProjectInfo_ExcelDevCopy where proj_id= " & compare
wks_ProjDescription.Range("AX2").CopyFromRecordset rs
.Close
End With
value = wks_ProjDescription.Range("AX"& iRowNo).value
If compare = value And hasExecuted = False Then
stSQL = "delete from dbo.STAR_DC_INITIAL_ProjectInfo_ExcelDevCopy where proj_id = " & value
conn.Execute stSQL
hasExecuted = True
End If
sql = "insert into dbo.STAR_DC_INITIAL_ProjectInfo_ExcelDevCopy ("
sql = sql & targetFieldNames
sql = sql & ") values (" & vbNewLine
'
'couldn't do transpose since rowData represents a row, not a column
For i = 1 To UBound(rowData, 2)
aField = Replace(rowData(1, i), "'", "''")
Select Case i
Case 1 To 40
sql = sql & "'" & aField & "', " & vbNewLine
Case 41
If aField Like "*,*" Then
sql = sql & "'" & """" & aField & """" & vbNewLine
Else
sql = sql & "'" & aField & "' " & vbNewLine
End If
End Select
Next i
sql = sql & ");"
' sql = sql & "');"
conn.Execute sql
iRowNo = iRowNo + 1
Loop
conn.Close
Set conn = Nothing
End With
End Sub

VBA: Robust Database creation

i find this code, when trying to create db, using adodb and adox.
Here you can check original, it is the same. Thanks for author
Private Sub Command1_Click()
Dim db_file As String
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim num_records As Integer
' Get the database name.
db_file = App.Path
If Right$(db_file, 1) <> "\" Then db_file = db_file & _
"\"
db_file = db_file & "People.mdb"
' Open a connection.
Set conn = New ADODB.Connection
conn.ConnectionString = _
"Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & db_file & ";" & _
"Persist Security Info=False"
conn.Open
' Drop the Employees table if it already exists.
On Error Resume Next
conn.Execute "DROP TABLE Employees"
On Error GoTo 0
' Create the Employees table.
conn.Execute _
"CREATE TABLE Employees(" & _
"EmployeeId INTEGER NOT NULL," & _
"LastName VARCHAR(40) NOT NULL," & _
"FirstName VARCHAR(40) NOT NULL)"
' Populate the table.
conn.Execute "INSERT INTO Employees VALUES (1, " & _
"'Anderson', 'Amy')"
conn.Execute "INSERT INTO Employees VALUES (1, 'Baker', " & _
" 'Betty')"
conn.Execute "INSERT INTO Employees VALUES (1, 'Cover', " & _
" 'Chauncey')"
' Add more records ...
' See how many records the table contains.
Set rs = conn.Execute("SELECT COUNT (*) FROM Employees")
num_records = rs.Fields(0)
conn.Close
MsgBox "Created " & num_records & " records", _
vbInformation, "Done"
End Sub
But how to make it more robust, so, i don't want to delete db.
How to check, if db exists and if db.tables contains my table?
additional question: am i right, that this code create db for ms-access 2007?
Thanks for help!
Your question includes these two:
How to check, if db exists and if db.tables contains my table?
am i right, that this code create db for ms-access 2007?
For the first part of #1, use the Dir() function.
If Len(Dir("C:\SomeFolder\YourDb.mdb")) > 0 Then
Debug.Print "db exists"
Else
Debug.Print "db not found"
End If
For the second part of #1, try this function. pTable is the name of the table you're checking for. pDbPath is the full path, including the file name, for the db file you want to examine. The path can be one which begins with a drive letter, or it can be a UNC path ( \\Server\Share\YourDb.mdb ).
Public Function TableExists(ByVal pTable As String, _
Optional ByVal pDbPath As String) As Boolean
'return True if pTable exists as either a native or linked table '
'pass any error to caller '
Dim blnReturn As Boolean
Dim db As DAO.Database
Dim tdf As DAO.TableDef
If Len(Trim(pDbPath)) > 0 Then
Set db = OpenDatabase(pDbPath)
Else
Set db = CurrentDb
End If
For Each tdf In db.TableDefs
If tdf.Name = pTable Then
blnReturn = True
Exit For
End If
Next tdf
Set tdf = Nothing
If Len(Trim(pDbPath)) > 0 Then
db.Close
End If
Set db = Nothing
TableExists = blnReturn
End Function
Regarding your second question, no that code you showed us does not create a db file for any Access version. If db_file is not the path to an existing db file, that code will throw an error at conn.Open. It does not create the missing db file.
However I doubt that code will compile as VBA, despite the fact you included VBA in your title and tagged your question as vba. Really you should have at least tried it first before including it in a question on Stack Overflow.
For creating a MDB file from VB6/VBA code you could use ADOX. Here's a sample function to create an MDB file.
Public Function CreateMDB(strDBPath As String) As Boolean
'To make code compile add a reference to Microsoft ADO Ext 2.x for DDL and Security
'(msADOX.dll)
Dim catDB As ADOX.Catalog
Dim tblNew As ADOX.Table
Dim keyPrim As New ADOX.Key
Set catDB = New ADOX.Catalog
If Dir(strDBPath) = "" Then
CreateMDB = False
End If
With catDB
.Create "Provider=Microsoft.Jet.OLEDB.4.0;Locale Identifier=" & _
1033 & ";Data Source=" & strDBPath
.ActiveConnection = "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strDBPath
End With
Set tblNew = New ADOX.Table
With tblNew
.Name = "data"
With .Columns
.Append "Field_0", adVarWChar
.Append "Field_1", adVarWChar
.Append "Field_2", adVarWChar
.Append "Field_3", adVarWChar
End With
End With
catDB.Tables.Append tblNew
Set keyPrim = New ADOX.Key
With keyPrim
.Name = "Field_0"
.Type = adKeyPrimary
.RelatedTable = "data"
.Columns.Append "Field_0"
End With
catDB.Tables("data").Keys.Append keyPrim
Set catDB = Nothing
Set tblNew = Nothing
End Function

Resources