Requête SQL - problème date - where - récupération celllule

rcan7412

XLDnaute Occasionnel
Bonjour,

Je cale depuis des heures sur un problème de requête sql qui emploie un critère de date.

L'application doit extraire d'un fichier DBF, des données.
Je souhaiterais que les données extraites soient limitées en fonction du critère suivant :
DATESOR (champ date de la table de donnée) soit vide ou supérieur à la valeur date stockée dans la cellule nommée "DateSortie" de la feuille "Start" (cellule E13).

J'avais compris que la date des requêtes était au format américain (mm/dd/yyyy).
J'ai essayé plein de choses mais je n'y arrive pas.

Je joins en annexe le fichier avec le code VBA et le fichier des dossiers (normalement format dbf mais renommé en xls pour l'import sur le forum) et un fichier de données (idem dbf > xls)

Voici le code

Cible = "SELECT CODE,LIBELLE,FOURNI,DATEE,COMPTE,VALACHAT,TYPE,CUMUL,DUREA,PCOMPTA,DATSOR FROM " & laBase & " ORDER BY DATEE ;"

Je voudrais que ceci fonctionne :

WHERE DATSOR < DateSort OR DATSOR is null

DATESOR est le champ qui contient la date dans le fichier de données.
DateSort est la variable qui renvoie le contenu de la cellule nommée "DateSortie" de la feuille "Start" (cellule E13)

Si quelqu'un pouvait m'aider, car je désespère.

Merci d'avance

VB:
Private Sub CommandButton1_Click()
'bouton d'importation pour le processus d'import du fichier comptes.dbf et appel de la procédure d'import de lign.dbf
Application.ScreenUpdating = False
Dim Cn As ADODB.Connection
Dim Rs As ADODB.Recordset
Dim chemin As String, Cible As String, laBase As String
Dim Fld As ADODB.Field
Dim i As Integer
Dim DateSort As Date


If ComboBox1.ListIndex = -1 Then Exit Sub

chemin = ComboBox1.List(ComboBox1.ListIndex, 1)
laBase = "IMMOS.dbf"
DateSort = Format(Range("DateSortie"), "MM/DD/YYYY")



'efface la feuille comptes

Sheets("ImmoCiel").Select
    Columns("A:k").Select
    Range("k1").Activate
    Selection.ClearContents


Range("A1").Select


Set Cn = New ADODB.Connection
Cn.Open _
"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=" & _
chemin & ";"

'WHERE DATSOR < DateSort ORDER BY DATEE  WHERE DATSORT > DateSort"

Cible = "SELECT CODE,LIBELLE,FOURNI,DATEE,COMPTE,VALACHAT,TYPE,CUMUL,DUREA,PCOMPTA,DATSOR FROM " & laBase & " ORDER BY DATEE ;"



Set Rs = New Recordset
Rs.Open Cible, Cn, adOpenKeyset, adLockOptimistic

For Each Fld In Rs.Fields
i = i + 1
Sheets("ImmoCiel").Cells(1, i) = Fld.Name
Next Fld


Do While Not Rs.EOF
Sheets("ImmoCiel").Range("A2").CopyFromRecordset Rs
Loop

        
Rs.Close
Cn.Close

Sheets("Start").Select
Range("DOS") = ComboBox1
Range("REPDOS") = ComboBox1.List(ComboBox1.ListIndex, 1)
Range("CODEDOS") = ComboBox1.List(ComboBox1.ListIndex, 2)

Calculer
Application.ScreenUpdating = True
End Sub
 

Fichiers joints

tatiak

XLDnaute Barbatruc
Bonjour,

Avec des DBF, il faut que la date à tester soit au format entier-long

Pour moi j'écrirais donc plutôt :
VB:
Dim DateSort As Long
...
DateSort = clng(Range("DateSortie").value)
....
Requete = " SELECT ...blabla ... WHERE DATSOR < " & DateSort & " OR DATSOR is null"
Pierre
 

rcan7412

XLDnaute Occasionnel
Bonjour Pierre,

Merci pour ta suggestion que j'ai testée. Hélas elle ne fonctionne pas (voir image).
La procédure s'arrête sur :
Rs.Open Cible, Cn, adOpenKeyset, adLockOptimistic

Une idée sur l'erreur ?

Rodolphe
 

Fichiers joints

tatiak

XLDnaute Barbatruc
Bonjour,

Voici une démo fonctionnelle de liaison entre excel et un fichier dbf :

  • à l'ouverture du fichier, création d'une table
  • bouton pour insérer quelques données comprenant des dates
  • bouton pour lire les données comprises entre les 2 dates indiquées en F1 et G1

Dans la requête, les dates limites sont au format entier-long

Pierre

Extrait du code :
VB:
Sub lire()
Dim deb As Long, fin As Long, Req As String, S As String
Dim T As Variant, i As Integer

    deb = ActiveSheet.Range("F1").Value
    fin = ActiveSheet.Range("G1").Value
    Req = "SELECT `Dt`, `Intitule` FROM `Mars2019` " & _
            " WHERE `Dt` BETWEEN " & deb & " AND " & fin & _
            " ORDER BY `Dt` ASC"
    Connect_dbf ActiveWorkbook.Path & "\"
    T = Select_dbf(Req)
    Close_dbf 1
    
    If UBound(T, 1) > 0 Then
        For i = 0 To UBound(T, 1)
            S = S & Format(T(i, 0), "dd/mm/yyyy") & " " & T(i, 1) & vbCrLf
        Next i
    Else
        S = "La table `Mars2019` est vide"
    End If
    MsgBox S
End Sub
 

Fichiers joints

rcan7412

XLDnaute Occasionnel
Merci Pierre pour ta réponse que j'ai testée sur tes fichiers.

En cliquant sur INSERT, je reçois le message d'erreur suivant : Erreur de syntaxe dans l'instruction INSERT INTO.

Pour le reste j'ai essayé de m'inspirer de ton code avec WHERE et BETWEEN et j'ai à nouveau l'erreur " INDEX INTROUVABLE".

Pas évident pour un néophyte en matière VBA :rolleyes:

Rodolphe
 

tatiak

XLDnaute Barbatruc
Testé ma démo sur :
  • PC 64 bits + Office 2016 32bits => Ok
  • PC 32 bits + Office 2007 32bits => Ok
Quelle est ta configuration?
 

tatiak

XLDnaute Barbatruc
Ok, alors faisons du pas à pas :

1ère étape :
* est-ce que dans le même dossier que celui du fichier "Dbase_10mars2019.xlsm" il se crée un fichier "Mars2019.dbf" ?

* si point précédent=ok => écrire dans procédure "Sub Inserer()" (à la place de la ligne Req=...) :
Code:
Req = "INSERT INTO `Mars2019` (`Id`,`Intitule`) VALUES (" & .Cells(i, "A").Value  & ",'" & .Cells(i, "C").Value & "'" & ")"
puis clic sur bouton "Insérer"


* si point précédent=ok => écrire dans procédure "Sub Lire()" (à la place de la ligne Req=...) :
Code:
Req = "SELECT `Id`, `Intitule` FROM `Mars2019`"
puis clic sur bouton "Lire"


* si point précédent=ok => on pourra passer à la 2ème étape

Pierre
 

rcan7412

XLDnaute Occasionnel
Oui à ta première question.

En fait la procédure ne bugge pas si je laisse les enregistrements sur la feuil1 des colonnes ABC.
Mais dès que j'efface cette liste et je clique sur insérer, il met le message d'erreur.

Pour revenir à mon application, tu ne vois pas d'explication pour l'instant ?

Merci de consacrer du temps à mon problème.
 

tatiak

XLDnaute Barbatruc
Ok,
Alors donc tu viens de valider le code de ma démo, dans laquelle n'est pas prévu d'effacement de données, car ce n'est qu'une démo (forcement limitée donc)!

Donc dans ma démo, il y a du code fonctionnel pour, depuis excel :
  • créer un dbf
  • se connecter à un dbf puis fermer la connexion
  • insérer des données, dont des dates
  • lire des données comprises entre 2 dates quelconques.

Est-ce qu'on est d’accord sur ce point?


Maintenant si tu veux t'amuser à effacer des données dans ma démo, il suffit d'écrire dans la procédure Inserer() :
VB:
S = CInt(.Cells(i, "A").Value) & "," & CLng(.Cells(i, "B").Value) & ",'" & .Cells(i, "C").Value & "'"
Est-ce que tu veux bien tester cette modif de ton côté avant qu'on essaye d'aller plus loin?
 

rcan7412

XLDnaute Occasionnel
Je viens de comprendre quelque chose.... désolé mais je suis un peu lourd.
En fait les données du fichier xl (feuil1) vont dans le fichier dbf et par l'inverse.

Je suis tellement branché sur mon application qui va dans l'autre sens.
En fait les données contenues dans mes dbf de doivent pas être implémentées depuis excel.
L'idée est d'extraire des données de ces dbf qui sont gérés par un programme externe.

Je ne sais pas si je suis clair à ce sujet.

Pour ta démo, insérer et lire fonctionne.
 

tatiak

XLDnaute Barbatruc
Oulà!

Reste concentré si tu veux bien, on ne va pas pouvoir avancer sinon!

Pour les besoins de la démo il y a d'abord un transfert d'excel vers dbf pour qu'on puisse lire quelque chose ensuite!

Ensuite, la procédure "Lire()" transfère des données du dbf vers Excel! Dans la démo ce n'est qu'un simple Msgbox, mais on pourrait les écrire dans un onglet quelconque!
cf boucle "For i = 0 To UBound(T, 1)"

Mais je me pose une question, est-ce que tu as bien les épaules pour ce type de projet?
 

rcan7412

XLDnaute Occasionnel
La Msgbox, oui j'avais bien compris.

Soyons clair, je suis expert-comptable et pas programmeur. J'ai suivi en son temps des formations de base en VBA. Ce n'est donc pas mon métier.
Mais j'utilise tous les jours depuis des années des applications excel vba pour analyser les chiffres extraits de mon logiciel comptable dont les données sont stockées dans des tables dbf.

Les codes vba de mes applications, je les ai glané ici et là sur internet et adapté à mes besoins avec l'aide de personnes sur des forums comme celui-ci. Mais je suis loin d'avoir la logique d'un informaticien.

J'espère que ça ne te décourage pas trop, autrement tant pis.
 

tatiak

XLDnaute Barbatruc
Bon, reprenons.

La démo fonctionne donc sur ton PC. Ca peut être une base de réflexion.

Pour revenir cette fois à ton code, on va prendre point par point.
Je te suggère d'effacer le contenu de ta procédure "Private Sub CommandButton1_Click()" en gardant jusqu'à : chemin = ComboBox1.List(ComboBox1.ListIndex, 1)

* peux-tu faire un Msgbox chemin pour voir ce qu'il y a dedans?
Rq : pour se connecter il est impératif que ce chemin soit complet depuis la racine (ex c:\Dossier\Sous-dossier\ ...)
 

rcan7412

XLDnaute Occasionnel
Merci pour ton aide.

Ok voilà, quand je lance la macro, l'userform est chargé et je clique sur le bouton importation des données qui lance la macro en question (effacé le code comme tu le proposais) et j'ai ajouté comme demandé la Msgbox (voir image).
 

Fichiers joints

tatiak

XLDnaute Barbatruc
Ok, donc la connexion peut se faire.

Point suivant à vérifier, c'est l'existence du fichier "IMMOS.dbf" dans ce répertoire

Est-ce qu'il est présent?
 

rcan7412

XLDnaute Occasionnel
Oui oui je confirme que tout fonctionne sans problème quand je ne mets aucun critère de date (where).
J'obtiens l'extraction souhaitée hormis les enregistrements que je voudrais écarter par la requête sql pour éviter de les avoir dans la feuille excel de réception.
J'ai un fichier immos.dbf par client stocké dans des dossiers distincts.
 

tatiak

XLDnaute Barbatruc
Ok, alors je te suggère :
  • de copier/coller le contenu du module Sql de ma démo dans un module quelconque de ton appli
  • d'effacer les procédures Sub Install_Base() Sub Inserer() Sub lire(), et on garde le reste
  • de continuer dans ta procédure "Private Sub CommandButton1_Click()" en modifiant le type de DateSort, soit :
VB:
' ... autre variables déclarées ...
Dim chemin As String, Cible As String, laBase As String
Dim DateSort As Long
Dim T As Variant

    ' ...
    chemin = ComboBox1.List(ComboBox1.ListIndex, 1)
    laBase = "IMMOS.dbf"
    DateSort = CLng(Range("DateSortie").Value)
    
    Cible = "SELECT CODE,LIBELLE,FOURNI,DATEE,COMPTE,VALACHAT,TYPE," & _
            " CUMUL,DUREA,PCOMPTA,DATSOR FROM `" & laBase & "` ORDER BY DATEE ;"
    
    Connect_dbf chemin
    T = Select_dbf(Cible)
    Close_dbf 1
    
    MsgBox "lignes=" & UBound(T, 1) & " colonnes=" & UBound(T, 2)
On doit alors obtenir les dimensions d'un tableau non vide.
Si c'est le cas, on ajoute:
Code:
    Cible = "SELECT CODE,LIBELLE,FOURNI,DATEE,COMPTE,VALACHAT,TYPE," & _
            " CUMUL,DUREA,PCOMPTA,DATSOR FROM `" & laBase & "`" & _
            " WHERE DATSOR <" & DateSort & _
            " ORDER BY DATEE ;"
Quelles sont alors les dimensions obtenues? (en supposant que des données correspondantes existent bien)
 

rcan7412

XLDnaute Occasionnel
Ok, la première partie, j'obtiens bien la message box avec le message : lignes =... et colonnes : ....
Les nombres varient en fonction des dossiers.

Mais quand j'ajoute la seconde cible : Index introuvable
 

tatiak

XLDnaute Barbatruc
Ok, alors on ajoute une nouvelle feuille dans le classeur qu'on nomme "Feuil1", et on reprends le code :
VB:
    Cible = "SELECT CODE,LIBELLE,FOURNI,DATEE,COMPTE,VALACHAT,TYPE," & _
            " CUMUL,DUREA,PCOMPTA,DATSOR FROM `" & laBase & "`" & _
            " ORDER BY DATEE ;"
    
    Connect_dbf chemin
    T = Select_dbf(Cible)
    Close_dbf 1

    If Not UBound(T, 1) = 0 And UBound(T, 2) = 0 Then
        Sheets("Feuil1").Range("A2").Resize(UBound(T, 1) + 1, UBound(T, 2) + 1) = T
    End If
Et on regarde ce qui est dans la colonne devant contenir des dates (en K si j'ai bien compté)
Ce qui serait bien c'est de poster ici un fichier Excel avec uniquement le contenu copié/collé de cette colonne.
 

Discussions similaires


Haut Bas