IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Access Discussion :

[VBA][DAO] Update via Delete + Add : Astuces ?


Sujet :

Access

  1. #1
    Membre du Club

    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 61
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 66
    Points : 65
    Points
    65
    Par défaut [VBA][DAO] Update via Delete + Add : Astuces ?
    Bonjour à tous.
    Je travaille sur une appli frontale ayant une base IMAGE sur HP3000 via ODBC32.

    Je dois Updater des champs d'une table qui sont des "Sort Items" dans la base Image; ces champs ne sont pas modifiables directement via dt.update; il faut Deleter l'enregistrement pus le reécrire avec la valeur modifiée.

    Etant "feignant" sur le code et n'ayant pas envie de réecrire une procédure pour chaque table, voyez vous une solution maline ?

    Plusieurs solutions sont envisageables, vu de ma petite culture Access:

    1 - Utilisation d'une table "locale" Access copie de la base Image; vidage; ajout des enregistrements voulus; modifs data (en local, pas de pb); sup des enregistrements de la table ODBC; ajouts de ceux de la table locale dans la table ODBC.
    2 - Dim de variables correspondantes aux champs, stockage du record ODBC dans les variables, modif de la variable, delete du record ODBC et ADD à partir des variables mémoires.

    La 1ére méthode me pose le soucis de la sécurité de la transaction, comment être sûr que les 5 enregistrements concernés ont bien été mémorisés / détruits / ajoutés quand on utilise des requetes ? (je ne connais pas le moyen de sécuriser la chose); par contre elle n'est pas lourde en code.

    La 2éme méthode pose le soucis de la perso du code (un peu long) à chaque table à traiter de la sorte; a moins de trouver une méthode "générique" de stockage dans un tampon (pour modif) d'un enregistrement (énumération des champs ??).

    Merci de vos lumières et toutes mes félicitations aux contributeurs de ce site qui aident les développeurs occasionnels isolés comme moi.

    Philippe.

  2. #2
    Rédacteur/Modérateur
    Avatar de loufab
    Homme Profil pro
    Entrepreneur en solutions informatiques viables et fonctionnelles.
    Inscrit en
    Avril 2005
    Messages
    12 081
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Entrepreneur en solutions informatiques viables et fonctionnelles.
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2005
    Messages : 12 081
    Points : 24 726
    Points
    24 726
    Par défaut
    Bonjour,

    Le DAO ne fonctionne qu'avec le moteur JET pour ODBC il faut utiliser ADO.

    Cordialement,

  3. #3
    Membre du Club

    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 61
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 66
    Points : 65
    Points
    65
    Par défaut
    J'ai oublié de préciser : je suis en Access 97.
    Dabs l'aide d'Access, on parle de ODBC Direct qui ne passe pas par Jet, et de ODBC qui passe lui par Jet ....

    Comment on reconnait un "lien" ODBC Direct ??

    Merci.

  4. #4
    Membre du Club

    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 61
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 66
    Points : 65
    Points
    65
    Par défaut
    Ayant regardé rapidement DAO et ADO, je crois pouvoir dire que j'attaque actuellement mes bases Images via ODBC en DAO, si j'ai tout compris. Et il me semble comprendre que ADO est arrivé après Access97.

    Merci.

  5. #5
    Nouveau membre du Club
    Inscrit en
    Avril 2006
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 27
    Points : 29
    Points
    29
    Par défaut
    Bonjour.

    Selon moi, il ne faut pas supprimer tous les enregistrements de la table reliee par ODBC. Il ne faut supprimer que ceux qui sont a modifier. Si Access plante, il vaut peut etre mieux mettre les donnees a remplacer ou a supprimer dans une table intermediaire.

    Dans le cas ou il y a plusieurs tables a toucher, pourquoi ne pas les lister dans une table speciale qui les passe en revue ? Pour chaque enregistrement de la table (pour chaque table referencee), il y a une suite d'actions. Des que la suite d'actions est terminee pour une table, on passe a l'enregistrement suivant de la table listant les tables a traiter et on lance a nouveau les differentes actions.

    Cdlt.
    Jeannot2.

  6. #6
    Membre du Club

    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 61
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 66
    Points : 65
    Points
    65
    Par défaut
    Il est sous entendu qu'on ne supprime QUE les enregistrements à modifier; il n'est pas question de vider la table. L'ordre de grandeur est de UN enregistrement à modifier parmis quelques milliers, mais cette modification (Update) suppose un Delete suivi d'un Add des données modifiées et donc stockées quelque part par là avant le Delete.
    Toute ma question concerne en fait le stockage de l'enregistrement avant son delete. L'idéal serait d'avoir une fonction qui, quelle que soit la table, puisse faire la mémo, le Delete, puis le Add en lui passant la valeur à chercher, le champ à modifier et son futur contenu .... Mais bon, je ne vois pas bien comment.

    J'avais pensé parcourir les champs de la table et leur type moyennant un for ... each, puis stocker les valeurs dans des variables, mais comment fait-on pour déclarer des variables dont le type est dans une variable ??

    t="String"
    Dim a as contenu(t) .... !t ??

    Merci de votre aide ...

  7. #7
    Expert éminent sénior

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2004
    Messages
    9 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2004
    Messages : 9 501
    Points : 32 311
    Points
    32 311
    Par défaut
    Bonjour

    Dans ta base locale access, il te faudrait une table possédant la même structure que la table source.

    La première étape consite à stocker le (les) enregistrements à modifier dans cette table, puis à faire un delete sur la table source et enfin un add. Enfin, si le add s'est bien passé (propriété recordsaffected<>0 de l'objet querydef ou database), il faut vider la table "temporaire"

    A chaque démarrage de l'appli, vérifier que la table temporaire est vide. Si ce n'est pas le cas, proposer à l'utilisateur d'insérer les données (en les sélectionnant avec des case à cocher par exemple).

  8. #8
    Nouveau membre du Club
    Inscrit en
    Avril 2006
    Messages
    27
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 27
    Points : 29
    Points
    29
    Par défaut
    En ce qui concerne la recherche d'enregistrements dans une table j'utilise toujours DAO :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    dim Tb as recordset
     
    sub xxxx
    set tb=currentdb.openrecordset("matable",dbopendynaset)
    if tb.eof=true then
    else
    tb.movefirst
    do while tb.eof=false
    if tb!champ=valeur then
    action a mener (copie de donnees, recuperation de donnees etc)
    else
    end if
    tb.movenext
    loop
    end if
    end sub
    tb.close
    Ce genre de programme marche sous Access 97.

    Tu peux copier des donnees d'une table a l'autre, d'une requete a une table....

    Par contre, un petit soucis, suppression de la ligne que tu ne veux plus. en general j'utilise une requete suppression mais uniquement apres avoir modifie la valeur d'un champ sur l'enregistrement que je veux supprimer pour demander a cette requete suppression de ne me supprimer que l'enregistrement contenant la valeur que j'ai moi meme demande au programme de saisir. Car tu ne peux pas supprimer des enregistrement a partir d'une requete de suppression s'il y a des liens entre plusieurs tables dans cette requete. Or, tu dis qu'il n'est pas possible de modifier une valeur dans ta table ODBC.
    Il doit y avoir un autre moyen que je n'utilise pas.

    Cdlt.
    Jean.

  9. #9
    Expert éminent sénior

    Avatar de Tofalu
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Octobre 2004
    Messages
    9 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Octobre 2004
    Messages : 9 501
    Points : 32 311
    Points
    32 311
    Par défaut
    Bonjour

    Je ne suis pas vraiment d'accord avec votre mode de recherche. Pourquoi ne pas filtrer des le départ le contenu du recordset en utilisant une requête paramétrée ? C'est beaucoup plus performant que de parcourir toute une table.

  10. #10
    Membre du Club

    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 61
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 66
    Points : 65
    Points
    65
    Par défaut
    Finalement, après avoir commencé la déclaration d'autant de variable que de champ, et en ouvrant la table filtrée sur les records désirés via un

    dim dt as recordset
    set dt="select * from table where code='TOTO';",dbopendynaset

    do until dt.eof()
    etc ...

    je me suis dit que j'aurais un peu de mal à retrouver l'enregistrement courant après un mémo / delete / add pour faire un Movenext.

    Donc j'ouvre 2 fois ma table :
    - Une fois filtrée pour lecture des records voulus et delete
    - Une fois full acces pour Add

    et du coup, la mémo devient simple : (j'ecris le code de tete, il est au boulot).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    ' xx6 est le champ à modifier, ici en constante, passé en param 
    dim dt as recordset,dt2 as recordset
    set dt="select * from table where code='TOTO';",dbopendynaset
    set dt2="table",dbopendynaset
     
    dt.movefirst
    do until dt.eof()
     dt2.addnew
     ' mémo des data dans nouvel enregistrement
     for i = 0 to dt.fields.count
      dt2(i)=dt(i)
     next i
     ' ecriture valeur à modifier
     dt2("XX6")="20070101"
     dt.delete
     dt2.update
    loop
    Finalement, c'est assez compact, applicable facilement à n'importe quelle table sans énumérer les champs et on peut même passer en paramètre le nom du champ à modifier, sa valeur, le nom de la table et les critères de sélection (clause SQL)...

    Bien sur, la recopie des données avant suppression fonctionne uniquement si les champs de DT et DT2 sont dans le même ordre, ce qui est le cas ici car DT est un select all de la table et DT2 la table elle même.

    Et encore une fois, c'est en exposant ici le problème que j'entrevois la solution la plus élégante ..

    A moins que encore + compact ... ??

    Merci de votre participation et @ + !

  11. #11
    Membre du Club

    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 61
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 66
    Points : 65
    Points
    65
    Par défaut
    Ah, j'oubliais, faire le Delete avant l'Update, sinon, on peut se retrouver avec des problèmes de Violation de Cléfs primaire, ce qui m'est arrivé, car je voulais faire l'update avant le Delete, par sécurité.

    On doit pouvoir cadrer le tout dans une transaction Workspace, avec un begintrans et un commit, pour sécuriser ....

    Est-ce possible avec une table attachée ODBC ?

    Bonne soirée.

  12. #12
    Membre du Club

    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Âge : 61
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 66
    Points : 65
    Points
    65
    Par défaut Solution Universelle (!) à un Update non directement possible
    Bonjour.

    Code définitif qui permet de faire un Update là où on ne peut pas via la méthode Update sur des tables attachées ODBC avec des SortsItems ou des SearchItems.

    Principe : dans les commentaires.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    Sub dt_update(table As String, filtre As String, champ As String, valeur As Variant)
    '
    ' table     : Table lu, deletée et modifiée
    ' filtre    : condition permettant de sélectionner les enr à modifier
    '               attention : si critère String  : cod_art='toto'
    ' champ     : nom du champ dont la valeur doit être modifiée
    ' valeur    : Nouvelle valeur du champ précité
    '
    ' on ouvre 2 fois la table :
    ' une fois au travers d'une requete qui filtre les enregistrements à traiter pour mémo / delete
    ' une fois en direct pour l'écriture
     
    Dim instsql As String
    Dim i As Byte
    'Dim t As String, x As String
    Dim db As DATABASE
    Dim dt As Recordset, dt2 As Recordset
     
    instsql = "select * from " & table & " where " & filtre & ";"
     
    Set db = DBEngine.Workspaces(0).Databases(0)
    ' sélection pour copie et delete
    Set dt = db.OpenRecordset(instsql, DB_OPEN_DYNASET)
    ' pour écrire
    Set dt2 = db.OpenRecordset(table, DB_OPEN_DYNASET)
    dt.MoveFirst
    Do Until dt.EOF
        ' mémo
        dt2.AddNew
        For i = 0 To dt.Fields.Count - 1
            dt2(i) = dt(i)
        Next i
        ' modif champ
        dt2(champ) = valeur
        ' delete ancien
        dt.Delete
        dt2.Update
        dt.MoveNext
    Loop
     
     
    End Sub
    Cela mérite-t-il la FAQ ??
    Merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 25
    Dernier message: 03/05/2007, 16h40
  2. [VBA-W] Impossible de lancer une macro via AddIns.Add
    Par massif dans le forum VBA Word
    Réponses: 1
    Dernier message: 06/09/2006, 16h52
  3. INSERT/UPDATE via DBLink
    Par Wilk dans le forum Oracle
    Réponses: 1
    Dernier message: 15/03/2006, 15h51
  4. [VBA/Excel] Formule via macro
    Par UNi[FR] dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 18/10/2005, 16h11
  5. Evenement sur UPDATE, INSERT, DELETE
    Par papouAlain dans le forum Langage SQL
    Réponses: 6
    Dernier message: 23/12/2004, 15h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo