Requête SQL en VBA avec liaison odbc

Bonjour,

J'ai utilisé MS Query pour effectuer une liaison ODBC et une requête entre plusieurs tables afin de pouvoir analyser les données dans Excel.

J'ai l'impression que MS query est quelque peu limité dans les requêtes alors j'aimerais les insérer en VBA afin de pouvoir lui passer des paramètres provenant de mon fichier Excel.

les paramètres pour la connexion ODBC sont les suivants :

DSN=Visual FoxProTables;UID=;;SourceDB=d:\temp\2015;SourceType=DBF;Exclusive=No;BackgroundFetch=Yes;Collate=Machine;Null=Yes;Deleted=Yes;

Comment faire la connexion en VBA ? et surtout comment insérer ma requête en VBA ?

Merci d'avance pour votre aide

Katia

Bonjour Katia,

On peut aussi établir une liaison ADO directement vers les fichiers dbf et faire toutes (ou presque) les requêtes Sql dont on a besoin (jointure, agrégation, ...)

Ci-joint en exemple une appli (fonctionnelle) qui gère des fichiers dbf (en création/lecture/modification).

Il y a un module "DBF" qui contient l'ensemble des requêtes SQL de l'appli pour montrer diverses possibilités (CREATE, INSERT, UPDATE, DELETE, SELECT, ...), et c'est non exhaustif de ce qu'il est possible de faire.

Je pense qu'avec ces exemples, il sera possible de transposer à ton besoin.

Pierre

PS: pour ce fichier exemple la première ouverture du fichier avec activation des macro crée les fichiers dbf.

841resahotel-dbf.xlsm (136.53 Ko)

Merci pour ta réponse

Concernant la liaison ADO, j'ai vu que tu avais ce code

' ***** REQUETEUR *********************************************************************************
Function Query(Requete As String, Optional Rep As String = "") As Long
Dim Cnx As Object, Rst As Object
Dim Col_SQL As Integer, i As Long, j As Integer

    On Error GoTo errhdlr
    If Rep = "" Then Rep = ActiveWorkbook.Path
    Set Cnx = CreateObject("ADODB.Connection")
    Cnx.Open "Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=" & Rep & ";"

    If Left(Requete, 6) = "SELECT" Then
        Set Rst = CreateObject("ADODB.Recordset")
        Rst.Open Requete, Cnx, adOpenStatic
        Query = Rst.RecordCount
                Col_SQL = Rst.Fields.Count - 1
        If Not Query = 0 Then
            ReDim Ent(Col_SQL)
            For i = 0 To Col_SQL
                Ent(i) = Rst.Fields(i).Name
            Next i
            ReDim RcdSt(Col_SQL, Query - 1)
            ReDim StRcd(Query - 1, Col_SQL)
            Rst.MoveFirst
            RcdSt = Rst.GetRows
            For i = 0 To Query - 1
                For j = 0 To Col_SQL
                    If Not IsNull(RcdSt(j, i)) And Not RcdSt(j, i) = "" Then
                        StRcd(i, j) = RcdSt(j, i)
                    End If
                Next j
            Next i
        End If
    Else
        Cnx.Execute Requete
        Query = 0
    End If

    Cnx.Close
    Set Cnx = Nothing
    Exit Function

errhdlr:
    If Not Rst Is Nothing Then
        If Rst.State = adStateOpen Then Rst.Close
    End If
    Set Rst = Nothing

    If Not Cnx Is Nothing Then
        If Cnx.State = adStateOpen Then Cnx.Close
    End If
    Set Cnx = Nothing
    Query = -1
    MsgBox (Err.Description)
End Function

Est-ce que je dois reprendre la totalité de ce code pour faire la liaison avec mes fichiers DBF ? comment je définis le chemin des fichiers ?

Merci d'avance

Katia

Bonjour,

En effet quelques explications ne sont jamais inutiles.

La "Function Query" que je me suis écrit me sert de "couteau suisse". C'est ce qui établit la connexion et qui renvoie les données.

Je l'utilise par exemple depuis soit une autre function (pour les Select), soit une sub (pour les autres type de requêtes).

Et ça évite de réécrire les mêmes lignes de code à chaque requête.

L'appel est simple, je lui passe 2 arguments : la chaine de requête et le répertoire des fichiers.

Par ex : Get_Affichage = DBF.Query(Requete, Rep)

(le répertoire est optionnel, par défaut il se base sur le répertoire du fichier Xl)

En retour, pour les Select, j'obtiens un entier long (le nombre d'enregistrements trouvés) et un jeu de données, qui est contenu dans 2 tableaux de recordset :

* soit dans RcdSt dimensionné en : colonne, ligne

* soit dans StRcd dimensionné en : ligne, colonne (c'est utile par exemple pour alimenter directement un combobox ou un listbox)

Pour reprendre l'exemple précédent la function Get_Affichage est appelée depuis la sub Graphe (module "Graphique"), le nombre d'enregistrements est récupéré dans ma variable lig et des données sont exploitées dans la sub DessinLigne, dans les variable C1 = RcdSt(2, index) et C2 = RcdSt(3, index)

Sinon, pour les .dbf, ce qui est important à définir ce sont 2 choses (cf. module "Commun"):

* la définition précise de la structure du dbf (dans l'exemple les constantes Table1 et Table2). A noter Xl ne lit que 2 types de données : du texte et des integer (utile pour les Create)

* la définition précise des entêtes du dbf (dans l'exemple les constantes Table1_head et Table2_head)

Ces constantes servent lors des update, des insert et des create. (cf dans l'exemple pour l'utilisation)

Voilà dans les grandes lignes. Ça pourrait très probablement être optimisé, mais je trouve que c'est déjà efficace et relativement simple à mettre en œuvre.

A noter : ça fonctionne bien avec Office 2013, mais j'ai constaté que Office 2016 preview ne connait pas (encore?) le driver : Microsoft dBASE Driver (*.dbf)};DriverID=277

(j'espère que ce sera fonctionnel dans la version définitive)

Bonne journée,

Pierre

Merci pour toutes les explications.

J'ai pu faire la connexion à l'aide de la requête suivante:

Public cN As ADODB.Connection
Public rs As ADODB.Recordset
Public Sub conNect()
    Set cN = New ADODB.Connection
    dbPath = Path
        cN.ConnectionString = "Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=d:\temp\data\2015;Exclusive=No;"
    cN.Open
End Sub

Maintenant, j'aimerais reprendre mes requêtes qui sont dans MS Query afin de la mettre en VBA. Mais étant donné que c'est une requête assez longue, je n'arrive pas à comprendre comment structurer la requête.

Voici ma requête

SELECT adresses.ad_societe, 
adresses.ad_nom, 
adresses.ad_prenom, 
document.do_nodoc, 
document.do_type, 
document.do_date1, 
document.do_paye, 
document.do_net,
document.do_tva,
document.do_pmt,
document.do_montant - document.do_pmt 
FROM adresses,  document
WHERE adresses.ad_numero = document.do_adr1 
AND ((document.do_type=$17) OR (document.do_type=$20))
AND(document.do_paye<>1)
UNION 
SELECT adresses.ad_societe,
adresses.ad_nom, 
adresses.ad_prenom, 
document.do_nodoc, 
document.do_type, 
document.do_date1, 
document.do_paye,
-document.do_net,
-document.do_tva,
document.do_pmt,
-document.do_montant + document.do_pmt 
FROM adresses,  document
WHERE adresses.ad_numero = document.do_adr1 
AND (document.do_type=$22)
AND(document.do_paye<>1)

Peux-tu m'aider pour la structure ?

Avec mes habitudes de travail, j'écrirais un truc du genre :

dim Requete as string
Requete = "SELECT A.ad_societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " D.do_net, D.do_tva, D.do_pmt, (D.do_montant - D.do_pmt) AS mt " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  ((D.do_type=$17) OR (D.do_type=$20)) AND(D.do_paye<>1) " & _
            " UNION " & _
            " SELECT A.ad_societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " -D.do_net, -D.do_tva, D.do_pmt, (-D.do_montant + D.do_pmt) AS mt2 " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document AS D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  (document.do_type=$22) AND (document.do_paye<>1) "

Pour les $17, $20 et $22, si ce sont des variables il faudrait écrire par exemple :

" WHERE  ((D.do_type=" & variable_dollar17 & ") OR (D.do_type=" & variable_dollar20 & " )) AND(D.do_paye<>1) " & _

(même chose pour $22)

Enfin, en fonction des données et des résultats attendus il faut peut être utiliser LEFT JOIN ou RIGHT JOIN (?)

(après, il y a probablement d'autres syntaxes qui donneraient un résultat identique)

Tu me dira si j'ai bon


ps : j'ai un doute avec UNION est-ce que ce serait pas mieux avec plutôt UNION ALL?

Parfait. Merci beaucoup.

Je vais pouvoir transformer mes autres requêtes.

Je pourrais effectivement convertir les 17, 20 et 22 en variable.

Je vais remplacer le union par le union all, je l'avais fait pour une autre requête et j'ai oublié de modifier celle-ci.

Donc maintenant j'ai ceci:

Private Sub Workbook_Open()
Dim Debiteurs_ouverts As String
Debiteurs_ouverts = "SELECT A.ad_societe as Societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " D.do_net, D.do_tva, D.do_pmt, (D.do_montant - D.do_pmt) AS mt " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  ((D.do_type=17) OR (D.do_type=20)) AND(D.do_paye<>1) " & _
            " UNION ALL " & _
            " SELECT A.ad_societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " -D.do_net, -D.do_tva, D.do_pmt, (-D.do_montant + D.do_pmt) AS mt2 " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document AS D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  (document.do_type=22) AND (document.do_paye<>1) "

module1.conNect
Set rs = New ADODB.Recordset

rs.Open Debiteurs_ouverts, cN

i = 1
While Not rs.EOF
        For j = 1 To rs.Fields.Count - 1
            Feuil1.Cells(i, j) = rs(j - 1)
        Next
i = i + 1
rs.MoveNext

Wend

End Sub

Pour afficher les en-têtes de colonnes, je fais comment ?

Si je veux exécuter plusieurs requêtes à l'ouverture du fichier, je répète l'opération ci-dessus et je change juste le nom de la feuille excel dans lequel je veux afficher le résultat ?

Un grand merci pour ton aide.

Ok, parfait!

pour les entêtes, il suffit d'invoquer un rs.fieds.name comme ceci

Dim nb_col As Integer

...

rs.Open Debiteurs_ouverts, cN
nb_col = rs.Fields.Count
For j = 0 To nb_col - 1
    Feuil1.Cells(1, j+1).Value = rs.Fields(j).Name
Next j
rs.movefirst
i = 2
While Not rs.EOF
    For j = 0 To nb_col - 1
        Feuil1.Cells(i, j+1) = rs(j)
    Next
    i = i + 1
    rs.MoveNext
Wend

Pour les autres requêtes, en effet une simple référence à Feuil2, Feuil3, etc ... c'est tout simple.

Pierre

Merci beaucoup.

Mon code est le suivant :

Private Sub Workbook_Open()

Dim Debiteurs_ouverts, Creanciers_ouverts As String
Dim nb_col As Integer

Debiteurs_ouverts = "SELECT A.ad_societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " D.do_net, D.do_tva, D.do_pmt, (D.do_montant - D.do_pmt) AS mt " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  ((D.do_type=17) OR (D.do_type=20)) AND(D.do_paye<>1) AND(D.do_period<>1)" & _
            " UNION ALL " & _
            "SELECT A.ad_societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " (-D.do_net), (-D.do_tva), D.do_pmt, (-D.do_montant + D.do_pmt) AS mt2 " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  (D.do_type=22) AND(D.do_paye<>1) "

Creanciers_ouverts = "SELECT A.ad_societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " D.do_net, D.do_tva, D.do_pmt, (D.do_montant - D.do_pmt) AS mt " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  ((D.do_type=44) OR (D.do_type=43)) AND(D.do_paye<>1) " & _
            " UNION ALL " & _
            "SELECT A.ad_societe, A.ad_nom, A.ad_prenom, D.do_nodoc, D.do_type, D.do_date1, D.do_paye, " & _
            " (-D.do_net), (-D.do_tva), D.do_pmt, (-D.do_montant + D.do_pmt) AS mt2 " & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " WHERE  (D.do_type=47) AND(D.do_paye<>1) AND(D.do_period<>1) "

module1.conNect
Set rs = New ADODB.Recordset

rs.Open Debiteurs_ouverts, cN
nb_col = rs.Fields.Count
For j = 1 To nb_col - 1
    Feuil1.Cells(1, j).Value = rs.Fields(j).Name
Next j
rs.MoveFirst
i = 2
While Not rs.EOF
    For j = 1 To nb_col - 1
        Feuil1.Cells(i, j) = rs(j - 1)
    Next
    i = i + 1
    rs.MoveNext
Wend

End Sub

Par contre j'ai un décalage dans les en-tête de colonne, il ne m'affiche pas la colonne ad_societe. Une raison ?

De plus, comment faire en sorte que le champ date s'affiche au format date ? Je dois passer par une variable ?

Comme j'ai 7 ou 8 requêtes à insérer. Est-ce que je les insères toutes dans la même procédure ? ou est-ce que je fais une procédure dans laquelle j'insère toutes mes requêtes (enfin si c'est possible.) ?

Je crois qu'après toutes ces infos, je dois pouvoir me débrouiller enfin je l'espère

Encore merci pour ton aide et ta rapidité !

Oui, j'avais édité mon code précédent : il faut dire :

For j = 0 To nb_col - 1
    Feuil1.Cells(1, j+1).Value = rs.Fields(j).Name

Pour tes requêtes suivantes, c'est possible de faire comme tu l'indiques. Après chaque écriture sur une feuille, je mettrais bien un

'Ecriture feuil1
Set rs = Nothing
rs.Open Creanciers_ouverts, cN
'Ecriture Feuil2 ...

Pour finir de toute façon par un

Set rs = Nothing

Pour les dates on peut faire un truc genre :

if j = 5 then Feuil1.Cells(i, j) = format(rs(j - 1), "dd/mm/yyyy")

Merci beaucoup. Je vais essayer de me débrouiller avec toutes ces infos.

Salut,

J'ai une requête assez longue (plusieurs union all). Le nombre de "& _" dans une requête me semble limité. Est-ce possible de simplifier la requête ci-dessous ?

"SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
            "dt.dl_compte, dt.dl_montant, dt.dl_tva_mnt" & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero " & _
            " WHERE  ((D.do_type=17) OR (D.do_type=20)) AND(D.do_paye<>1) AND(D.do_period<>1) AND (dt.dl_compte Like '3000.%')AND (dt.dl_tva_inc<>$1) " & _
            " UNION ALL" & _
            "SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
            "dt.dl_compte, (dt.dl_montant-dt.dl_tva_mnt) as montant, dt.dltva_mnt" & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero " & _
            " WHERE  ((D.do_type=17) OR (D.do_type=20)) AND(D.do_paye<>1) AND(D.do_period<>1) AND (dt.dl_compte Like '3000.%')AND (dt.dl_tva_inc=$1) " & _
            " UNION ALL" & _
            "SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
            "dt.dl_compte, (-dt.dl_montant), (-dt.dl_tva_mnt)" & _
            " FROM adresses AS A " & _
            " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 " & _
            " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero " & _
            " WHERE  (D.do_type=22) AND(D.do_paye<>1) AND(D.do_period<>1) AND (dt.dl_compte Like '3000.%')AND (dt.dl_tva_inc<>$1) " & _
            " UNION ALL" & _
            "SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
            "dt.dl_compte, (-dt.dl_montant+dt_dl_tva_mnt), (-dt.dl_tva_mnt)" & _
            " FROM adresses AS A INNER JOIN  document As D ON A.ad_numero = D.do_adr1 INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero" & _
            " WHERE  (D.do_type=22) AND(D.do_paye<>1) AND(D.do_period<>1) AND (dt.dl_compte Like '3000.%')AND (dt.dl_tva_inc=$1)"

Merci d'avance pour ton aide

Bonjour,

En effet la requête est simple^^!

Plusieurs points à noter :

* en VBA les jointures imbriquées nécessitent des parenthèses,

* attention aux espaces, il faut écrire par exemple : "...) AND (truc...", et non : "...)AND(truc..."

* pour les caractères de continuité, effectivement le nombre est limité, il suffit donc de scinder la chaine.

Ce qui peut donner un truc genre :

Dim S As String
' ...
    S = "SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
                " dt.dl_compte, dt.dl_montant, dt.dl_tva_mnt" & _
                " FROM ((adresses AS A " & _
                " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 )" & _
                " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero )" & _
                " WHERE ((D.do_type=17) OR (D.do_type=20)) AND (D.do_paye<>1) AND (D.do_period<>1) AND (dt.dl_compte Like '3000.%') AND (dt.dl_tva_inc<>$1) " & _
                " UNION ALL"

    S = S & " SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
                " dt.dl_compte, (dt.dl_montant-dt.dl_tva_mnt) as montant, dt.dltva_mnt" & _
                " FROM ((adresses AS A " & _
                " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 )" & _
                " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero )" & _
                " WHERE ((D.do_type=17) OR (D.do_type=20)) AND (D.do_paye<>1) AND (D.do_period<>1) AND (dt.dl_compte Like '3000.%') AND (dt.dl_tva_inc=$1) " & _
                " UNION ALL"

    S = S & " SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
                " dt.dl_compte, (-dt.dl_montant), (-dt.dl_tva_mnt)" & _
                " FROM ((adresses AS A " & _
                " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 )" & _
                " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero )" & _
                " WHERE (D.do_type=22) AND (D.do_paye<>1) AND (D.do_period<>1) AND (dt.dl_compte Like '3000.%') AND (dt.dl_tva_inc<>$1) " & _
                " UNION ALL"

    S = S & " SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
                " dt.dl_compte, (-dt.dl_montant+dt_dl_tva_mnt), (-dt.dl_tva_mnt)" & _
                " FROM ((adresses AS A " & _
                " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 )" & _
                " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero )" & _
                " WHERE (D.do_type=22) AND (D.do_paye<>1) AND (D.do_period<>1) AND (dt.dl_compte Like '3000.%') AND (dt.dl_tva_inc=$1)"

' ...
    rs.Open S, cN

Tu me diras si j'ai bon

PS : j'ai juste un doute pour les jointures est-ce que la parenthèse fermante ne doit pas intégrer le where? (tu testeras ...)

ça fonctionne.. presque

Le 3ème et 4ème Select ne sont pris en compte.

J'ai fait les tests requêtes après requête et c'est ok pour le select 1 et 2.

Pour le 3ème et 4ème, quelque chose ne joue pas.

Dès que le type 22 est sélectionné, j'ai une erreur d'automation.. J'ai essayé de simplifier la requête et l'erreur semble venir de dt.dl_tva_inc. j'ai essayé de faire une requête en affichant seulement ce champ mais il reste vide.

Dans la table, il contient les données 1 ou 2. et là impossible de l'afficher.

Juste 2 questions (vu que je connais pas le contenu de tes tables) :

1/ est-ce que le $ ne serait pas de trop? : (dt.dl_tva_inc=1) plutôt que (dt.dl_tva_inc=$1)?

2/ dans tes Like est-ce que le point n'est pas de trop? : (dt.dl_compte Like '3000%')plutôt que (dt.dl_compte Like '3000.%')?

Sinon je ne vois pas bien où est le bug, la syntaxe me semble bonne, enfin je crois(?)

Dans ton 2ème Select tu as un : dt.dltva_mnt

est-ce qu'il faudrait pas plutôt : dt.dl_tva_mnt

Avec ou sans le $, ça ne fonctionne pas.

avec ou sans le . dans le like, le problème est le même.

Ci-joint les fichiers detail et document

43dbf.zip (5.21 Ko)

Ok,

Pour commencer, je ne dispose pas de FoxPro, je lis donc tes fichiers avec Excel.

* Ok pour les (dt.dl_compte Like '3000.%') avec le point, la colonne semble être interprétée par excel comme du texte

* en revanche je mettrai quand même (dt.dl_tva_inc=1) sans le $, la colonne semble être numérique.

Et je remplacerai AND (dt.dl_tva_inc<>1) par AND NOT (dt.dl_tva_inc=1)

Ensuite, je note que Excel lit la valeur de DO_PAYE et de DO_PERIOD en tant que booléenne (VRAI ou FAUX), j'essayerai bien de remplacer (D.do_paye<>1) par (D.do_paye<>'VRAI') et (D.do_period<>1) par (D.do_period<>'VRAI')

ou même (D.do_paye<>1) par (D.do_paye='FAUX') et (D.do_period<>1) par (D.do_period='FAUX')

(je suppose que dans la table 0=faux 1=vrai?)

(sans oublier le : dt.dl_tva_mnt au lieu du dt.dltva_mnt) (1 occurrence)

Souhaitant que ça se débloque ...

Merci pour ton aide. J'ai fais les corrections.

ça ne résout pas mon problème, mais par contre je pense avoir trouver d'où il provient.

Dans ce code, on doit interpréter les montants en négatif et c'est ça qui pose problème. Est-ce la bonne méthode de mettre un - devant le champ ?

" SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
                " dt.dl_compte, (-dt.dl_montant), (-dt.dl_tva_mnt)" & _
                " FROM ((adresses AS A " & _
                " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 )" & _
                " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero )" & _
                " WHERE (D.do_type=22) AND (D.do_paye<>1) AND (D.do_period<>1) AND (dt.dl_compte Like '3000.%') AND NOT (dt.dl_tva_inc=1) " & _
                " UNION ALL" & _
                " SELECT A.ad_societe as Société, A.ad_nom as Nom, A.ad_prenom as Prénom, D.do_nodoc as Numéro, D.do_type as Type, D.do_date1 as Date, " & _
                " dt.dl_compte, (-dt.dl_montant + dt_dl_tva_mnt), (-dt.dl_tva_mnt)" & _
                " FROM ((adresses AS A " & _
                " INNER JOIN  document As D ON A.ad_numero = D.do_adr1 )" & _
                " INNER JOIN  detail As DT ON D.do_numero= dt.dl_numero )" & _
                " WHERE (D.do_type=22) AND (D.do_paye<>1) AND (D.do_period<>1) AND (dt.dl_compte Like '3000.%') AND (dt.dl_tva_inc=1)"

Ah, peut être qu,il vaudrait mieux les multiplier par moins1 du genre :

Dl_mnt* -1

Rechercher des sujets similaires à "requete sql vba liaison odbc"