O objetivo deste artigo é o de ser uma referência para os desenvolvedores da língua portuguesa, demonstrando como usar a biblioteca DAO de forma programável, criando, apagando, modificando e listando os objetos no MS Access. Através deste artigo terá condições de manipular as tabelas, os seus campos e índices, bem como o seu relacionamento com outras tabelas. Também poderá ler e definir suas propriedades, tanto de consultas como as do banco de dados.
Note: Não há explicações além de comentários numa linha, e nenhum erro de manipulação, na maioria dos exemplos.
'Constants for examining how a field is indexed.
Private Const intcIndexNone As Integer = 0
Private Const intcIndexGeneral As Integer = 1
Private Const intcIndexUnique As Integer = 3
Private Const intcIndexPrimary As Integer = 7
Function CreateTableDAO()
'Purpose: Create two tables using DAO.
'Initialize the Contractor table.
Set tdf = db.CreateTableDef("tblDaoContractor")
'AutoNumber: Long with the attribute set.
Set fld = .CreateField("ContractorID", dbLong)
fld.Attributes = dbAutoIncrField + dbFixedField
'Text field: maximum 30 characters, and required.
Set fld = .CreateField("Surname", dbText, 30)
'Text field: maximum 20 characters.
.Fields.Append .CreateField("FirstName", dbText, 20)
.Fields.Append .CreateField("Inactive", dbBoolean)
.Fields.Append .CreateField("HourlyFee", dbCurrency)
.Fields.Append .CreateField("PenaltyRate", dbDouble)
'Date/Time field with validation rule.
Set fld = .CreateField("BirthDate", dbDate)
fld.ValidationRule = "Is Null Or <=Date()"
fld.ValidationText = "Birth date cannot be future."
.Fields.Append .CreateField("Notes", dbMemo)
'Hyperlink field: memo with the attribute set.
Set fld = .CreateField("Web", dbMemo)
fld.Attributes = dbHyperlinkField + dbVariableField
'Save the Contractor table.
Debug.Print "tblDaoContractor created."
'Initialize the Booking table
Set tdf = db.CreateTableDef("tblDaoBooking")
Set fld = .CreateField("BookingID", dbLong)
fld.Attributes = dbAutoIncrField + dbFixedField
.Fields.Append .CreateField("BookingDate", dbDate)
.Fields.Append .CreateField("ContractorID", dbLong)
.Fields.Append .CreateField("BookingFee", dbCurrency)
Set fld = .CreateField("BookingNote", dbText, 255)
Debug.Print "tblDaoBooking created."
Application.RefreshDatabaseWindow 'Show the changes
Function ModifyTableDAO()
'Purpose: How to add and delete fields to existing tables.
'Note: Requires the table created by CreateTableDAO() above.
Set tdf = db.TableDefs("tblDaoContractor")
'Add a field to the table.
tdf.Fields.Append tdf.CreateField("TestField", dbText, 80)
Debug.Print "Field added."
'Delete a field from the table.
tdf.Fields.Delete "TestField"
Debug.Print "Field deleted."
Function DeleteTableDAO()
DBEngine(0)(0).TableDefs.Delete "DaoTest"
'Purpose: How to create a table with a GUID field.
Set tdf = db.CreateTableDef("Table8")
Set fld = .CreateField("ID", dbGUID)
fld.Attributes = dbFixedField
fld.DefaultValue = "GenGUID()"
Function CreateIndexesDAO()
Set tdf = db.TableDefs("tblDaoContractor")
Set ind = tdf.CreateIndex("PrimaryKey")
.Fields.Append .CreateField("ContractorID")
Set ind = tdf.CreateIndex("Inactive")
ind.Fields.Append ind.CreateField("Inactive")
Set ind = tdf.CreateIndex("FullName")
.Fields.Append .CreateField("Surname")
.Fields.Append .CreateField("FirstName")
'Refresh the display of this collection.
Debug.Print "tblDaoContractor indexes created."
Function DeleteIndexDAO()
DBEngine(0)(0).TableDefs("tblDaoContractor").Indexes.Delete "Inactive"
Function CreateRelationDAO()
Set rel = db.CreateRelation("tblDaoContractortblDaoBooking")
'Specify the primary table.
.Table = "tblDaoContractor"
'Specify the related table.
.ForeignTable = "tblDaoBooking"
'Specify attributes for cascading updates and deletes.
.Attributes = dbRelationUpdateCascade + dbRelationDeleteCascade
'Add the fields to the relation.
'Field name in primary table.
Set fld = .CreateField("ContractorID")
'Field name in related table.
fld.ForeignName = "ContractorID"
'Repeat for other fields if a multi-field relation.
'Save the newly defined relation to the Relations collection.
Debug.Print "Relation created."
Function DeleteRelationDAO()
DBEngine(0)(0).Relations.Delete "tblDaoContractortblDaoBooking"
Function DeleteQueryDAO()
DBEngine(0)(0).QueryDefs.Delete "qryDaoBooking"
Function SetPropertyDAO(obj As Object, strPropertyName As String, intType As Integer, _
varValue As Variant, Optional strErrMsg As String) As Boolean
'Purpose: Set a property for an object, creating if necessary.
'Arguments: obj = the object whose property should be set.
' strPropertyName = the name of the property to set.
' intType = the type of property (needed for creating)
' varValue = the value to set this property to.
' strErrMsg = string to append any error message to.
If HasProperty(obj, strPropertyName) Then
obj.Properties(strPropertyName) = varValue
obj.Properties.Append obj.CreateProperty(strPropertyName, intType, varValue)
strErrMsg = strErrMsg & obj.Name & "." & strPropertyName & " not set to " & varValue & _
". Error " & Err.Number & " - " & Err.Description & vbCrLf
Public Function HasProperty(obj As Object, strPropName As String) As Boolean
'Purpose: Return true if the object has the property.
varDummy = obj.Properties(strPropName)
HasProperty = (Err.Number = 0)
Function StandardProperties(strTableName As String)
'Purpose: Properties you always want set by default:
' TableDef: Subdatasheets off.
' Numeric fields: Remove Default Value.
' Currency fields: Format as currency.
' Yes/No fields: Display as check box. Default to No.
' Text/memo/hyperlink: AllowZeroLength off,
' All fields: Add a caption if mixed case.
'Argument: Name of the table.
'Note: Requires: SetPropertyDAO()
Dim db As DAO.Database 'Current database.
Dim tdf As DAO.TableDef 'Table nominated in argument.
Dim fld As DAO.Field 'Each field.
Dim strCaption As String 'Field caption.
Dim strErrMsg As String 'Responses and error messages.
Set tdf = db.TableDefs(strTableName)
'Set the table's SubdatasheetName.
Call SetPropertyDAO(tdf, "SubdatasheetName", dbText, "[None]", _
For Each fld In tdf.Fields
'Handle the defaults for the different field types.
Case dbText, dbMemo 'Includes hyperlinks.
fld.AllowZeroLength = False
Call SetPropertyDAO(fld, "UnicodeCompression", dbBoolean, _
Call SetPropertyDAO(fld, "Format", dbText, "Currency", _
Case dbLong, dbInteger, dbByte, dbDouble, dbSingle, dbDecimal
fld.DefaultValue = vbNullString
Call SetPropertyDAO(fld, "DisplayControl", dbInteger, _
'Set a caption if needed.
strCaption = ConvertMixedCase(fld.Name)
If strCaption <> fld.Name Then
Call SetPropertyDAO(fld, "Caption", dbText, strCaption)
'Set the field's Description.
Call SetFieldDescription(tdf, fld, , strErrMsg)
If Len(strErrMsg) > 0 Then
Debug.Print "Properties set for table " & strTableName
Function ConvertMixedCase(ByVal strIn As String) As String
'Purpose: Convert mixed case name into a name with spaces.
'Argument: String to convert.
'Return: String converted by these rules:
' 1. One space before an upper case letter.
' 2. Replace underscores with spaces.
' 3. No spaces between continuing upper case.
'Example: "FirstName" or "First_Name" => "First Name".
Dim lngStart As Long 'Loop through string.
Dim strOut As String 'Output string.
Dim boolWasSpace As Boolean 'Last char. was a space.
Dim boolWasUpper As Boolean 'Last char. was upper case.
strIn = Trim$(strIn) 'Remove leading/trailing spaces.
boolWasUpper = True 'Initialize for no first space.
For lngStart = 1& To Len(strIn)
Select Case Asc(Mid(strIn, lngStart, 1&))
Case vbKeyA To vbKeyZ 'Upper case: insert a space.
If boolWasSpace Or boolWasUpper Then
strOut = strOut & Mid(strIn, lngStart, 1&)
strOut = strOut & " " & Mid(strIn, lngStart, 1&)
Case 95 'Underscore: replace with space.
Case vbKeySpace 'Space: output and set flag.
Case Else 'Any other char: output.
strOut = strOut & Mid(strIn, lngStart, 1&)
ConvertMixedCase = strOut
Function SetFieldDescription(tdf As DAO.TableDef, fld As DAO.Field, _
Optional ByVal strDescrip As String, Optional strErrMsg As String) _
'Purpose: Assign a Description to a field.
'Arguments: tdf = the TableDef the field belongs to.
' fld = the field to document.
' strDescrip = The description text you want.
' If blank, uses Caption or Name of field.
' strErrMsg = string to append any error messages to.
'Notes: Description includes field size, validation,
' whether required or unique.
If (fld.Attributes And dbAutoIncrField) > 0& Then
strDescrip = strDescrip & " Automatically generated " & _
"unique identifier for this record."
'If no description supplied, use the field's Caption or Name.
If Len(strDescrip) = 0& Then
If HasProperty(fld, "Caption") Then
If Len(fld.Properties("Caption")) > 0& Then
strDescrip = fld.Properties("Caption") & "."
If Len(strDescrip) = 0& Then
strDescrip = fld.Name & "."
'Ignore Date, Memo, Yes/No, Currency, Decimal, GUID,
Case dbByte, dbInteger, dbLong
strDescrip = strDescrip & " Whole number."
strDescrip = strDescrip & " Fractional number."
strDescrip = strDescrip & " " & fld.Size & "-char max."
'Check for single-field index, and Required property.
Select Case IndexOnField(tdf, fld)
strDescrip = strDescrip & " Required. Unique."
strDescrip = strDescrip & " Required. Unique."
strDescrip = strDescrip & " Unique."
strDescrip = strDescrip & " Required."
If Len(fld.ValidationRule) > 0& Then
If Len(fld.ValidationText) > 0& Then
strDescrip = strDescrip & " " & fld.ValidationText
strDescrip = strDescrip & " " & fld.ValidationRule
If Len(strDescrip) > 0& Then
strDescrip = Trim$(Left$(strDescrip, 255&))
SetFieldDescription = SetPropertyDAO(fld, "Description", _
dbText, strDescrip, strErrMsg)
Private Function IndexOnField(tdf As DAO.TableDef, fld As DAO.Field) _
'Purpose: Indicate if there is a single-field index _
' on this field in this table.
'Return: The constant indicating the strongest type.
intReturn = intcIndexNone
For Each ind In tdf.Indexes
If ind.Fields.Count = 1 Then
If ind.Fields(0).Name = fld.Name Then
intReturn = (intReturn Or intcIndexPrimary)
intReturn = (intReturn Or intcIndexUnique)
intReturn = (intReturn Or intcIndexGeneral)
Function CreateQueryDAO()
'Purpose: How to create a query
'Note: Requires a table named MyTable.
'The next line creates and automatically appends the QueryDef.
Set qdf = db.CreateQueryDef("qryMyTable")
'Set the SQL property to a string representing a SQL statement.
qdf.SQL = "SELECT MyTable.* FROM MyTable;"
'Do not append: QueryDef is automatically appended!
Debug.Print "qryMyTable created."
Function CreateDatabaseDAO()
'Purpose: How to create a new database and set key properties.
Dim dbNew As DAO.Database
'Create the new database.
strFile = "C:\SampleDAO.mdb"
Set dbNew = DBEngine(0).CreateDatabase(strFile, dbLangGeneral)
'Create example properties in new database.
Set prp = .CreateProperty("Perform Name AutoCorrect", dbLong, 0)
Set prp = .CreateProperty("Track Name AutoCorrect Info", _
Debug.Print "Created " & strFile
Function ShowDatabaseProps()
'Purpose: List the properies of the current database.
For Each prp In db.Properties
Function ShowFields(strTable As String)
'Purpose: How to read the fields of a table.
'Usage: Call ShowFields("Table1")
Set tdf = db.TableDefs(strTable)
For Each fld In tdf.Fields
Debug.Print fld.Name, FieldTypeName(fld)
Function ShowFieldsRS(strTable)
'Purpose: How to read the field names and types from a table or query.
'Usage: Call ShowFieldsRS("Table1")
strSql = "SELECT " & strTable & ".* FROM " & strTable & " WHERE (False);"
Set rs = DBEngine(0)(0).OpenRecordset(strSql)
For Each fld In rs.Fields
Debug.Print fld.Name, FieldTypeName(fld), "from " & fld.SourceTable & "." & fld.SourceField
Public Function FieldTypeName(fld As DAO.Field)
'Purpose: Converts the numeric results of DAO fieldtype to text.
'Note: fld.Type is Integer, but the constants are Long.
Dim strReturn As String 'Name to return
Select Case CLng(fld.Type)
Case dbBoolean: strReturn = "Yes/No" ' 1
Case dbByte: strReturn = "Byte" ' 2
Case dbInteger: strReturn = "Integer" ' 3
If (fld.Attributes And dbAutoIncrField) = 0& Then
strReturn = "Long Integer"
Case dbCurrency: strReturn = "Currency" ' 5
Case dbSingle: strReturn = "Single" ' 6
Case dbDouble: strReturn = "Double" ' 7
Case dbDate: strReturn = "Date/Time" ' 8
Case dbBinary: strReturn = "Binary" ' 9 (no interface)
If (fld.Attributes And dbFixedField) = 0& Then
strReturn = "Text (fixed width)"
Case dbLongBinary: strReturn = "OLE Object" '11
If (fld.Attributes And dbHyperlinkField) = 0& Then
Case dbGUID: strReturn = "GUID" '15
'Attached tables only: cannot create these in JET.
Case dbBigInt: strReturn = "Big Integer" '16
Case dbVarBinary: strReturn = "VarBinary" '17
Case dbChar: strReturn = "Char" '18
Case dbNumeric: strReturn = "Numeric" '19
Case dbDecimal: strReturn = "Decimal" '20
Case dbFloat: strReturn = "Float" '21
Case dbTime: strReturn = "Time" '22
Case dbTimeStamp: strReturn = "Time Stamp" '23
'Constants for complex types don't work prior to Access 2007.
Case 101&: strReturn = "Attachment" 'dbAttachment
Case 102&: strReturn = "Complex Byte" 'dbComplexByte
Case 103&: strReturn = "Complex Integer" 'dbComplexInteger
Case 104&: strReturn = "Complex Long" 'dbComplexLong
Case 105&: strReturn = "Complex Single" 'dbComplexSingle
Case 106&: strReturn = "Complex Double" 'dbComplexDouble
Case 107&: strReturn = "Complex GUID" 'dbComplexGUID
Case 108&: strReturn = "Complex Decimal" 'dbComplexDecimal
Case 109&: strReturn = "Complex Text" 'dbComplexText
Case Else: strReturn = "Field type " & fld.Type & " unknown"
FieldTypeName = strReturn
Function DAORecordsetExample()
'Purpose: How to open a recordset and loop through the records.
'Note: Requires a table named MyTable, with a field named MyField.
strSql = "SELECT MyField FROM MyTable;"
Set rs = DBEngine(0)(0).OpenRecordset(strSql)
Function ShowFormProperties(strFormName As String)
On Error GoTo Err_Handler
'Purpose: Loop through the controls on a form, showing names and properties.
'Usage: Call ShowFormProperties("Form1")
DoCmd.OpenForm strFormName, acDesign, WindowMode:=acHidden
Set frm = Forms(strFormName)
For Each prp In ctl.Properties
strOut = strFormName & "." & ctl.Name & "." & prp.Name & ": "
strOut = strOut & prp.Type & vbTab
strOut = strOut & prp.Value
If ctl.ControlType = acTextBox Then Stop
DoCmd.Close acForm, strFormName, acSaveNo
strOut = strOut & Err.Description
MsgBox "Error " & Err.Number & ": " & Err.Description, vbExclamation, "ShowFormProperties()"
Public Function ExecuteInTransaction(strSql As String, Optional strConfirmMessage As String) As Long
On Error GoTo Err_Handler
'Purpose: Execute the SQL statement on the current database in a transaction.
'Return: RecordsAffected if zero or above.
'Arguments: strSql = the SQL statement to be executed.
' strConfirmMessage = the message to show the user for confirmation. Number will be added to front.
' No confirmation if ZLS.
Const lngcUserCancel = -2&
db.Execute strSql, dbFailOnError
lngReturn = db.RecordsAffected
If strConfirmMessage <> vbNullString Then
If MsgBox(lngReturn & " " & Trim$(strConfirmMessage), vbOKCancel + vbQuestion, "Confirm") <> vbOK Then
lngReturn = lngcUserCancel
ExecuteInTransaction = lngReturn
MsgBox "Error " & Err.Number & ": " & Err.Description, vbExclamation, "ExecuteInTransaction()"
Function GetAutoNumDAO(strTable) As String
'Purpose: Get the name of the AutoNumber field, using DAO.
Set tdf = db.TableDefs(strTable)
For Each fld In tdf.Fields
If (fld.Attributes And dbAutoIncrField) <> 0 Then