To use the ADOX
Library for the following ADOX examples,
you need to set reference to Microsoft ADO Ext.2.7 or 2.8 for DDL and
Security library. In the code window, go to
Tools/Reference and check the box
[see
diagram].
'To make a table,
make new ADOX.Table object. Use its Columns collection's Append method
to define fields. When it is done, use the Catalog's Tables collection's
Append method to add the Table.
Option Compare Database
Option Explicit
' Purpose: To add table, columns
and records to a
database using ADOX Sub CreateTable()
Dim cat As New ADOX.Catalog
Dim tbl As New ADOX.Table
Dim col As New ADOX.Column
' connect the catalog to the current database cat.ActiveConnection = CurrentProject.Connection
With col
Set .ParentCatalog = cat
' associate with the
provider in order you can set provider-specific properties .Name = "SN"
' define the first
column 'SN' .Type = adInteger
' equivalent of the VB Long
data type .Properties("Autoincrement") = True
' automatically generate
unique identifier, auto-incrementing .Properties("Description") = "unique serial numbers" End With
With tbl
.Name = "MyTable" ' create a table 'MyTable' .Columns.Append col
' create column 'SN' to the
Columns collection of the table .Columns.Append "Part_Number", adVarWChar, 12
' create 2nd column 'Part_Number',
Text (12 max) .Columns.Append "Part_Description", adVarWChar, 30
' create 3rd column
'Description', Text (30 max) .Columns.Append "Std_Cost", adSingle '
create the 4th column 'Std_Cost',
data type Single .Columns.Append "Released_Date", adDate
' create the 5th column "Released_Date",
data type Date .Columns.Append "Quantity",
adSmallInt ' create the 6th
column "Quantity" as Integer .Keys.Append "PrimaryKey", adKeyPrimary, "SN"
' append column 'SN' as
primary key to the Keys collection
End With
cat.Tables.Append tbl
' save the table by
appending to catalog
' Connect to the
database.
Set cnn =
cat.ActiveConnection
' Insert records. cnn.Execute "INSERT INTO MyTable VALUES ('01 ', '11543B', "
& _
"'Hub Bearing', '125.05' ,'15 Feb 2005', '27')"
' or you can input the date
as #2/15/2005#
' This line will
delete the table. ''cat.Tables.Delete "MyTable"
' clean up objects
Set cat = Nothing
Set col = Nothing
End Sub
'Purpose: To create different tables with various field types using ADOX.
Function CreateTables_VariousFieldTypes()
Dim cat As New ADOX.Catalog
Dim tbl As ADOX.Table
Dim col As ADOX.Column
' connect the catalog to this database
Set cat.ActiveConnection = CurrentProject.Connection ' Initialize the 'tbl_CustomerCode' table
Set tbl = New ADOX.Table
tbl.Name = "tbl_CustomerCode"
Set col = New ADOX.Column
col.Name = "CustomerCode"
col.Type = adInteger
Set col.ParentCatalog = cat
col.Properties("Autoincrement") = True
col.Properties("Description") =
"generate
auto-unique identifier for this record" col.Properties("Nullable") = False
col.Properties("Jet OLEDB:Allow Zero Length") = False
tbl.Columns.Append col
Set col = New ADOX.Column
col.Name = "CustomerName"
col.Type = adWChar
col.DefinedSize = 50
col.Attributes = 0 ' disallow null Set col.ParentCatalog = cat
col.Properties("Description") = "customer names"
tbl.Columns.Append col
' Save the new table by appending to catalog.
cat.Tables.Append tbl
' Clean up objects Set tbl = Nothing
' Initialize the 'Suppliers' table.
Set tbl = New ADOX.Table
tbl.Name = "tbl_Suppliers"
' Add some columns to the table. With tbl.Columns .Append "SupplierID", adInteger
' Number (Long Integer) .Append "SupplierName", adVarWChar, 50
' Text (30 max) .Append "ContactName", adVarWChar, 15
' Text (15 max) .Append "Active", adBoolean
' Yes/No .Append "UnitPrice", adCurrency
' Currency .Append "MOQ", adSingle
' Number (Single) .Append "LastPurchaseDate", adDate
' Date/Time .Append "Web", adLongVarWChar
' Memo (for hyperlink) End With ' Set the field properties AutoNumber With !SupplierID Set .ParentCatalog = cat .Properties("Autoincrement") = True
End With ' Required field with no null With !SupplierName Set .ParentCatalog = cat .Properties("Nullable") = False
.Properties("Jet OLEDB:Allow Zero Length") = False
End With ' Set a validation rule With !LastPurchaseDate Set .ParentCatalog = cat .Properties("Jet OLEDB:Column Validation Rule") = "Is Null Or <=Date()" .Properties("Jet OLEDB:Column Validation Text") = "Date cannot be past"
End With
' Hyperlink field. With !Web Set .ParentCatalog = cat .Properties("Jet OLEDB:Hyperlink") = True
End With ' Save the new table by appending to catalog. cat.Tables.Append tbl
' clean up object Set tbl = Nothing Set cat = Nothing End Function
create an index for any field that we intend to sort or search
frequently.
Sub CreateIndexes()
Dim cat As New ADOX.Catalog
Dim tbl As ADOX.Table
Dim idx As ADOX.Index
Dim col As ADOX.Column
' Set up a catalog pointing to this database
Set cat.ActiveConnection = CurrentProject.Connection
' Retrieve an existing table 'MaterialsMaster' Set tbl = cat.Tables("MaterialsMaster")
' Create a primary key and an index on this primary key field 'PartNumber' Set idx = New ADOX.Index
With idx .Name = "PrimryKey" .PrimaryKey = True .Unique = True .Columns.Append "PartNumber"
' Specify the column for the index
End With
tbl.Indexes.Append idx
' Add the index to the table
' Create a second index on the StandardCost field Set idx = New ADOX.Index With idx .Name = "StdCosIndex" .Unique = False .Columns.Append "StandardCost"
End With
tbl.Indexes.Append "StdCosIndex", "StandardCost" ' Retrieve another table 'Q1CostReductionList' Set tbl = cat.Tables("Q1CostReductionList")
' And create its primary key and index on the 'MaterialNumber' field Set idx = New ADOX.Index
With idx .Name = "PrimryKey" .PrimaryKey = True .Unique = True .Columns.Append "MaterialNumber"
' Specify the column for the index End With
tbl.Indexes.Append idx' Add the index to the table
'Purpose: To create a new foreign key relationship between two
existing tables _
named 'Customers' and 'Orders'.
Sub
CreateForeignKeyRelationship()
On Error GoTo CreateKeyError
Dim kyForeign As New ADOX.Key
Dim cat As New ADOX.Catalog
' Connect to the catalog.
cat.ActiveConnection = "Provider='Microsoft.Jet.OLEDB.4.0';" & _
"Data Source=C:\Program Files\Microsoft
Office\OFFICE11\SAMPLES\Northwind.mdb;"
' Define the foreign
key. kyForeign.Name = "CustOrder"
' define name of key kyForeign.Type = adKeyForeign
' type as foreign key kyForeign.RelatedTable = "Customers"
' name of the primary key
table 'Customers' kyForeign.Columns.Append "CustomerId"
' to append column 'CustomerID'
of the foreign key table kyForeign.Columns("CustomerId").RelatedColumn = "CustomerId"
' primary key table is also 'CustomerID' kyForeign.UpdateRule = adRICascade
' Append the foreign
key to the keys collection. cat.Tables("Orders").Keys.Append kyForeign
' Delete the key to
demonstrate the Delete method. cat.Tables("Orders").Keys.Delete kyForeign.Name
' Clean up objects.
Set cat.ActiveConnection = Nothing
Set cat = Nothing
Set kyForeign = Nothing
Exit Sub
CreateKeyError:
Set cat = Nothing
Set kyForeign = Nothing
If Err <> 0 Then
MsgBox Err.Source & "-->" & Err.Description, , "Error"
End If
End Sub
'Purpose: To
create/delete new fields with Types and Attributes
Sub CreateNewFieldWithAttributes()
On Error GoTo AttributesXError
Dim cnn As New ADODB.Connection
Dim cat As New ADOX.Catalog
Dim col As New ADOX.Column
Dim rst As New ADODB.Recordset
Dim tbl As ADOX.Table
Dim strMessage As String
Dim strInput As String
' Connect the
catalog. cnn.Open
"Provider='Microsoft.Jet.OLEDB.4.0';" & _
"Data Source=C:\Program Files\Microsoft
Office\OFFICE11\SAMPLES\Northwind.mdb;"
Set cat.ActiveConnection = cnn
' Make a catalog for the database. Set tbl = cat.Tables("Employees")
' Get the table.
' Create a new Field
object 'Fax' and append it to the Fields collection of the Employees table. col.Name = "Fax"
col.Type = adVarWChar
col.DefinedSize = 12
col.Attributes = adColNullable
cat.Tables("Employees").Columns.Append col.Name, adWChar, 12
' Open the Employees
table for updating as a Recordset. rst.Open "Employees", cnn, adOpenKeyset, adLockOptimistic, adCmdTable
With rst ' Get user input. strMessage = "Enter fax number for " & !FirstName & " " & !LastName &
"." & vbCr & _
"[? = unknown, NA = no fax]"
strInput = UCase(InputBox(strMessage))
If
strInput <> "" Then
Select Case strInput
Case "?"
!Fax = Null
Case "NA"
!Fax = ""
Case Else
!Fax = strInput
End Select
.Update
If
IsNull(!Fax) Then
Debug.Print "[Unknown]"
Else
If
!Fax = "" Then
Debug.Print "[Has no fax]"
Else
Debug.Print !Fax
End If
End If
End If
.Close
End With
' Drop the field.
It's just a test. tbl.Columns.Delete "Fax" 'Or, tbl.Columns.Delete col.Name
' Clean up objects. cnn.Close
Set rst = Nothing
Set cat = Nothing
Set col = Nothing
Set cnn = Nothing
Exit Sub
AttributesXError:
If
Not rst Is Nothing Then
If
rst.State = adStateOpen Then rst.Close
End If
Set rst = Nothing
If
Not tbl Is Nothing Then
tbl.Columns.Delete col.Name
End If
Set cat = Nothing
Set col = Nothing
If
Not cnn Is Nothing Then
If
cnn.State = adStateOpen Then
cnn.Close
End If
End If
Set cnn = Nothing
If
Err <> 0 Then
MsgBox Err.Source & "-->" & Err.Description, , "Error"
End If
End Sub
' Show the current owner of the 'Orders' table. strOwner = cat.GetObjectOwner("Orders", adPermObjTable)
Debug.Print "Orders table is owned by " & strOwner
' Display permissions of current owner of the 'Orders' table. Refer to
RightsEnum Constants. Debug.Print "Full permissions: " & _
str(cat.Users("admin").GetPermissions("Orders", adPermObjTable))
' Change the ownership. cat.SetObjectOwner "Orders", adPermObjTable, "William"
Debug.Print "Orders table is now owned by William"
' Grant user full access
right permissions on the 'Orders' table. cat.Users("William").SetPermissions "Orders", adPermObjTable,
adAccessSet, adRightFull
' these 2 lines are to delete user's account and group 'Planning'. cat.Users.Delete ("William")
cat.Groups.Delete ("Planning")
' Or alternatively, use this
line to revoke only all permissions to the user. 'cat.Users("William").SetPermissions "Orders", adPermObjTable,
adAccessRevoke, adRightFull
' Set ownership back to Admin with full access permissions. cat.SetObjectOwner "Orders", adPermObjTable, "Admin"
cat.Users("Admin").SetPermissions "Orders", adPermObjTable, adAccessSet,
adRightFull
End Sub
'Create the
parameterized command text (Microsoft Jet specific) Set cmd.ActiveConnection = cnn
cmd.CommandText = "PARAMETERS [CustID] Text;" _
&
"SELECT * FROM Customers WHERE CustomerID = [CustID]"
'Create the new
Procedure cat.Procedures.Append "qry_CustomerByID", cmd
' or use
cat.Views.Append "qry_CustomerByID", cmd
'use the
Command property to update the text of a procedure. Set cmd = cat.Procedures("qry_CustomerByID").Command
' Get the
command. cmd.CommandText = "SELECT * FROM Customers WHERE CustomerID = 'ANTON'"
' Update the CommandText. Set cat.Procedures("qry_CustomerByID").Command = cmd
' Update the procedure.
'To obtain all views
in the catalog For Each objView In cat.Views
Debug.Print viw.Name
Next
cat.Views.Delete "qry_CustomerByID" ' Delete the procedure as
it's only testing
'Clean up
objects cnn.Close
Set cmd = Nothing
Set cat = Nothing
Set cnn = Nothing
End Sub
'Purpose: To modify/delete tables, procedures, columns, fields,
indexes, keys, users and group.
Sub Deletes()
Dim cnn As New ADODB.Connection
Dim cat As New ADOX.Catalog
Dim tbl As New ADOX.Table
Dim col As New ADOX.Column
Dim cmd As New ADODB.Command
Dim ind As New ADOX.Index
Dim ky As New ADOX.Key
Dim prp As ADOX.Property
' Connect the catalog to the current database
cat.ActiveConnection = CurrentProject.Connection
' Add a new table and
two fields tbl.Name = ("My_Table")
tbl.Columns.Append "Field1", adInteger
With col
.Name = "My_Field"
.Type = adNumeric 'Decimal data type
.Precision = 16 '28 digits
.NumericScale
= 4 '8 decimal places
End With
tbl.Columns.Append col
cat.Tables.Append tbl
' Modify the column
properties Set col = cat.Tables("My_Table").Columns("My_Field")
' Point column object
to the field Set prp = col.Properties("Nullable")
' Set column property
to null Debug.Print prp.Name, prp.Value, prp.Attributes, (prp.Type = adBoolean)
' Print the property col.Properties("Jet OLEDB:Allow Zero Length") = False
' Change to disallow
zero-length
' Create a primary
key index Set tbl = cat.Tables("My_Table")
Set ind = New ADOX.Index
ind.Name = "PrimaryKey"
ind.PrimaryKey = True
ind.Columns.Append "My_Field"
tbl.Indexes.Append ind
' Retrieve the
foreign key table Set tbl = cat.Tables("My_Table2") ' Create as foreign
key to Table2.Field2 Set ky = New ADOX.Key
With ky
.Name = "My_Table2Key"
.Type = adKeyForeign
.RelatedTable
= "My_Table"
.Columns.Append
"My_Field2"
.Columns("My_Field2").RelatedColumn = "My_Field" .DeleteRule
= adRISetNull
' Cascade to Null on
delete End With
tbl.Keys.Append ky
' Create the command
and the new view cmd.CommandText = "Select * From My_Table"
cat.Views.Append "My_Query", cmd
cat.Tables("My_Table2").Keys.Delete ky.Name
' Delete the foreign
key cat.Tables("My_Table").Indexes.Delete "Primarykey"
' Delete the index cat.Views.Delete "My_Query"
' Delete the query cat.Tables.Delete "My_Table"
' Delete the table cat.Users.Delete ("William")
' Delete the user
account cat.Groups.Delete ("Planning")
' Delete the group
account
' Clean up the
objects Set ky = Nothing
Set ind = Nothing
Set prp = Nothing
Set col = Nothing
Set tbl = Nothing
Set cat = Nothing
End Sub
Note:
It is wise to have a message box to prompt user for confirmation
especially on deleting tables and fields. Below is an example code.
Dim cat As
ADOX.Catalog
Dim tbl As New ADOX.Table
Dim input As Long
For Each tbl In cat.Tables
input = MsgBox("Do you want to delete " & tbl.Name, vbYesNo, "Delete
table..."), _
vbYesNo, "Confirm table delete")
If input = vbYes Then
input = MsgBox("Are you sure you want
to PERMANENTLY delete " & tbl.Name _
& "from the database?", vbYesNo,
"Confirm delete...")
If input = vbYes Then DoCmd.DeleteObject acTable,
tbl.Name
"MsgBox "Table
deleted"
End If
End If
Next tbl
'Purpose: To
retrieve total count of Excel worksheets and all sheet names.
Sub
RetrieveWorkbooksSchema()
Dim cnn As New ADODB.Connection
Dim cat As New ADOX.Catalog
Dim adoTable As ADOX.Table
Dim adoTables As ADOX.Tables
Dim path As String
path = "C:\MySheet.xls"
' change your path and
workbook name
' Connection string to Excel cnn.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
path & _
";Extended Properties=""Excel 8.0;HDR=Yes;""" ' Open the connection cnn.Open
' Treat the workbook as a database catalog cat.ActiveConnection = cnn
' Get the catalogs tables, which in this case is the worksheets Set adoTables = cat.Tables
' Print a count of the worksheets Debug.Print "No. of worksheets: " & adoTables.Count
' For each table/sheet in the catalog/workbook display the name For Each adoTable In adoTables
Debug.Print adoTable.Name
Next
' Close the connection cnn.Close ' Clean up objects Set cnn = Nothing
Set cat = Nothing
Set adoTables = Nothing
Set adoTable = Nothing
End Sub
'Purpose: another
Visual Basic example that gets Excel spreadsheet schema and print into
an array _ using ADOX objects.
Sub RetrieveWorkbooksSchema2()
Dim cnn As New ADODB.Connection
Dim cat As New ADOX.Catalog
Dim tbl As ADOX.Table
Dim col As ADOX.Column
Dim strCnn As String
Dim iTbl As Integer, iCol As Integer
Dim strColNames(1 To 100, 1 To 1000) As String
' a two-dimensional array
assigns two indexes to each element
iTbl = 0
iCol = 0
For Each tbl In cat.Tables
iTbl = iTbl + 1 For Each col In tbl.Columns
iCol = iCol + 1 strColNames(iTbl, iCol) = tbl.Name & col.Name Debug.Print tbl.Name & ": " & col.Name Next col
Next tbl
End Sub
Show the columns in a table, and optionally their properties, using ADOX.
Function ShowTableProperties(strTable As String, Optional
ShowProperties As Boolean)
Dim cat As New ADOX.Catalog
Dim tbl As ADOX.Table
Dim col As ADOX.Column
Dim prp As ADOX.Property
'Point the catalog to the current project's connection. Set cat.ActiveConnection = CurrentProject.Connection
Set tbl = cat.Tables(strTable)
For Each col In tbl.Columns
Debug.Print col.Name If ShowProperties Then For Each prp In col.Properties Debug.Print , prp.Name, prp.Type,
prp.Attributes, prp.Value Next Debug.Print
"---------------------" End If
Next
'Clean up objects Set prp = Nothing
Set col = Nothing
Set tbl = Nothing
Set cat = Nothing
End Function