Problème Dictionary avec parcours bases mdb

cs_JMO Messages postés 1854 Date d'inscription jeudi 23 mai 2002 Statut Membre Dernière intervention 24 juin 2018 - 22 janv. 2007 à 21:01
cs_JMO Messages postés 1854 Date d'inscription jeudi 23 mai 2002 Statut Membre Dernière intervention 24 juin 2018 - 23 janv. 2007 à 10:58
 Bonsoir à tous,


Attention, comme souvent, certains (dont moi) le rappellent ...
un peu plus de précision dans l'énoncé du problème,
avec moi, vous allez être servi.

Après tri chronologique de x bases .mdb, situées dans un répertoire spécifique, 
<?xml:namespace prefix = v /??><v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><v:stroke join=""></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path></v:shapetype>


j'ouvre celles-ci pour trier (toujours chrono) certaines tables.





Dans chaque table, je vais parcourir, un champ nommé '"jobid".


Je ne selectionne que les "jobid" commençant par "ALES", "BOUR" et "PNEU" et,
 les dates d'éxécution (début et fin).

Ex:
champ "jobid"     champ "datedéb"    champ "datefin"
ALES001J          31/12/2006 hh:mm   31/12/2006 hh:mm
PNEU001J          31/12/2006 hh:mm   31/12/2006 hh:mm
BOUR005D          31/12/2006 hh:mm   31/12/2006 hh:mm
ALES008M          31/12/2006 hh:mm   31/12/2006 hh:mm
BOUR008M          31/12/2006 hh:mm   31/12/2006 hh:mm
<?xml:namespace prefix v ns "urn:schemas-microsoft-com:vml" /??><v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600">Mon problème, dans un premier temps, consiste à ne conserver que

 le dernier passage de chaque job (donc, pas de doublon).

Vous l'aurez compris:
- pour le jobid "journalier" ALES001J, logiquement, il doit se trouver dans la 1ère base et 1ère table;
- pour un jobid "hebdo", "mensuel", "annuel", "à la demande", je dois donc parcourir les bases et
  tables pour trouver la première occurrence.
strSite Left(Rst("Jobid"),4)<?xml:namespace prefix o ns = "urn:schemas-microsoft-com:office:office" /??>

strName = Mid(Trim(Rst("Jobid")),5,3)

avec Rst("DateDebut") & " | " & Rst("DateFin")

Tous les strSite n'ont pas obligatoirement en commun le strName.

Dès qu'un jobid est trouvé, il faut mémorisé son nom (key) et sa date d'exécution (item), pour faire 
un exit de la recherche de ce jobid sur les autres bases.
 

Codant en vbs (le mot qui fâche), je pense que l'object Dictionary convient à cette gymnastique de keys et d'items,

mais, hélas pour moi, je ne maitrise pas du tout l'objet et ses méthodes !!!

Mon souhait final est de créer une nouvelle base, appelée à être le référentiel (update journalier en 2007).

Jobid, PNEU, ALES, BOUR, ----
001J, Date deb / date fin, Date deb / date fin,  , ----
050D,  , Date deb / date fin,  , ----
120M,  ,  , Date deb / date fin, ----
Etc...,  ,  ,  
 

Ci-dessous, mon toussotement bordélique, et erroné,  de l'objet DicoJcls.

Le tri chronologique de mes bases et tables est, lui, opérationnel (vérifié avec .txt).

J'ai omis les constantes internes d'ADODB.

Je vous remercie, déjà, pour cette lecture, quelque peu soporifique !!!

 

Ma question pourrait être:

- l'objet Dictionary est-il le mieux approprié ???

- et si oui, comment l'utiliser !!!

Le hic se trouve dans la function ReadBase.
==================================================
Const PathMDB = "D:\Archivage"
'Déclaration des Objets et Variables
Dim Usines
Usines = Array("PNEU","ALES","BOUR")

Dim fso, dossier, fichiers, fileItem, DicoJcls, Db, Rs
Dim fichier, i, j, t, imax, z, valeur, cible, result, strAccess
Dim bpermute, cprovisoire
imax = 0

'Création Dictionnaire pour les jobs
Set DicoJcls = CreateObject("Scripting.Dictionary")

DicoJcls.RemoveAll 'supprime tous les éléments du Dictionary
DicoJcls.CompareMode = VBBinaryCompare

Set fso = CreateObject("Scripting.FileSystemObject")
Set dossier  = fso.GetFolder(PathMDB)
Set fichiers = dossier.Files

'début de l'énumération des fichiers
For Each fichier In fichiers    If Left(fichier.Name, 6) "DIA7LM" And UCase(Right(Fichier,3)) "MDB" Then
       Set fileItem = fso.GetFile(fichier)
   
       imax = imax + 1
       ReDim Preserve Tableau(2, imax)
       Tableau(1, imax) = Fichier.Name
       Tableau(2, imax) = FileItem.DateLastModified

       '--- Tri chronologique des fichiers (des + récents aux + anciens) ---
       Do
       Valeur = 0
       For i = 1 To imax - 1
           If CDate(Tableau(2, i)) < CDate(Tableau(2, i + 1)) Then
              For z = 1 To 2
                  Cible = Tableau(z, i)
                  Tableau(z, i) = Tableau(z, i + 1)
                  Tableau(z, i + 1) = Cible
              Next
           Valeur = 1
           End If
       Next
       Loop While Valeur = 1
    End If
Next

If imax=0 Then MsgBox "Repertoire vide - abandon du traitement" : WScript.Quit

'Fichier tempry pour vérif fichiers/tables
'Dim ObjTextStream : Set ObjTextStream = Fso.OpenTextFile("D:\DICTIONARY.txt", 2, True)

'Pour chaque base mensuelle (de la + récente à la + ancienne), recherche des tables journalières
For i = 1 To imax
    'Connexion base
    Set Db = CreateObject("ADODB.Connection")
   
    strAccess = "DRIVER={Microsoft Access Driver (*.mdb)}; DBQ=" & PathMDB & Tableau(1, i)
    Db.Open(StrAccess)
    Set Rs = Db.OpenSchema(adSchemaTables)
     
    ReDim TableJour(0)

    Do Until Rs.EOF
   
       If Left(Rs.Fields("TABLE_NAME").Value, 13) = "JobsPresents_" Then
          ReDim Preserve TableJour(UBound(TableJour) + 1)
          TableJour(UBound(TableJour)) = Rs.Fields("TABLE_NAME").Value
       End If
       Rs.MoveNext
    Loop
    'MsgBox UBound(TableJour) & vbTab&TableJour(UBound(TableJour)-1)

    '--- Tri chronologique des tables ---
    bpermute = True                      
    Do While bpermute = True              
       bpermute = False                  
       For t = 1 To UBound(TableJour) - 1             
           If TableJour(t) < TableJour(t + 1) Then
              cprovisoire = TableJour(t)      
              TableJour(t) = TableJour(t + 1)     
              TableJour(t + 1) = cprovisoire  
              bpermute = True
           End If
       Next
    Loop
    'MsgBox UBound(TableJour) &vbCrLf& TableJour(UBound(TableJour))

    'Ouverture des bases et tables (triées chronologiquement)
    For j = 1  To UBound(TableJour)
        'ObjTextStream.Write j & Space(5) & Tableau(1, i) & Space(5) & TableJour(j) &vbCrLf 
        Call ReadBase(TableJour(j), strAccess, Usines, DicoJcls)
       
    Next   
    Rs.Close
Next
Db.Close

'MsgBox DicoJcls.Count

Set Rs = nothing
Set Db = nothing
Set DicoJcls = nothing
Set fileItem = nothing
Set fichiers = nothing
Set dossier  = nothing
Set fso = nothing

WScript.Quit

'------------------------------------------------
'------------------------------------------------
Function ReadBase(MaTable, StrAccess, Usines, DicoJcls)
'MsgBox MaTable & vbCrLf& StrAccess &vbCrLf& DicoJcls.Count,,"Vérif variables ReadBase"
Dim Rst, OldList, k

Set Rst = CreateObject("ADODB.Recordset")
Rst.CursorType = adOpenForwardOnly  
Rst.LockType = adLockReadOnly   
Rst.Open "SELECT Jobid, DateDebut, DateFin FROM " & MaTable & " ORDER BY Jobid ",strAccess
    
If Rst.EOF = False Then
   Rst.MoveFirst
   Do While Not Rst.EOF
      Dim strName, strSite
      strSite = Left(Rst("Jobid"),4)
      strName = Mid(Trim(Rst("Jobid")),5,3)
     
      For k = 0 To UBound(Usines)
          If strSite = Usines(k) Then
             'MsgBox Usines(k) & vbCrLf& Rst("Jobid"),,"vérif site"
    
             Select Case strName
                    Case "WAI"
                    Case "SVD"
                    Case "IQS"

                    Case Else
                    'ici on a donc strSite = ALES ou BOUR ou PNEU
                   
                    'MsgBox "Nbre éléments DicoJcls : " & DicoJcls.Count &vbCrLf& _
                    '       "Rst(Jobid):  " & Rst("Jobid")   &vbCrLf& _
                    '        DicoJcls(Mid(Rst("Jobid"),5)),,"Vérif AVANT test Exists"
                           
                           
                         If Not DicoJcls.Exists(Rst("Jobid")) Then
                            MsgBox "key: " & Rst("Jobid") &vbCrLf& Rst("Jobid") & " | " & Rst("DateDebut") & " | " & Rst("DateFin") _
                                  ,,"N''EXISTE PAS          CREATION"
                            DicoJcls.Add DicoJcls.Item(Rst("Jobid")), Rst("Jobid") & " | " & Rst("DateDebut") & " | " & Rst("DateFin")
      
                         else
                            OldList = DicoJcls.Item(Rst("Jobid"))
                            DicoJcls.Item(Rst("Jobid")) = OldList & "," & DicoJcls.Item(Rst("Jobid")) & " | " & Rst("DateDebut") & " | " & Rst("DateFin")
                           MsgBox Mid(Rst("Jobid"),5) &vbCrLf& Rst("Jobid"),,"EXISTE DEJA"

                           'Vérification keys
                            'Dim aKeys, AllKeys, u
                            'aKeys = DicoJcls.Keys
                            'For u = 0 To UBound(aKeys)
                            '    AllKeys = AllKeys & vbCrLf & aKeys(u)
                            '    MsgBox aKeys(u),,"Vérif aKeys(u)"
                            '    MsgBox AllKeys,,"Vérif AllKeys"
                            'Next
'  
'                           'Vérification items
                            Dim aItems, AllItems, v
                            aItems = DicoJcls.Items
                            For v = 0 To UBound(aItems)
                                AllItems = AllItems & vbCrLf & aItems(v)
                                MsgBox aItems(v),,"Vérif aItems(v)"
                                MsgBox AllItems,,"Vérif AllItems"
                            Next   
     
 'erreur : clé déjà associée à un élément de cette collection                      
                            'DicoJcls.Add DicoJcls.Item(Mid(Rst("Jobid"),5)), Rst("Jobid") & " | " & Rst("DateDebut") & " | " & Rst("DateFin")
                    End If
    
            End Select

      End If
      Next
      Rst.MoveNext
   Loop
End If
Rst.Close    
Set Rst = Nothing
End Function
 <v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"></v:shapetype>

</v:shapetype>

Merci pour vos suggestions.

jean-marc

5 réponses

cs_caramelmou Messages postés 56 Date d'inscription jeudi 25 décembre 2003 Statut Membre Dernière intervention 23 avril 2008 3
23 janv. 2007 à 00:27
Je ne sais pas si j'ai bien compris ce que tu veux faire:
S'il s'agit de rechercher la dernière occurence d'un job qui peut-être présent dans plusieurs table en se basant sur sa date d'execution (qui est le champ date_debut ou date_fin ) ,  il me semble plus simple d'ajouter les enregistrements de toutes les tables dans une seule sur laquelle tu ferais une requete SQL, quelque chose comme

TRANSFORM Max(date_debut) AS Maxdate
SELECT Mid([JobId],5) AS Job FROM maTable
GROUP BY Mid([JobId],5) PIVOT Left([JobId],4);

Comme ça c'est Jet qui cherche la derniere occurence (qui evite les doublons), qui te met les colonne usines (le PIVOT), etc...
Mais je suis pas sur d'avoir bien compris comment tes données étaient enregistrées ...

Dr.T
0
cs_JMO Messages postés 1854 Date d'inscription jeudi 23 mai 2002 Statut Membre Dernière intervention 24 juin 2018 27
23 janv. 2007 à 05:56
 Bonjour à tous,

 Bonjour caramelmou ,
je ne souhaite pas créer une base intermédiaire dans laquelle j'irai écrire 
plus de 300 fois 
ALES001J   datedeb   datefin
ALES001J   datedeb   datefin
.... et ce pour tous les jobs alors que seul le 1er recordset m'interesse (d'où le tri de mes bases)

je vais regarder du côté des instructions SQL pour tester l'existence de mon champ"jobid"  parcouru
dans ma base "referentielle". Pour chaque job, s'il n'existe pas, je copie.....
Ce qui implique de bloquer ma base référence pendant toute la recherche dans mes bases et tables mensuelles. 

Merci quand même.

jean-marc
0
cs_caramelmou Messages postés 56 Date d'inscription jeudi 25 décembre 2003 Statut Membre Dernière intervention 23 avril 2008 3
23 janv. 2007 à 10:22
Ok!  l'instruction SQL pour inserer les données d'une table TABLE dans une table TABLE_REF en évitant les doublons sur job_ID  est du type

INSERT INTO TABLE_REF( JobId, .. les autres champs... )
SELECT JobId, .. les autres champs...
FROM TABLE LEFT JOIN TABLE_REFON TABLE .JobId = TABLE_REF.JobId  WHERE (((table_ref.JobId ) Is Null));

Sinon pour inserer chaque table (solution precedente) c'est juste
INSERT INTO TABLE_REF( JobId, .. les autres champs... )
SELECT JobId, .. les autres champs... FROM TABLE
Mettre 300 lignes dans une table intermediaire n'est pas vraiment un probleme, ce qui me parait potentiellement dangereux dans ton systeme, c'est de se baser sur la valeur FileItem.DateLastModified pour trier chronologiquement les bases Access : il suffit de compacter ou d'ouvrir une base Access (même sans modifier les données, simplement en cliquant sur une table par exemple) pour que la valeur DatelastModified soit changée

Dr.T
0
cs_caramelmou Messages postés 56 Date d'inscription jeudi 25 décembre 2003 Statut Membre Dernière intervention 23 avril 2008 3
23 janv. 2007 à 10:50
Re... Pardon la syntaxe pour l'insertion dans ton cas c'est

strSQL="INSERT INTO TABLE_REF(JobId,...) SELECT JobId,... FROM TABLE_SRC IN 'C:\TEST\TEST.mdb'"
cnn.execute strSQL

ou 'C:\TEST\TEST.mdb' est ta base source et Cnn une connection ouverte sur la base qui contient la table_ref
Malheureusement le JOIN avec une table externe ne marche pas: pour la premiere solution, il faut importer d'abord la table source dans la base qui contient la table de reference
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_JMO Messages postés 1854 Date d'inscription jeudi 23 mai 2002 Statut Membre Dernière intervention 24 juin 2018 27
23 janv. 2007 à 10:58
 Re,

Merci pour toutes ces infos. Je testerai, at home, ce soir.
Dans un premier temps, je vais incrémenter ma base "référence" à partir des bases mensuelles 2006. Quand ce sera ok, mon script passera tous les jours en parcourant simplement la base mensuelle en cours et la table J-1.
Je n'aurai plus cette notion de DateLastModified, qui est aléatoire.

jean-marc
0
Rejoignez-nous