FAQ Visual Basic
FAQ Visual Basic Consultez toutes les FAQ
Nombre d'auteurs : 50, nombre de questions : 300, dernière mise à jour : 15 juin 2021
- Pourquoi j'ai l'erreur "type de données incompatible dans l'expression du critère" ?
- Pourquoi ma requête, qui a un critère sur une date, ne me renvoie aucun enregistrement ?
- Pourquoi j'ai une erreur de syntaxe dans ma requête quand un des arguments contient une apostrophe ?
- Comment spécifier les valeurs des paramètres d'une procédure stockée ?
- Qu'est-ce que MDAC et où puis-je le télécharger ?
- Comment lire la structure d'une base de données avec ADO ?
- Comment déterminer si une table existe avec ADO ?
- Pourquoi la propriété RecordCount me renvoie toujours -1 ?
- Comment connaître le nombre de lignes affectées par une requête UPDATE (ADO) ?
- Comment créer un lien ODBC à partir de VB ?
- Comment ouvrir la boîte de dialogue pour créer/éditer une connexion OleDB ?
- Comment créer une base mdb, sans Access :
- Comment compacter une base de données avec ADO ?
- Comment créer une base mdb, en DAO :
- Comment afficher les tables et champs d'une base de données ?
Cette erreur a lieu lorsque la valeur d'un critère dans la clause WHERE d'une requête Sql est mal écrite. Les valeurs spécifiées pour des champs de type texte doivent être entre apostrophes, et pour les champs de type date, entre "#".
SELECT * FROM documents WHERE ((titre like 'how-to%') AND (creation>#01/01/2002#) AND (auteur=10))
Parce que la date est lue au format mois/jour/année. Donc dans vos requêtes, les dates doivent être dans ce format. L'exemple suivant utilise la fonction Format() afin de formater la date correctement :
sql=
"SELECT * from documents WHERE (DateCreation >= #"
&
Format
(
dateSaisie,"mm/dd/yyyy"
) &
"#)"
Parce que l'apostrophe doit être doublée sinon elle est considérée comme la fin de la chaîne. Voici une fonction qui double les apostrophes trouvées dans la chaîne passée en paramètre.
Private
Function
DoubleQuote
(
ByVal
chaine As
String
) As
String
DoubleQuote =
Replace
(
chaine, "'"
,"''"
)
End
Function
Les paramètres sont dans la collection Parameters de l'objet Command :
Set
cmd =
New
ADODB.Command
cmd.CommandType
=
adCmdStoredProc
cmd.CommandText
=
"procedure1"
Set
cmd.ActiveConnection
=
cnn 'cnn est un objet Adodb.Connection
cmd.Parameters.Item
(
"@auteur"
).Value
=
10
cmd.Parameters.Item
(
"@type"
).Value
=
"how-to"
cmd.Parameters.Item
(
"@langage"
).Value
=
"vb"
MDAC, qui signifie Microsoft Data Access Component, contient les composants d'accès aux bases de données que sont OLE DB, ADO, ODBC et RDS, ainsi que quelques pilotes et providers pour ODBC et OLEDB.
Le contenu des différentes versions et les liens pour les télécharger sont sur la page officielle : http:/www.microsoft.com/downloads/
Lien : Comment inclure MDAC à mon programme d'installation ?
Pour lire la structure des bases on utilise la méthode OpenSchema de l'objet Connection. Cette méthode permet de lire des informations du schéma, soit globales, soit restreintes selon les paramètres passés.
Pour exécuter l'exemple suivant, vous devez sélectionner la référence "Microsoft ActiveX Data Object 2.X Library" ainsi que le composant "Microsoft Windows Common Controls 6.0". Déposez sur votre feuille un contrôle TreeView nommé "TreeView1", un bouton de commande nommé "Command1", et un textbox "Text1". Puis copiez le code ci-dessous dans le module de la form.
Private
Sub
Command1_Click
(
)
Dim
MaConn As
ADODB.Connection
, rstTable As
ADODB.Recordset
Dim
rstEnfant As
ADODB.Recordset
, rstCompl As
ADODB.Recordset
Dim
cmpt1 As
Long
, cmpt2 As
Long
, NomTable As
String
, Indexed As
Boolean
Dim
cleNoeudTable As
String
, cleNoeudChamps As
String
, cleNoeudCles As
String
Dim
cleNoeudChampCourant As
String
, cleNoeudCleCourante As
String
'création de la connexion
Set
MaConn =
New
ADODB.Connection
MaConn.Provider
=
"Microsoft.Jet.OLEDB.4.0;"
MaConn.Open
Text1.text
'création du recordset contenant la structure des tables
Set
rstTable =
New
ADODB.Recordset
Set
rstTable =
MaConn.OpenSchema
(
adSchemaTables)
'Ajout de la racine du treeview
TreeView1.Nodes.Add
, , "r"
, "Structure"
TreeView1.Nodes
(
1
).Expanded
=
True
'Parcours de la collection des tables
cmpt1 =
1
Do
While
Not
rstTable.EOF
NomTable =
rstTable!Table_Name
'élimine les tables systèmes et les Vues
If
InStr
(
1
, NomTable, "MSYS"
, vbTextCompare) <>
1
And
rstTable!Table_Type <>
"VIEW"
Then
'Ajout de la table au treeview
cleNoeudTable =
"t"
&
cmpt1
TreeView1.Nodes.Add
"r"
, tvwChild, cleNoeudTable, NomTable
'création du recordset des champs de la table
Set
rstEnfant =
New
ADODB.Recordset
Set
rstEnfant =
MaConn.OpenSchema
(
adSchemaColumns, Array
(
Empty
, Empty
, NomTable, Empty
))
cmpt2 =
1
cleNoeudChamps =
cleNoeudTable &
"ch"
cleNoeudCles =
cleNoeudTable &
"cl"
TreeView1.Nodes.Add
cleNoeudTable, tvwChild, cleNoeudChamps, "champs"
TreeView1.Nodes.Add
cleNoeudTable, tvwChild, cleNoeudCles, "clés"
Do
While
Not
rstEnfant.EOF
'ajoute au treeview le champ et ses caractéristiques
cleNoeudChampCourant =
cleNoeudChamps &
cmpt2
TreeView1.Nodes.Add
cleNoeudChamps, tvwChild, cleNoeudChampCourant, rstEnfant!COLUMN_NAME
TreeView1.Nodes.Add
cleNoeudChampCourant, tvwChild, cleNoeudChampCourant &
"n"
, _
"peut être NULL -> "
&
rstEnfant!IS_NULLABLE
TreeView1.Nodes.Add
cleNoeudChampCourant, tvwChild, cleNoeudChampCourant &
"t"
, _
"Type -> "
&
Switch
(
rstEnfant!DATA_TYPE =
adInteger
, "Long"
, _
rstEnfant!DATA_TYPE =
adSmallInt
, "Entier"
, _
rstEnfant!DATA_TYPE =
adWChar
, "String"
)
If
Not
IsNull
(
rstEnfant!CHARACTER_MAXIMUM_LENGTH) Then
_
TreeView1.Nodes.Add
cleNoeudChampCourant, tvwChild, cleNoeudChampCourant &
"l"
, _
"Max Caractères -> "
&
rstEnfant!CHARACTER_MAXIMUM_LENGTH
If
Not
IsNull
(
rstEnfant!NUMERIC_PRECISION) Then
TreeView1.Nodes.Add
cleNoeudChampCourant, tvwChild, cleNoeudChampCourant &
"p"
, _
"Précision -> "
&
rstEnfant!NUMERIC_PRECISION
TreeView1.Nodes.Add
cleNoeudChampCourant, tvwChild, cleNoeudChampCourant &
"e"
, _
"Echelle -> "
&
rstEnfant!NUMERIC_SCALE
End
If
'vérifie si le champ est indexé
Set
rstCompl =
New
ADODB.Recordset
Set
rstCompl =
MaConn.OpenSchema
(
adSchemaIndexes, Array
(
Empty
, Empty
, Empty
, Empty
, NomTable))
Indexed =
False
Do
While
Not
rstCompl.EOF
If
rstCompl!COLUMN_NAME =
rstEnfant!COLUMN_NAME Then
Indexed =
True
TreeView1.Nodes.Add
cleNoeudChampCourant, tvwChild, cleNoeudChampCourant &
"i"
, _
"Indexé -> Oui"
&
IIf
(
rstCompl!Unique, " sans "
, " avec "
) &
"doublons"
Exit
Do
End
If
rstCompl.MoveNext
Loop
If
Not
Indexed Then
TreeView1.Nodes.Add
cleNoeudChampCourant, tvwChild, _
cleNoeudChampCourant &
"i"
, "Indexé -> Non"
rstCompl.Close
Set
rstCompl =
Nothing
cmpt2 =
cmpt2 +
1
rstEnfant.MoveNext
Loop
rstEnfant.Close
cmpt2 =
2
'recherche les clés de la tables
Set
rstEnfant =
MaConn.OpenSchema
(
adSchemaPrimaryKeys, Array
(
Empty
, Empty
, NomTable))
If
Not
rstEnfant.BOF
Then
'ajout de la clé primaire si elle existe
TreeView1.Nodes.Add
cleNoeudCles, tvwChild, cleNoeudTable &
"cp"
, _
"Clé primaire -> "
&
rstEnfant!COLUMN_NAME
End
If
rstEnfant.Close
'Ajout des clés étrangères et de leurs caractéristiques
Set
rstEnfant =
MaConn.OpenSchema
(
adSchemaForeignKeys, _
Array
(
Empty
, Empty
, Empty
, Empty
, Empty
, NomTable))
Do
While
Not
rstEnfant.EOF
cleNoeudCleCourante =
cleNoeudCles &
cmpt2
TreeView1.Nodes.Add
cleNoeudCles, tvwChild, cleNoeudCleCourante, _
"Clé Etrangère -> "
&
rstEnfant!FK_COLUMN_NAME
TreeView1.Nodes.Add
cleNoeudCleCourante, tvwChild, cleNoeudCleCourante &
"cl"
, _
"Clé de la table -> "
&
rstEnfant!PK_TABLE_NAME
TreeView1.Nodes.Add
cleNoeudCleCourante, tvwChild, cleNoeudCleCourante &
"ur"
, _
"Update Rules -> "
&
rstEnfant!UPDATE_RULE
TreeView1.Nodes.Add
cleNoeudCleCourante, tvwChild, cleNoeudCleCourante &
"dr"
, _
"Delete Rules -> "
&
rstEnfant!DELETE_RULE
cmpt2 =
cmpt2 +
1
rstEnfant.MoveNext
Loop
cmpt1 =
cmpt1 +
1
rstEnfant.Close
Set
rstEnfant =
Nothing
End
If
rstTable.MoveNext
Loop
TreeView1.Style
=
tvwTreelinesPlusMinusText
End
Sub
Lancez le projet. Saisissez dans le textbox le chemin complet d'une base de données Access et cliquez sur le bouton de commande. Toute la structure de la base de données apparaît dans le treeview.
La fonction ci-dessous reçoit une connexion ouverte et le nom de la table à tester et renvoie Vrai si la table existe.
Public
Function
TableExiste
(
cnn As
ADODB.Connection
, ByVal
strTable As
String
) As
Boolean
Dim
rstTables As
ADODB.Recordset
'création du recordset contenant la structure des tables
Set
rstTables =
cnn.OpenSchema
(
adSchemaTables)
'Parcours de la collection des tables
Do
While
Not
rstTables.EOF
If
rstTables.fields
(
"Table_Name"
).Value
=
strTable And
rstTables.fields
(
"Table_Type"
).Value
<>
"VIEW"
Then
TableExiste =
True
Exit
Do
End
If
rstTables.MoveNext
Loop
rstTables.Close
End
Function
Parce qu'avec certains types de curseurs, la propriété Recordcount n'est pas valorisée automatiquement. Vous devez dans ce cas appeler tout d'abord la méthode movelast afin de vous placer sur le dernier enregistrement, puis appeler la méthode movefirst pour vous replacer sur le premier enregistrement, si nécessaire. Après un appel à movelast, recordcount contiendra la bonne valeur.
Pour éviter d'avoir à faire cette opération, privilégiez les curseurs "static" (cursorType = adOpenStatic) ou keyset (cursorType = adOpenKeyset). Enfin, si votre but est uniquement de déterminer si votre recordset contient des enregistrements ou pas, préférez l'utilisation de la propriété eof juste après l'ouverture du recordset.
Après votre requête UPDATE, placez ce code :
Dim
rs as
New
Adodb.Recordset
rs.CursorLocation
=
adUseclient
Set
rs =
ObjetCommand.Execute
(
nNbRecordAffected)
Placez 3 CommandButton sur une Form et les codes respectifs suivants.
Info : Me.hwnd est le handle de la Form appelant la configuration du DNS
Private
Const
ODBC_ADD_DSN =
1
Private
Const
ODBC_CONFIG_DSN =
2
Private
Const
ODBC_REMOVE_DSN =
3
Private
Declare
Function
SQLConfigDataSource Lib
"ODBCCP32.DLL"
(
ByVal
hwndParent As
Long
, _
ByVal
fRequest As
Long
, ByVal
lpszDriver As
String
, _
ByVal
lpszAttributes As
String
) As
Long
Private
Sub
Command1_Click
(
)
'---- Créer un DSN ---------
Dim
strDriver As
String
Dim
strAttributes As
String
Dim
intRet As
Long
strDriver =
"Microsoft Access Driver (*.mdb)"
&
Chr
$(
0
)
strAttributes =
"DSN=MS Access Perso"
&
Chr
$(
0
)
strAttributes =
strAttributes &
"DESCRIPTION=Test DSN par VB6"
&
Chr
$(
0
)
strAttributes =
strAttributes &
"DBQ=c:\bd_test.mdb"
&
Chr
$(
0
)
intRet =
SQLConfigDataSource
(
vbNull
, ODBC_ADD_DSN, strDriver, strAttributes)
If
intRet Then
MsgBox
"DSN Created"
Else
MsgBox
"Create Failed"
End
If
End
Sub
Private
Sub
Command2_Click
(
)
'---- Supprimer un DSN ---------
Dim
strDriver As
String
Dim
strAttributes As
String
Dim
intRet As
Long
strDriver =
"Microsoft Access Driver (*.mdb)"
&
Chr
$(
0
)
strAttributes =
"DSN=MS Access Perso"
&
Chr
$(
0
)
intRet =
SQLConfigDataSource
(
vbNull
, ODBC_REMOVE_DSN, strDriver, strAttributes)
If
intRet Then
MsgBox
"DSN Removed"
Else
MsgBox
"Remove Failed"
End
If
End
Sub
Private
Sub
Command3_Click
(
)
'---- Configurer un DSN ---------
Dim
strDriver As
String
Dim
strAttributes As
String
Dim
intRet As
Long
strDriver =
"Microsoft Access Driver (*.mdb)"
&
Chr
$(
0
)
strAttributes =
"DSN=MS Access Perso"
&
Chr
$(
0
)
intRet =
SQLConfigDataSource
(
Me.hWnd
, ODBC_CONFIG_DSN, strDriver, strAttributes)
End
Sub
Il faut ajouter à votre projet les références : - Microsoft OLE DB Service component 1.0 Type Library (oledb32.dll) - Microsoft ActiveX Data Object 2.x Library
Pour créer une nouvelle connexion :
Private
Sub
Command1_Click
(
)
Dim
DataOLE As
New
MSDASC.DataLinks
Dim
MaConn As
ADODB.Connection
On
Error
GoTo
Command1_Click_Error
Set
MaConn =
DataOLE.PromptNew
MsgBox
MaConn.ConnectionString
Exit
Sub
Command1_Click_Error
:
MsgBox
"Error "
&
Err
.Number
&
" ("
&
Err
.Description
&
")"
Err
.Clear
End
Sub
Pour éditer une connexion existante :
Dim
ret As
Boolean
ret =
DataOLE.PromptEdit
(
MaConn) '-- MaConn est un objet ADODB.Connection
MsgBox
MaConn.ConnectionString
En utilisant jet et ADOX (installés par défaut sous XP)
Cocher la référence : Microsoft ADO Ext 2.x for DDL and Security
Sub
CreerBASE
(
)
'Creer une base ACCESS par ADOX
Dim
NewBase As
ADOX.Catalog
Dim
NewTable As
ADOX.Table
Set
NewBase =
New
ADOX.Catalog
NewBase.Create
"Provider=Microsoft.Jet.OLEDB.4.0;"
&
_
"Data Source=c:\base.mdb;"
&
_
"Jet OLEDB:Engine Type=5;"
Set
NewTable =
New
ADOX.Table
With
NewTable
.Name
=
"Table1"
.Columns.Append
"Champ1"
, adInteger
.Columns
(
"Champ1"
).Attributes
=
adColNullable
.Columns.Append
"Champ2"
, adWChar
, 50
End
With
NewBase.Tables.Append
NewTable
Set
NewTable =
Nothing
Set
NewBase =
Nothing
End
Sub
Attention il conviendra d'intégrer une gestion d'erreur.
Bien qu'ADO ne fournisse pas de méthode agissant sur la structure du fichier mdb, il est possible d'utiliser JRO (Jet Réplication Object)
Pour cela ajouter une référence Microsoft JRO à vote projet et utiliser la syntaxe suivante :
Dim
jro As
jro.JetEngine
Set
jro =
New
jro.JetEngine
jro.CompactDatabase
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\MaBase.mdb;Jet OLEDB:Database Password=test"
, _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\MaBaseCompactee.mdb;Jet OLEDB:Engine Type=4;Jet OLEDB:Database Password=test"
En utilisant DAO 3.6
Cocher la référence : Microsoft DAO 3.6 Object Library
Sub
CreerBaseDAO
(
)
Dim
oDAO36 As
New
DAO.DBEngine
Dim
oBase As
DAO.Database
Dim
oTable As
DAO.TableDef
'Création base
Set
oBase =
oDAO36.CreateDatabase
(
"c:\tmp\Mabase.MDB"
, ";LANGID=0x0409;CP=1252;COUNTRY=0"
, 64
)
'Création d'une table
Set
oTable =
oBase.CreateTableDef
(
"Table1"
)
oTable.Fields.Append
oTable.CreateField
(
"Champ1"
, dbInteger)
oTable.Fields.Append
oTable.CreateField
(
"Champ2"
, dbText, 50
)
oBase.TableDefs.Append
oTable
oBase.Close
End
Sub
Ce code permet d'afficher toutes les tables et champs d'une base de données, ceci peut entre pratique si l'on veux connaitre sa base.
Ce code fonctionne 100 % avec des bases ACCESS.
Rajoutez la référence à référence Microsoft ActiveX Data Object 2.X
'
' Utilise la référence Microsoft ActiveX Data Object 2.X ..
'
'Tout d'abord il faut deux ListBox
'Tables : qui va avoir toutes les Tables
'Champs : qui va avoir tous les champs d'une table donne
'
Dim CNX As ADODB.Connection
Dim Schema As ADODB.Recordset
Dim DBPath As String
Private Sub Form_Load()
DBPath = "c:\tmp\mabase.mdb"
'tout d'abord il faut bien évidement ouvrir une connexion avec la base de donne
ACS_Connect
'Affiche les tables
ViewTables
End Sub
'Connexion avec une base de donnee
Public Sub ACS_Connect()
Set CNX = New ADODB.Connection
CNX.Provider = "Microsoft.Jet.Oledb.4.0"
CNX.ConnectionString = DBPath 'Le de ta base de donnee
CNX.Open
End Sub
'Recuperation et affichage des tables dans Tables, cette procedure
Public Sub ViewTables()
Set Schema = CNX.OpenSchema(adSchemaTables)
Do Until Schema.EOF
If Schema!TABLE_TYPE = "TABLE" Then
Tables.AddItem Schema!TABLE_NAME
End If
Schema.MoveNext
Loop
Schema.Close
End Sub
'Maintenant lorsqu'on clique sur une table (dans le listbox Tables), on affiche les champs
'dans le Listbox Champs
Private Sub Tables_Click()
Champs.Clear
Set Schema = CNX.OpenSchema(adSchemaColumns)
While Not Schema.EOF
If Schema!TABLE_NAME = Tables.Text Then
Champs.AddItem Schema!COLUMN_NAME
End If
Schema.MoveNext
Wend
Schema.Close
End Sub