Below are some subs and functions to create, delete, and fill tables in a Jet database. I was fiddling with this in order to create a database without using Access, but I ultimately decided to download SQL Server 2005 Express and use it to set up the tables. I’ll still be manipulating the data from Excel, but it’s a lot easier to futz with the fields in a GUI, although I’m struggling to learn SQL Server.
The code to create the table by automating ADOX was provided by motobit.com.
Const Jet10 = 1
Const Jet11 = 2
Const Jet20 = 3
Const Jet3x = 4
Const Jet4x = 5
Sub CreateNewMDB(FileName, Format)
‘From http://www.motobit.com/tips/detpg_createmdb/
Dim Catalog As Object
Set Catalog = CreateObject(“ADOX.Catalog”)
Catalog.Create “Provider=Microsoft.Jet.OLEDB.4.0;” & _
“Jet OLEDB:Engine Type=” & Format & _
“;Data Source=” & FileName
End Sub
Sub MakeJetDB()
‘Create Access2000 database
CreateNewMDB “C:a2000.mdb”, Jet4x
End Sub
Sub CreateTblinDb()
‘creates a table in the database
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sSQL As String
‘create the table with autonumber, primary key OrderID and
‘some other fields
sSQL = “CREATE TABLE Orders (“ & _
“OrderID COUNTER CONSTRAINT PrimaryKey PRIMARY KEY, “ & _
“OrderDate date, “ & _
“CustId char(8), “ & _
“Amount float)”
Set cn = New ADODB.Connection
cn.Open sCON
cn.Execute sSQL
End Sub
Sub DeleteTblinDb()
‘Deletes a table in a database
Dim cn As ADODB.Connection
Dim sSQL As String
‘deletes the table called Orders
sSQL = “DROP TABLE Orders”
Set cn = New ADODB.Connection
‘sCON is a constant with a proper connection string
cn.Open sCON
cn.Execute sSQL
End Sub
Sub PutDataInTable()
‘Puts data from a spreadsheet into a table
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sSQL As String
Dim rRow As Range
Dim rRng As Range
Dim i As Long
Set rRng = Sheet2.Range(“b2:d4”)
Set cn = New ADODB.Connection
cn.Open sCON
‘Loops through the rows and builds a SQL statement via a function
For Each rRow In rRng.Rows
sSQL = MakeInsertInto(“Orders”, rRow, False, Sheet2.Range(“b1:d1”))
If Len(sSQL) > 0 Then
cn.Execute sSQL
End If
Next rRow
cn.Close
Set cn = Nothing
End Sub
Function MakeInsertInto(ByVal sTable As String, _
ByRef rRecord As Range, _
Optional ByVal bAutoIncrement As Boolean = True, _
Optional ByRef rHeader As Range) As String
‘Builds a string that’s a SQL statement to insert records into a table
‘sTable is the name of the table
‘rRecord is the range that contains all the value, one per field
‘bAutoIncrement is true if the first field is an autonumber
‘rHeader is range that contains the field names – to be used when
‘ you’re not inserting all the fields and you need to identify
‘ which values are for which fields
Dim rCell As Range
Dim sSQL As String
sSQL = sSQL & “INSERT INTO “ & sTable & ” “
‘Add the fields portion of the sql statement if rHeader was supplied
If Not rHeader Is Nothing Then
‘compare cell count of record with header. If autoincrement, header should be
‘one greater than record
If rRecord.Cells.Count <> rHeader.Cells.Count + CLng(bAutoIncrement) Then
MakeInsertInto = “”
Exit Function
End If
‘add column names
sSQL = sSQL & “(“
For Each rCell In rHeader.Cells
sSQL = sSQL & rCell.Value & “, “
Next rCell
sSQL = Left$(sSQL, Len(sSQL) – 2) & “) “
End If
sSQL = sSQL & “VALUES (“
‘If the first field is an autonumber, make the value default
If bAutoIncrement Then
sSQL = sSQL & “DEFAULT, “
End If
‘Loop through the record and add the values to the sql statement
For Each rCell In rRecord.Cells
If rCell.NumberFormat = “@” Then ‘force a number to be text
sSQL = sSQL & “‘” & CleanField(rCell.Value) & “‘, “
ElseIf IsEmpty(rCell.Value) Or Not IsNumeric(rCell.Value) Then
sSQL = sSQL & “‘” & CleanField(rCell.Value) & “‘, “
Else
sSQL = sSQL & rCell.Value & “, “
End If
Next rCell
‘get rid of the last comma-space sequence and close the paren
sSQL = Left$(sSQL, Len(sSQL) – 2)
sSQL = sSQL & “);”
MakeInsertInto = sSQL
End Function
Function CleanField(sValue As String) As String
Dim sTemp As String
‘double up quotes and underscores
sTemp = Replace$(sValue, “‘”, “””)
sTemp = Replace$(sTemp, “_”, “__”)
CleanField = sTemp
End Function
Const Jet11 = 2
Const Jet20 = 3
Const Jet3x = 4
Const Jet4x = 5
Sub CreateNewMDB(FileName, Format)
‘From http://www.motobit.com/tips/detpg_createmdb/
Dim Catalog As Object
Set Catalog = CreateObject(“ADOX.Catalog”)
Catalog.Create “Provider=Microsoft.Jet.OLEDB.4.0;” & _
“Jet OLEDB:Engine Type=” & Format & _
“;Data Source=” & FileName
End Sub
Sub MakeJetDB()
‘Create Access2000 database
CreateNewMDB “C:a2000.mdb”, Jet4x
End Sub
Sub CreateTblinDb()
‘creates a table in the database
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sSQL As String
‘create the table with autonumber, primary key OrderID and
‘some other fields
sSQL = “CREATE TABLE Orders (“ & _
“OrderID COUNTER CONSTRAINT PrimaryKey PRIMARY KEY, “ & _
“OrderDate date, “ & _
“CustId char(8), “ & _
“Amount float)”
Set cn = New ADODB.Connection
cn.Open sCON
cn.Execute sSQL
End Sub
Sub DeleteTblinDb()
‘Deletes a table in a database
Dim cn As ADODB.Connection
Dim sSQL As String
‘deletes the table called Orders
sSQL = “DROP TABLE Orders”
Set cn = New ADODB.Connection
‘sCON is a constant with a proper connection string
cn.Open sCON
cn.Execute sSQL
End Sub
Sub PutDataInTable()
‘Puts data from a spreadsheet into a table
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim sSQL As String
Dim rRow As Range
Dim rRng As Range
Dim i As Long
Set rRng = Sheet2.Range(“b2:d4”)
Set cn = New ADODB.Connection
cn.Open sCON
‘Loops through the rows and builds a SQL statement via a function
For Each rRow In rRng.Rows
sSQL = MakeInsertInto(“Orders”, rRow, False, Sheet2.Range(“b1:d1”))
If Len(sSQL) > 0 Then
cn.Execute sSQL
End If
Next rRow
cn.Close
Set cn = Nothing
End Sub
Function MakeInsertInto(ByVal sTable As String, _
ByRef rRecord As Range, _
Optional ByVal bAutoIncrement As Boolean = True, _
Optional ByRef rHeader As Range) As String
‘Builds a string that’s a SQL statement to insert records into a table
‘sTable is the name of the table
‘rRecord is the range that contains all the value, one per field
‘bAutoIncrement is true if the first field is an autonumber
‘rHeader is range that contains the field names – to be used when
‘ you’re not inserting all the fields and you need to identify
‘ which values are for which fields
Dim rCell As Range
Dim sSQL As String
sSQL = sSQL & “INSERT INTO “ & sTable & ” “
‘Add the fields portion of the sql statement if rHeader was supplied
If Not rHeader Is Nothing Then
‘compare cell count of record with header. If autoincrement, header should be
‘one greater than record
If rRecord.Cells.Count <> rHeader.Cells.Count + CLng(bAutoIncrement) Then
MakeInsertInto = “”
Exit Function
End If
‘add column names
sSQL = sSQL & “(“
For Each rCell In rHeader.Cells
sSQL = sSQL & rCell.Value & “, “
Next rCell
sSQL = Left$(sSQL, Len(sSQL) – 2) & “) “
End If
sSQL = sSQL & “VALUES (“
‘If the first field is an autonumber, make the value default
If bAutoIncrement Then
sSQL = sSQL & “DEFAULT, “
End If
‘Loop through the record and add the values to the sql statement
For Each rCell In rRecord.Cells
If rCell.NumberFormat = “@” Then ‘force a number to be text
sSQL = sSQL & “‘” & CleanField(rCell.Value) & “‘, “
ElseIf IsEmpty(rCell.Value) Or Not IsNumeric(rCell.Value) Then
sSQL = sSQL & “‘” & CleanField(rCell.Value) & “‘, “
Else
sSQL = sSQL & rCell.Value & “, “
End If
Next rCell
‘get rid of the last comma-space sequence and close the paren
sSQL = Left$(sSQL, Len(sSQL) – 2)
sSQL = sSQL & “);”
MakeInsertInto = sSQL
End Function
Function CleanField(sValue As String) As String
Dim sTemp As String
‘double up quotes and underscores
sTemp = Replace$(sValue, “‘”, “””)
sTemp = Replace$(sTemp, “_”, “__”)
CleanField = sTemp
End Function
Hi Dick,
Maybe the reason you were experimenting with this topic was the same as…
While spending way too much time on the code to deal with duplicates in multiple arrays, the one nagging thought I couldn’t escape was that the entire process was a major waste of time — other than being an interesting intellectual exercise.
The easiest way to eliminate dups on a large scale would be to create a new table in a new db with just one field designated as ‘no duplicates’. Now, just add all the data in all the different arrays into this table, skip errors and you have the necessary solution. Very scalable in that it would work not only with in-memory arrays but also files!
To put data back into the original sources, one would need a 2nd column in the table indicating the original source.
It wouldn’t have the rebalance capability in the code I posted to the NG but it would be much more scalable — and easier to write. {grin}
Hey Dick,
I have been fiddling with something similar. Now I’m not as good at this stuff as the rest of you, but I think this might help. The whole making a SQL statement to do an INSERT INTO the Access table doesn’t seem to be the fastest/cleanest method. I recently changed how I getting the data from Excel into Access.
I don’t know how to use ADO (yet) so I have DAO in my code but this is the short of it here. What I’ve done is CREATED the table which I know the field types I want and the total number of fields. Let me know what you think and if you need more info.
Set rs = db.OpenRecordset(“tblDMLifeCycle”)
Do
‘Insert data into the table
intCount = 1
‘Load Array with values from Excel
For i = 0 To 37
varExcelInfo(i) = Application.Cells(intRcount, intCount)
intCount = intCount + 1
Next
rs.AddNew
‘Take values from Excel Array and plug into Access table.
For i = 0 To 37
rs.Fields(i) = varExcelInfo(i)
Next
rs.Update
‘Move down Excel workbook.
intRcount = intRcount + 1
Erase varExcelInfo()
Loop Until intRcount > End_Row