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

Sondages et Débats Discussion :

[Cours pt-05]Moteur de mise à jour de base de données


Sujet :

Sondages et Débats

  1. #1
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut [Cours pt-05]Moteur de mise à jour de base de données
    >>>> Merci de noter toutes remarques concernant ce cours dans le sujet parallèle : [Cours papyturbo]Commentaires, remarques et suggestions
    -------------------------------------------------------------------------
    Ce cours est la suite
    - du [Cours pt-01][Débutants]Analyse structure base de données simple et
    - du [Cours pt-02][Débutants]Requête avec plusieurs sommes
    - du [Cours pt-03]turbo-formulaire (les bases)
    -------------------------------------------------------------------------
    Le but de cet exercice est de choisir la meilleure méthode pour mettre à jour une base de données (le fichier .mdb contenant les données dans les tables), alors que nous (développeurs) avons
    - développé une nouvelle application,
    - modifié la structure des tables, de leurs indexes, leurs champs et des relations entre tables,
    et que, pendant ce temps là, les utilisateurs ont continué à ajouter des données dans la version précédente.
    Précision : Même si je suis le seul utilisateur d'une application dont je me sers tous les jours, il n'est pas question de modifier l'application avec laquelle je réalise mon travail quotidien : un bug surviendra toujours au pire moment critique, lorsqu'un client t'appelle pour avoir l'info indispensable tout de suite .
    Je conseille donc de développer toujours sur des copies de l'application et des copies de la base de données, puis de faire une installation avec mise à jour de la BDD.

    Nous allons utiliser les éléments suivants, chacun correspondant à un fichier ".mdb" :
    - base de données (tables) à la version 1 : en cours d'utilisation. Nous allons utiliser une copie, pour les tests.
    - base de données (tables) à la version 2 : nouvelle structure, à mettre en production.
    - application, version 2 : à mettre en production, ici par simple copie.
    - le moteur de mise à jour V1 > V2 : une mini-application Access que nous n'utiliserons qu'une seule fois.
    J'ignore l'application, version 1, qui sera écrasée par la copie de l'application, version 2, pendant l'installation.
    À noter, que, dans le zip ci-joint, l'application a été "splittée" en 2, en utilisant l'assistant d'Access (menu Outils > Utilitaires de base de données > Fractionner une base de données), pour séparer toutes les tables, sauf bien sûr, la table [Affaires_Selection] qui doit impérativement être une table locale, propre à chaque utilisateur (sinon, je te laisse imaginer l'embrouille ! )

    Il y a 2 méthodes possibles pour réaliser cette mise à jour :
    méthode #1 : reporter dans la base de données active (V1) toutes les modifications que nous avons mises au point et testées dans la base V2.
    méthode #2 : créer un modèle de base en vidant les tables de la base V2, et transférer dans ces tables vides toutes les données existantes, depuis la base V1.

    Quelle que soit la méthode, il va falloir interrompre les utilisateurs pendant la mise à jour : le moins longtemps possible, of course.
    Une mise à jour très complexe, concernant quelques dizaines de tables, chacune ayant de 100 à quelques dizaines de milliers d'enregistrements, ne dépasse jamais quelques minutes : rarement 5 minutes, à moins que certaines opérations exigent une intervention de l'utilisateur pour faire des choix...

    Je n'ai jamais utilisé la méthode #1, sauf s'il s'agit d'ajouter un seul nouveau champ dans une table, ou une nouvelle table dans la base.
    Le principal argument en faveur de la méthode #2 est que je n'ai jamais été capable de faire une liste exhaustive et complète des modifications apportées à une base de données, dès que ces modifications sont un peu complexes.
    Il y a toujours quelque part un index ou une propriété oubliée...

    Le fonctionnement de la méthode #2 est par contre assez simple dans son principe :
    - nous allons traiter chaque table dans l'ordre des niveaux d'intégrité référentielle (détails ci-dessous),
    - pour les tables sans modifications majeures, une requête ajout (INSERT INTO) va transférer toutes les données de la V1 à la V2,
    - nous allons contrôler les erreurs : essentiellement en comparant le nombre d'enregistrements transférés dans la V2, avec ceux de la table V1.
    S'il en manque, nous ajusterons la requête pour tenir compte de chaque cas, ou nous mettrons en place des transformations plus complexes, avec une table locale intermédiaire, par exemple.
    - nous recommencerons jusqu'à ce que toutes les données soient correctement transférées.
    - nous passerons alors "en production" : installation de la nouvelle application + mise à jour de la base contenant les dernières données réelles.

    Niveaux d'intégrité référentielle :
    Cette notion, rarement mentionnée dans l'aide ou les ouvrages sur les bases de données, est primordiale pour tout transfert de données (mise à jour, synchronisation, extraits...) : nous ne pourrons pas, par exemple, copier les Affaires (niveau 1 d'intégrité) dans la base V2 si nous n'avons pas d'abord transféré tous les Clients (niveau 0).
    La relation d'intégrité entre les tables Clients et Affaires de la V2 nous empêcherait d'ajouter une affaire avec une IdClients qui ne correspond à aucun client dans la table Clients.
    Bien sûr, seules les règles d'intégrité de la base V2 nous concernent : celles de la base dans laquelle nous allons écrire.
    Et, bien sûr toujours, il est impératif de ne jamais rien modifier dans la V1, pour pouvoir revenir en arrière, en cas de problème non prévu.

    C'est pour clarifier cette notion de niveaux que je conseille toujours très vivement de disposer, dans les schémas de relations (menu Outils > Relations...),
    - à gauche, les tables auxquelles n'aboutissent aucune relation, (niveau 0)
    - immédiatement à leur droite, en colonne, les tables qui dépendent des premières par une relation, (niveau 1)
    - continuer ainsi, de la gauche vers la droite, en alignant autant que possible les tables les unes sous les autres, par niveau.
    C'est aussi pour cette raison que j'ai utilisé Excel comme outil de dessin, dans la réponse #31 du cours 01. Ça me permet de mettre clairement en évidence les numéros, comme dans le schéma ci-dessous (qui, attention, ne correspond plus à notre base V2 , mais plutôt à la V1 ) :


    La toute première étape qui consiste à
    - créer une base vierge pour le moteur de mise à jour (fichier SuiviAffaire_MaJ_V1_V2 2006-11-06.mdb),
    - attacher toutes les tables de la V1 et celles de la V2, (Fichier > Données externes > Lier les tables...)
    - différencier les tables en ajoutant le n° de version "_1" ou "_2" derrière chaque nom,
    est faite, dans le zip ci-joint.

    Il va donc falloir pour toi :
    1- utiliser le gestionnaire de tables attachées (Outils > Utilitaires de bases de données > Gestionnaire de tables liées...) pour réattacher les tables correctement, en fonction de ton chemin d'accès,
    2- me corriger (chacun son tour ) en vérifiant que les fichiers ci-joint correspondent bien aux bases de données de la version 1 (en cours d'utilisation) et 2 (celle que nous avons mise au point).
    Note : tu pourras supprimer l'application (fichier SuiviAffaire_App 2006-11-06.mdb) du fichier zip. Elle ne nous intéresse plus, dans le cadre du cours 05. dans les prochains échanges, seul le moteur de mise à jour (fichier SuiviAffaire_MaJ_V1_V2 2006-11-06.mdb) devrait être modifié et zippé.
    3- faire une liste complète des tables de la V2, en indiquant, pour chaque table, le niveau d'intégrité référentielle.
    Fichiers attachés Fichiers attachés
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Citation Envoyé par Papy Turbo
    2- me corriger (chacun son tour) en vérifiant que les fichiers ci-joint correspondent bien aux bases de données de la version 1 (en cours d'utilisation) et 2 (celle que nous avons mise au point).
    J’ai repris toutes les tables de la version 1 avec correction.

    Quelques commentaires sur les tables de la version 1 par rapport à la version 2.
    ‘Personnel’ --> ‘Employé’.
    ‘AvancementEtudeFournisseur’ --> ‘HeurePassee-SectionAffaire-Fournisseur’.
    ‘AvancementEtudePersonnel’ --> ‘HeurePasseee-SectionAffaire-Personnel’.
    ‘Date/Semaine’ --> ‘Date-Semaine’.
    ‘HeureFournisseurAffaire’ --> ‘Fournisseur-SectionAffaire’
    ‘HeurePersonnelAffaire’ --> ‘Personnel-SectionAffaire’.
    ‘HeuresAllouées’ --> HeureAllouees-SectionAffaire’.
    ‘SectionPerFou’ --> Section.

    Joint le fichier : SuiviAffaire_Maj_V1_V2 2006-11-08.zip contenant (pour que nous travaillons sur les mêmes fichiers)
    1- NI_V1.xls : Schéma du niveau d’intégrité référentiel de la version 1.
    2- NI_V2.xls : Schéma du niveau d’intégrité référentiel de la version 2.
    3- SuiviAffaire_BDD_V1.mdb : Base version 1.
    4- SuiviAffaire_BDD_V2.mdb : Base version 2.
    5- SuiviAffaire_MAJ_V1_V2 2006-11-08.mdb : début de la base de mise à jour.
    -------
    Fichiers attachés : SuiviAffaire_Maj_V1_V2 2006-11-08.zip (62,6 ko)
    -------

  3. #3
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Tu vas t'occuper très bientôt des tables qui ont changé de nom, donc très bonne liste.
    La première tâche, pour l'instant, est de créer un modèle de base de données vide et propre, au format des nouvelles tables.
    Il faut donc :
    - conserver une base de données version 2 avec des données dedans, au cas où on aurait encore des tests à faire sur notre application, version 2.
    - utiliser une copie, que nous allons vider.

    Comme je suis flemmard, je n'ai aucune envie de créer une requête pour vider chaque table. Je préfèrerais créer un assistant qui fasse le boulot aussi automatiquement que possible.
    Tu trouveras
    - une requête type, utilisée comme test et pour copier son code SQL dans le code VBA : *** Test suppression données
    - une nouvelle table, locale, intitulée [000 DestinationTables]. Son index est basé sur le niveau d'intégrité de chaque table + le nom de la table. Je suppose que tu devines pourquoi ?
    Les champs de la table devraient être évidents :
    - niveau d'intégrité, J'ai suivi ton schéma NI_V2.xls pour noter les niveaux d'intégrité de chaque table.
    - nom de la table,
    et un nouveau
    - champ DataTable, format Oui/Non, pour distinguer les tables de données des tables dites "de paramètres" ou "de données fixes".
    Les tables "de données" sont celles dont nous allons récupérer les contenus à partir de la version 1.
    Les tables "de paramètres" sont celles dont le contenu ne peut pas être changé par les utilisateurs.
    Exemple :
    À toi de décider si ton application SuiviAffaires permet ou non de créer des nouvelles sections ?
    - si oui, la table Sections est une table de données, comme les autres.
    - si non, tu es le seul à ajouter/supprimer/renommer ces sections et la table Sections de la version 2 doit être laissée telle quelle, avec toutes les sections dedans.
    Tu trouveras également :
    - un formulaire UpdateWizard, qui contient
    - un onglet tabWizard, qui contient 2 pages :
    ... la 1ère page, Nettoyage modèle n'intéresse que nous, les développeurs, pour préparer un beau modèle de base vide.
    ... la 2ème page, Transfert, sera visible lorsque nous enverrons cet "assistant d'installation et mise à jour de la base de données" à notre client. Lui n'aura pas besoin de vider les tables, parce que nous lui donnerons seulement le modèle propre et vide.
    Je sais que tu portes les 2 casquettes, mais il est utile pour tous les autres de bien séparer les tâches "développeur" des tâches "utilisateur/installateur".
    En situation réelle, il sera facile de masquer la 1ère page avant d'envoyer l'assistant à un utilisateur.

    - l'onglet Nettoyage modèle contient un sous-formulaire ssfDestinationTables basé sur la nouvelle table, et un bouton qui vide toutes les tables.
    Le code de ce bouton devrait être clair ?
    La seule particularité est peut être le DoCmd.SetWarnings : permet de supprimer les messages d'avertissement de Jet, lors de l'exécution d'une requête SQL. À maintenir actif pendant le débogage, pour voir et corriger les problèmes, puis à éteindre(False) lorsque le code est correct.

    J'ai également ajouté, dans le module VBA, une référence à DAO, et supprimé la référence à ADO (ActiveX Data Objects), dont nous n'aurons pas besoin. En VBA, voir menu Outils > Références.

    À part cela, le reste devrait être limpide :
    - on travaillera toujours à partir des tables de destination, celles dont les règles (d'intégrité, d'indexation avec/sans doublon, de champs nulls admis/refusés, etc.) devront être respectées,
    - on ne peut vider ces tables qu'en commençant par le dernier niveau d'intégrité. Pause : la raison est évidente ?
    - il reste un mini-bug , à résoudre avant de supprimer les Stop et autres commentaires destinés au débogage.
    Le mini-bug est juste là pour mette en évidence la méthode générale :
    On avance pas à pas, en essayant bêtement de "faire le travail" (vider toutes les tables de données, puis copier leurs contenus...).
    À chaque étape, on lance le processus complet, et on corrige les erreurs au fur et à mesure qu'elles apparaissent.
    Cette méthode plante nécessairement au début, mais elle va beaucoup plus vite que d'essayer de tout prévoir d'avance. Ça sera encore + évident + tard, quand ça va se compliquer...

    Bref, le travail pour toi va consister à
    - réparer le dernier bug qui plante,
    - préparer la prochaine étape : juste un bouton Mise à jour dans le 2ème onglet, qui va transférer toutes les données depuis chaque table de la version 1 dans chaque table de la version 2.
    Tu peux reprendre le modèle de code que j'ai utilisé pour vider les tables, évidemment en inversant l'ordre des tables (c'est bien clair, ça ? )
    En remplaçant le code de la requête SQL de Suppression par une requête Ajout, qui copie toutes les données d'un table V1 dans la même table V2.
    Tu vas avoir des problèmes, ne serait-ce que dès qu'une table aura changé de nom : pitête qu'un nouveau champ dans la table 000 DestinationTables, genre un champ SourceTableName, pourrait résoudre ce 1er problème ?

    N'essaye pas de résoudre tous les problèmes d'un coup : pour l'instant, juste un transfert standard, très générique, qui ne marchera correctement que pour les tables dont les champs n'ont pas changé.
    Rappel : ici, nous avons volontairement fait de profondes modifications à la structure de la base. En temps "normal", seuls un nouveau champ par ci-par là, ou quelques nouvelles tables... nécessiteront un traitement spécial. Mais la plupart des tables ne changent pas d'une version à l'autre.
    Commençons donc avec cette routine générique qui fera le gros des transferts.
    Bon courage.
    Et si tu es bloqué, suffit de crier très fort.

    P.S. : je suis gentil : je ne t'ai pas demandé de faire un Form_Resize du formulaire, de l'onglet, du sous-formulaire... bien que tu saches maintenant faire ça en 2 minutes.
    Parce que c'est juste un outil qui va tourner une seule fois.
    Mais si tu veux faire l'exercice, faut pas te gêner.
    Fichiers attachés Fichiers attachés
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Une initiative : Renommer toutes les tables en mettant le numéro de la table en tête du nom de la table (plus facile et moins de risque lors de la sélection pour ‘gestion des tables liées’). Donc reprise du code ‘Vider les tables de données’.


    Citation Envoyé par Papy Turbo
    À toi de décider si ton application SuiviAffaires permet ou non de créer des nouvelles sections ?
    Normalement elle permet, mais pour l’exemple on peut dire que NON.

    ... la 1ère page, Nettoyage modèle …
    Etape fonctionnelle.

    ... la 2ème page, Transfert,
    Création d’un champ supplémentaire dans la table 000_destinationTables (SourceTableName) pour y rajouter les noms des tables Sources.

    Création d’une requête pour nouveau sous formulaire ‘FUpdateWizard_002_TransfertData’ pour la lecture de la table source et table destination.

    Création d’un sous formulaire ‘UpdateWizard_002_TransfertData’ et insertion dans le 2ème onglet du formulaire ‘UpdateWizard’.

    Dans le 2ème onglet rajout d’un bouton de commande ‘cmdMAJTables ‘ Mise à Jour Tables.

    Puis je suis bloqué ( cause des différents nom de champ dans les tables).
    J’ai envisagé une solution : création d’une table du même style que ‘000 DestinationTables’ mais cette fois avec la liste de tous les champs ??

    Donc avant de continuer je crie très fort !!!

    -------
    Fichiers attachés : SuiviAffaire_MaJ_V1_V2 2006-11-14.zip (29,3 ko)
    -------

  5. #5
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Citation Envoyé par Serge57
    Une initiative
    1ère bonne surprise !
    Ça veut dire que tu commences à être à l'aise, donc continue comme ça.
    Il vaut mieux plein d'initiatives, quitte à te planter : il n'y a que comme ça qu'on apprend !

    Sur ce point, l'inconvénient de mettre le numéro de version avant, c'est que j'aime bien avoir la table version 1 + la même, version 2, + selon les besoins une 3ème table, locale, temporaire, qui porte le même nom.
    Tu verras donc toi même, au bout de quelques essais, ce que tu préfères : version par devant ou par derrière (sur l'air de ...)

    2ème bonne surprise : le redimensionnement des formulaires marche impec ! C'est top, et ça va nous permettre d'ajouter encore des champs à notre "table des tables".

    Diverses retouches :
    J'ai réactivé l'Echo False, au début de Form_Resize : c'est nettement plus agréable,sans le scintillement.

    Par contre, je ne sais pas si on va avoir besoin de 2 copies du sous-formulaire et de la table des tables ?
    Une seule devrait suffire, pourvu qu'on ait tous les champs, et, a priori, inutile d'afficher ça aux utilisateurs de l'installation.
    En tout cas, il faudra qu'ils ne puissent rien modifier.
    On reverra ça plus tard. Pour l'instant, on peut s'en servir pour montrer l'avancement, table par table.

    Dans le code VBA du formulaire, tri des routines : j'ai utilisé la commande de mzTools : Autres utilitaires > Trier les procédures.
    De manière à avoir, en tête, tous les évènements du formulaire, suivis, dans l'ordre, de nos 2 boutons. (hé oui, je suis maniaque !)

    Contrôle d'erreur : comme dans Form_Resize, qui doit impérativement faire un Echo True avant de sortir, nous devrons impérativement, au delà de la phase de débogage, faire un SetWarnings True.
    J'ai donc recopié le code de contrôle d'erreur de Form_Resize, pour être sûr de toujours exécuter cette commande, même si une erreur imprévue se produit.

    Formulaire principal (conteneur) : supprimé le sélecteur d'enregistrement (y a pas d'enregistrements), et les boutons de navigation.

    cmdMAJTables_Click : planté
    Quand on supprime des enregistrements, on commence par le dernier niveau d'intégrité, et on remonte vers le premier.
    Quand on ajoute, ou qu'on modifie des enregistrements, on commence par le niveau le plus bas (0), et on remonte.
    Il faut que cette notion devienne évidente.
    C'est la conséquence logique de l'intégrité : pas d'Affaire qui ne corresponde à aucun Client... donc
    - suppression des Affaires d'abord, puis suppression des Clients,
    - ajout des nouveaux Clients en premier, suivi de l'ajout des Affaires.

    En ce qui concerne notre transfert de données, j'ai rien fait !
    Je suis trop flemmard (je me répète, mais je pense que tout bon développeur est un flemmard qui préfère faire travailler son ordi, plutôt que de faire le travail "a la main") pour
    1- reconnecter les tables une par une, même avec le gestionnaire de tables attachées,
    2- noter tout ce qu'il se passe, et surtout les messages d'erreur.

    Tu trouveras donc un ensemble de classes objet (j'espère que ça te fait peur ) et de modules, dont certaines routines importées directement de la FAQ Access (à consommer sans modération) :
    Dans l'ordre où ils s'exécutent :
    - une macro Autoexec qui lance une routine d'initialisation : App_Init(). Cette routine initialise les objets dont nous avons besoin.
    - un module _Demarrage_Utilitaires qui, comme son nom l'indique, contient les routines de démarrage (App_Init(), et de fin : App_Quit() qui ferme proprement les mêmes objets) + divers utilitaires dont nous aurons besoin,
    - une classe clApplication, qui va servir à créer un objet ThisApp, auquel on va donner toutes les propriétés et les méthodes qu'on ne trouve pas dans l'objet Application d'Access : un nom, un titre, même un journal, etc. selon les besoins...
    - une classe clLog (Log = journal) qui va servir à créer le journal dont dispose notre nouvelle application (objet ThisApp.Log).

    Les codes extraits de la Faq sont déjà commentés dans la Faq.
    Y a t-il besoin de commentaires sur les différences entre un module de classe et un module ordinaire ?
    Disons seulement que je me suis permis d'ajouter des propriétés (Name, Title...) directement en tant que variables Publiques, en tête du module de classe, alors qu'il existe une méthode + lourde, avec Property Get et Property Let...
    Mieux vaut voir les divers cours d'initiation aux classes, dans la rubrique Cours de Développez, entre autres :
    - Création d'une classe de manipulation de chaînes de caractères
    - Tout comprendre à propos des modules de classes sous Access
    - La notion de la classe formulaire Access par l'exemple
    etc.
    Je passe sous silence la classe "Images" de Thierry Gasperment, qui est nettement plus tordue...)


    Il y a déjà une routine pour reconnecter les tables dans la FAQ : Rétablir les liaisons des tables liées après déplacement d'une base fractionnée par Tofalu.
    Celle qui figure dans la classe clApplication, la méthode CheckTablesConnection() fait un poil plus de travail pour automatiser cela, dans le cadre d'une application Access standard (toutes mes applications démarrent par une routine beaucoup plus complexe que celle-là, mais qui fait à peu près la même chose) :
    - elle parcourt les tables,
    - elle ignore les tables locales,
    - elle vérifie si les connexions sont bonnes en essayant d'ouvrir chaque table attachée,
    Dès qu'elle en trouve une dont la connexion est rompue,
    - elle extrait le nom de la base concernée (nous sommes ici connectés à 2 bases distinctes)
    - elle ouvre une boîte de dialogue pour demander où se trouve la bonne base à rattacher,
    - et elle reconnecte toutes les tables qui étaient liées à la même base (ça, c'est le seul point qui m'intéresse en temps que flemmard professionnel )

    Tout ça pour quoi ?
    En dehors de la reconnexion des tables, tu constateras, dans la routine cmdEmptyDataTables_Click() quelques retouches : il y a notamment un journal qui se crée dans le même dossier que l'application, pour noter, soit les erreurs, s'il y en a, soit le bon déroulement de notre mise à jour.
    Je te laisse donc, pour l'instant,
    1- digérer les nouveautés (bon appétit),
    2- appliquer la même méthode à ta routine cmdMAJTables_Click()
    Le but à atteindre :
    - que tout s'exécute, même s'il y a des erreurs,
    - qu'on puisse ensuite ouvrir le journal et voir quelles sont les tables dont les données ne sont pas passées.
    Pour cela, il serait bien de
    1- avoir un On Error Goto qui enregistre les erreurs (Number, Description) dans le journal, avec le nom de la table concernée, puis qui continue quand même (Resume Next),
    2- avec ou sans erreur, dans le journal, après exécution de la requête SQL Ajout, de
    - comparer le nombre d'enregistrements de la table V1 avec celui de la table V2,
    - s'ils sont égaux, OK - TVTB
    - s'ils sont différents : *** erreur !!!

    On verra alors, une par une, comment les traiter (requête spécifique, code...)
    Dans un cas réel, comme je l'ai déjà dit, seules quelques tables seront modifiées et "ne passeront pas" : la méthode avec journal permet de les identifier, sans se préoccuper des autres. C'est le but de cet exercice : te faire gagner du temps à chaque fois que tu recréeras un moteur de mise à jour à partir de ce modèle, pour les prochaines versions de SuiviAffaires, ou autres applis.
    Fichiers attachés Fichiers attachés
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Citation Envoyé par Papy Turbo
    Quand on supprime des enregistrements, on commence par le dernier niveau d'intégrité, et on remonte vers le premier.
    Quand on ajoute, ou qu'on modifie des enregistrements, on commence par le niveau le plus bas (0), et on remonte.
    Il faut que cette notion devienne évidente.
    J’avais compris, mais n’étant pas un virtuose de VBA, (j’ai pas vu ‘.MoveLast’ dans le code), j’avais fait un tri décroissant dans la requête ‘FUpdateWizard_002_TransfertData’ et ça avait l’air de marcher !!!!


    1- digérer les nouveautés (bon appétit),
    mal à l'estomac ! (mais enfin j'ai signé pour ça )


    2- appliquer la même méthode à ta routine cmdMAJTables_Click()

    1- avoir un On Error Goto qui enregistre les erreurs (Number, Description) dans le journal, avec le nom de la table concernée, puis qui continue quand même (Resume Next),
    J’ai appliqué la même méthode .

    2- avec ou sans erreur, dans le journal, après exécution de la requête SQL Ajout, de
    - comparer le nombre d'enregistrements de la table V1 avec celui de la table V2,
    - s'ils sont égaux, OK - TVTB
    - s'ils sont différents : *** erreur !!!
    Pour l’instant aucune table ne passe sont erreur (problème de nom de champ, de table inexistante, ….)

    Ci joint Application avec un embryon de code pour la commande cmdMAJTables_Click ?? pour gestion dans le journal et correction. (c'est une idée de code .
    -------
    Fichiers attachés : SuiviAffaire_MaJ_V1_V2 2006-11-17.zip (66,0 ko)
    -------

  7. #7
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut Encore un poil de POO
    Modifs de notre moteur, dans le désordre :
    - Table 000 DestinationTables : changé le champ IntegrityLevel, de texte en numérique - byte (j'aimerais bien voir une base Access avec + de 255 niveaux d'intégrité !)
    - j'ai bien aimé ta variable PasErreur (sauf qu'elle aurait dû être Booléenne, pas Integer !). Mais je l'ai virée de manière à inclure systématiquement le nombre d'enregistrements source/destination : même s'il y a erreur, je veux savoir si quelque chose passe, et combien. Ce qui pourra révéler un problème d'index unique..., par exemple.
    Et puis, j'ai déjà la réputation d'être trop bavard dans mes commentaires, alors, j'aime bien que mes logs aient les mêmes défauts
    - supprimé la moitié des erreurs (message plus clair dans le nouveau journal, ça aide), en remplaçant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SourceCountRecords = DCount("*", VERSION1 & !TableName)
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SourceCountRecords = DCount("*", VERSION1 & !SourceTableName)
    Un peu de POO, histoire de rigoler les jours de pluie.
    Non, c'est pas pour dire Poo Poo comme un fantôme holywoodien, ni que j'ai fait un gros Poopoo, c'est juste Programmation Orientée Objet.
    J'insiste lourdement : la POO n'est pas un luxe réservé aux "pros". Si tu sais faire des Sub et des Functions dans un module standard, tu sais faire aussi les mêmes dans un module de classe. Quand aux Propety Get / Let / Set (pour les objets), c'est pas sorcier.
    Il y a même, avec mzTools, un assistant qui transforme une variable publique en 2 propriétés Get/Let... (Autres utilitaires > Convertir la variable publique en propriétés...)
    Pour de bonnes bases, voir les cours, déjà cités en réponse #5.
    - J'ai donc complété la classe clLog :
    ... l'évènement Class_Initialize() se déclenche à la création de n'importe quelle classe (déjà vu dans la clase clApplication) : on en profite pour noter une fois pour toutes le chemin d'accès dans une variable locale.
    ... propriétés Path et Name : permettent au programmeur, dans son code, de changer le chemin et/ou le nom du journal, selon ses besoins.
    Remarque 1 : quand on traite des fichiers avec un chemin (path) + un nom (Name ou Filename), je conselle de
    - toujours séparer clairement le chemin du nom, ce qui permet de changer le nom facilement, indépendamment du chemin.
    - systématiquement terminer le chemin par un "\", ce qui permet de trouver le fichier à "Path & Name", en évitant l'erreur si il manque le dernier "\".

    Remarque 2 (POO) : Noter la différence entre ces 2 propriétés du journal (classe clLog) et les propriétés Public ... As ... de la classe clApplication.
    La méthode utilisant les 2 routines Get + Let est la méthode standard.
    Le raccourci qui utilise une simple variable publique est propre à VBA, et ne se retouve généralement pas dans d'autres langages. On retrouvera donc ce raccourci dans tous les langages basés sur VBA : Excel VBA, Visual Basic (VB6), etc.
    Gros avantage de la méthode POO standard , avec Get + Let (+Set pour les propriétés objet), les propriétés des objets deviennent plus "intelligentes" : ici, par exemple, on en profite pour vérifier la syntaxe du chemin (qui doit se terminer par un "\") et l'extension du nom de fichier du journal (".log")
    ... du coup, pour simplifier, n'ayant plus besoin de la propriété Name de l'application, j'ai supprimé cette propriété qui n'était utilisée que pour créer le nom du journal. Remplacée, dans AppInit(), par ThisApp.Log.Name = "..."
    Enfin, pour en finir avec la POO du jour, note que j'aurais pu créer une routine Public Sub DeleteLog(), et une autre DisplayLog(), dans notre module Utilitaires. Allez, j'avoue : j'avais commencé comme ça, avec DisplayLog(). Puis je me suis tapé sur les doigts
    Mais c'est quand même nettement plus élégant, et plus clair pour un autre programmeur qui découvre ton application, de mettre ces 2 routines directement dans l'objet Log, non ?
    ---------------------
    Retour à nos moutons.
    Solution, pour transférer la table Clients :
    - création d'une requête spécifique.
    Astuce, pour les débutants, s'il y en a : dans la fenêtre de création de requêtes d'access, pour insérer d'un coup tous les champs d'une table dans une requête :
    + double clic sur l'en tête de la table, pour sélectionner tous les champs
    + faire glisser le paquet vers les colonnes
    Dès qu'on choisit la table de destination, Access met en face tous les noms de champs qui correspondent, il n'y a plus qu'à compléter les noms qui ne correspondent pas (liste déroulante).
    Ensuite, pour que le "moteur" exécute cette requête,
    - ajout d'un champ dans la table [000 DestinationTables]
    - ajout des nouveaux champs dans les requêtes [FUpdateWizard_001_DestinationTables] et [FUpdateWizard_002_TransfertData]
    Noter que les 2 sont identiques : on simplifiera cela + tard.
    - ajout du nouveau champ dans le sous-formulaire [UpdateWizard_002_TransfertData]
    - code de cmdMAJTables_Click : ajout d'un test - Si une requête est spécifiée, on la lance à la place de notre requête standard.
    Si tu lances maintenant le transfert, il y a une table (sur 12) qui passe bien. Elle est pas belle, la vie ?
    Autrement dit, dans ton cas, il n'y a plus qu'à créer des requêtes spécifiques pour chaque table, et découvrir d'autres problèmes à résoudre...
    Ce qui veut dire que tout ce qu'on a fait jusque là ne sert à rien ? Ca sera pour ta prochaine mise à jour, peut être plus simple que celle la ?
    Fichiers attachés Fichiers attachés
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  8. #8
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Citation Envoyé par Papy Turbo
    Autrement dit, dans ton cas, il n'y a plus qu'à créer des requêtes spécifiques pour chaque table, et découvrir d'autres problèmes à résoudre...
    Aucun souci pour les tables de 1er niveau, mais pour le 2éme niveau ça se complique !!

    L’intégrité référentielle, la référence de certaine liste de choix, (clients, Employes) bloquent l’ajout d’enregistrement.

    Donc
    et découvrir d'autres problèmes à résoudre...
    voilà les nouveaux problèmes .

    Piste pour la référence des listes de choix,
    Donc je ne vois que 3 possibilités pour y arriver.
    1 – Renommer la table « 2-Clients » en « Clients »
    2 - Modifier la zone de liste modifiable pour quelle pointe sur la table « 2-Clients ».
    3 – Créer une copie de la table « 2-Clients » en « Clients » (en table locale).

    Par contre pour l’intégrité référentielle, je n’ai aucune piste. (sauf détruire la relation et la reconstruire ensuite. Mais comment !!!)

    Donc joint table avec mise à jour des tables 1er niveau, et .... .

    -------
    Fichiers attachés : SuiviAffaire_MaJ_V1_V2 2006-11-24.zip (79,9 ko)
    -------

  9. #9
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Youpi, c'est la vraie galère qui commence !

    Avant de mettre le doigt sur une solution, précisons clairement ce que nous ne voulons surtout pas faire :
    détruire la relation et la reconstruire ensuite
    Cette proposition est parfaitement naturelle : tous les "responsables base de données" que je connais, y compris quelques très bons maestros du Client/Serveur sous SQL Server, Oracle et divers ERP... en sont passés par là, et bon nombre le font encore (hou, la honte ! Non, je rigole. C'est la solution normale de facilité, à court terme.)

    Ce que nous voulons : un moteur qui transfère le tout, sans rien perdre : ni aucune donnée, bien sûr, ni aucune "meta-donnée", à savoir l'ensemble des règles et propriétés des tables, des champs, des relations qui décrivent la structure de la base.
    Une fois au point, notre moteur sera xxx fois plus rapide qu'un spécialiste qui
    - enlève les règles d'intégrité,
    - nettoie toute les tables "à la main" (doublons, champs nuls/non nuls, strings vides non autorisés, etc.)
    - remet chaque règle en place, et
    - recommence le nettoyage x fois, jusqu'à ce que toutes les nouvelles règles "passent".

    Pour trouver ce qui coince dans le transfert, on peut :
    - examiner les propriétés de chaque champ et surtout, comparer chaque index, en particulier les indexes uniques, en
    ::: ouvrant les tables V1 et V2 en mode création, côte à côte,
    ::: fenêtre des indexes ouverte et
    ::: clic sur celle de gauche -> clic sur celle de droite...

    Si rien n'est évident :
    - copier un des enregistrements "qui coince" (en l'occurence, n'importe lequel ), à la main, champ par champ, jusqu'à trouver le champ "qui ne passe pas".
    Attention de ne pas recopier ce qu'on voit dans la table source, mais bien de faire un copier/coller du champ source dans le champ destination.
    Sans cette précaution, on aurait pu rater le problème posé par le champ [codepersonnelRP] (légende : "Personnel PROJET") :


    Le piège était particulièrement tordu :
    - table [1_Affaire], champ [codepersonnelRP] : la valeur par défaut est 0 (zéro),
    - on n'a rien mis comme donnée, donc tous les RP sont à zéro !
    - il n'y a aucun employé avec la clé 0,
    - dans la base V1, pas d'intégrité : ça passe.
    - dans la table V2, intégrité : ça coince.
    C'est bien ce qu'on veut : empêcher ce genre d'incohérence.

    Le pire, est que, quand Access essaye d'afficher le nom de l'employé, spécifié par la liste déroulante du champ [codepersonnelRP], il ne trouve aucun employé.
    Dans ce cas, généralement, il n'affiche même pas la valeur '0' de la clé.
    Si on ouvre la base version 1, il n'affiche rien, et on croit à tord, que le champ est vide, c'est à dire : valeur nulle !
    Heureusement pour nous, lorsque la table est attachée et renommée ("1_Affaire"), la liste déroulante ne marche plus et, comme ci-dessus, on voit la valeur "0".

    Il va donc falloir :
    - refaire entièrement ta requête V1_V2_n1_01_Affaires, en y incluant bien tous les champs de chaque table,
    - pour le champ [codepersonnelRP], faire un petit calcul : si valeur = 0, faut coller la valeur 'Null'.

    Je te laisse faire le test + mise au point et, dans la foulée, profiter de notre table Affaires pour tester un problème très courant (peut être le plus courant de tous ?) dans la vie réelle : résoudre les doublons.

    L'exercice consiste, après avoir résolu le problème ci-dessus et correctement transféré nos 4 affaires,
    - ouvrir la table [1_Affaire],
    - comme dans l'image ci-dessus, changer le titre de la dernière affaire, de "Affaire 4" en "Affaire 2",
    - relancer tout le transfert en effaçant le contenu des tables...
    De manière à avoir un doublon sur le titre : c'est permis en V1 (champ mémo, donc non indexé). Pas acceptable en V2 : champ avec index unique.
    Donc, pendant la prochaine exécution, tu dois voir le message d'erreur suivant, pendant le transfert de la table Affaires :
    [...] 1 enregistrements n'ont pas été ajoutés à la table à la suite de violations de clé, [...]
    et, dans le journal, il doit y avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    =========================== niveau 1 ===========================
        Transfert de la table [Affaire] vers la table [Affaires]
    *** Erreur de transfert
        La table source [1_Affaire] contient 4 enregistrements.
        La table destination [2_Affaires] contient 3 enregistrements.
    --------------
    Puis réfléchir au moyen le plus simple de récupérer quand même ce titre en doublon ????
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  10. #10
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    - pour le champ [codepersonnelRP], faire un petit calcul : si valeur = 0, faut coller la valeur 'Null'.
    Ok. Et en plus ça fonctionne.

    profiter de notre table Affaires pour tester un problème très courant (peut être le plus courant de tous ?) dans la vie réelle : résoudre les doublons……
    Puis réfléchir au moyen le plus simple de récupérer quand même ce titre en doublon ????
    Le moyen le plus simple est de modifier les titres pour qu'il ne soient pas identique mais cohérent avec ce qui existe. Donc rajout au début du titre existant .... le champ "codeaffaire" qui lui est toujours pas définition différent.

    - comme dans l'image ci-dessus, changer le titre de la dernière affaire, de "Affaire 4" en "Affaire 2",
    Pour supprimer le doublon:
    1- Création d’une requête pour trouver les doublons. Requête 01_1_DoubonTitreAffaire.J’ai modifié manuellement le type de donnée du champ Titre Affaire (mémo => texte de 255 caractères) de la table affaire, base V1 pour que la requête fonctionne.
    2- Création de la requête 01_2_ModifDoublon pour mis à jour du titre de l’affaire. Concaténation du champ 'codeaffaire' et du 'Titre Affaire' existant. C’est une Idée !!!

    Ensuite, je me suis lancé sur la mise en forme du niveau 2. ET…. M…. . la table « SectionsAffaires » n’existe pas en version 1. Donc il faut la créer !!(la palice).J’ai créé une requête ajout V1_V2_n2_01_SectionsAffairesMais problème (ou pas), la combinaison des 2 tables (sections et affaires) crée des d’enregistrements pas toujours utiles pour la suite….. Mais je n'ai pas trouvé d’autre solution. (par contre j'ai modifié un peu le code 'cmdMAJTables'. problème pour compter des enregistrements sur une table qui n'existe pas')


    Ensuite, je me suis lancé sur la mise en forme du niveau 3, ET… MMM….
    1- Dans la base V1, manque une relation d’intégrité entre table ‘affaire’ et table ‘ HeurePersonnelAffaire’
    2- pas d’idée pour créer un automatisme de transfert !!!.
    -------
    Fichiers attachés : SuiviAffaire_MaJ_V1_V2 2006-11-30.zip (80,8 ko)
    -------

  11. #11
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut Solution des doublons
    Citation Envoyé par Serge57
    J’ai modifié manuellement le type de donnée du champ Titre Affaire (mémo => texte de 255 caractères) de la table affaire, base V1 pour que la requête fonctionne.
    Ce serait trop facile !
    Je répète un des premiers principes à respecter ici : On ne modifie jamais rien dans la base Source !
    C'est même le but de l'exercice.
    Donc, ta solution paraît bonne, sauf que, comme tu as constaté, on ne peut pas détecter les doublons, sur un champ de type Memo.

    La solution que je te propose est différente.
    Une fois bien comprise, elle doit permettre de régler aussi bon nombre d'autres problèmes (champs null/pas null, etc.) du même type.

    Solution Table locale temporaire :
    - importer la structure (sans les enregistrements) de la table d'origine dans le moteur de mise à jour :
    ::: Fichier > Données externes > Importer...
    ::: cliquer sur la base version 1,
    ::: sélectionner la table Affaires,
    ::: clic sur Options >
    ::: sous Importer les tables, choisir Définition uniquement
    ::: OK
    - renommer cette nouvelle table en Affaire_Temp (c'est là que je regrette que nous n'ayons pas conservé les n°s de version derrière le nom de chaque table. Si c'était le cas, on verrait l'une sous l'autre les 3 tables "Affaire" : Affaire_V1 + Affaire_V2 + Affaire_Temp )
    - ajouter (par un copier/coller) le champ Titre de la table V2, dans cette table temporaire.
    Le but de la manoeuvre est d'avoir une table qui contient
    1- tous les champs de la table V1
    2- tous les champs de la table V2 (donc certains champs en double).
    Avec cet outil, on peut tout faire : détecter les doublons, les manipuler, etc.

    Ensuite, une seule requête ne suffira pas : on est obligé d'adapter notre moteur de mise à jour pour qu'il appelle une routine spécifique.
    Cette routine VBA va pouvoir utiliser une ou plusieurs requêtes, et manipuler les données par le code.
    J'ai donc créé un nouveau module initulé SpecificTransferRoutines, dans lequel je colle en vrac (on fera un peu de rangement quand notre moteur marchera correctement) :
    - 2 routines très très spécifiques (BeforeTransfer et AfterTransfer)
    - une première sub/fonctions (CleanupStringDoubles) permettant de traiter les doublons sur un champ texte... (on pourra ensuite en ajouter d'autres du même genre, pour traiter les doublons sur un champ numérique, etc.)

    La bonne nouvelle : ça y est, avec ce nouveau système, nous allons pouvoir traiter tous les cas possibles.
    Lors de la réutilisation de ce moteur, le programmeur pourra :
    1- ne rien faire pour les tables non modifiées : elles sont transférées automatiquement, (c'est le cas le plus fréquent)
    2- créer juste une requête pour les cas où des noms de champ ont changé, (2ème cas le + fréquent : on en a quelques unes dans notre exemple)
    3- pour tous les autres cas, une routine spécifique va pouvoir appeler autant de requêtes que nécessaire, et surtout, appeler des routines 'standard' (réutilisables partout), du même genre que notre CleanupStringDoubles, pour résoudre les cas les plus complexes...

    Cette "routine spécifique" est double : BeforeTransfer et/ou AfterTransfer :
    - si on ne veut pas utiliser le transfert "standard", comme c'est le cas ici, à cause des doublons, on utilise la routine BeforeTransfer, et on renvoie l'argument Cancel = True, pour annuler l'opération de transfert standard.
    - sinon, on peut laisser faire le transfert standard, et juste intervenir après pour peaufiner, grâce à la sub AfterTransfer.
    - et on peut combiner les 3, dans quelques rares cas tout à fait spéciaux...
    Je te laisse regarder ces 2 nouvelles routines, et poser toutes questions si quelque chose n'est pas limpide.

    Traitement des doublons proprement dit :
    - nous avons une table avec les 2 champs : ancien titre + nouveau titre.
    - si nous transférons l'ancien titre dans le nouveau champ, seuls les titres qui ne sont pas des doublons passent.
    - on peut détecter les doublons simplement : le nouveau champ Titre est null.
    - la routine CleanupStringDoubles va parcourir ces doublons et les remplacer par une chaîne unique.
    Citation Envoyé par Serge57
    Concaténation du champ 'codeaffaire' et du 'Titre Affaire' existant. C’est une Idée !!!
    Excellente idée, mon cher Watson. J'avais l'habitude d'utiliser un simple compteur, et de rajouter "-1", "-2", "-3"... derrière chaque doublon.
    Ta méthode me plaît beaucoup, car elle permet d'ajouter un autre champ du même enregistrement, donc résultat plus cohérent, dans certains cas, pour l'utilisateur.
    J'ai inclus les 2 possibilités dans cette nouvelle routine, en spécifiant (ou pas) le nom du champ "code" à ajouter derrière le titre.
    Précision : pour résoudre des doublons, je conseille vivement de garder le texte d'origine devant, et d'ajouter autre chose derrière : après le transfert, dans la nouvelle application, l'utilisateur pourra faire un tri sur les titres (facile, avec les turbo-formulaires ! ), et voir, l'un en dessous de l'autre les doublons d'origine, qu'il pourra alors nettoyer.

    Enfin, il faut maintenant vider les tables temporaires, en plus des tables de destination. J'ai mis
    - le nom de la table temporaire comme nouveau champ, dans notre "table des tables" : [000 DestinationTables],
    - ajouté ce champ aux recordsets des sous-formulaires et aux sous-formulaires eux-mêmes, et
    - complété le code de la routine cmdEmptyDataTables_Click.

    ----------------------------
    Étape suivante : table SectionsAffaires
    Ta méthode marche bien, et elle ne posera aucun problème pour le reste du transfert.
    Mais tu vas te retrouver avec trop de SectionsAffaires : toutes les sections vont apparaître dans chaque affaire !
    Si tu examines les tables de la V1, tu en trouveras 5 qui contiennent des SectionsAffaires, c'est à dire qui contiennent à la fois un codeAffaire et un codeSectionPerFou.
    Si tu ne veux importer que ceux-là, tu dois maintenant pouvoir :
    - intervenir dans BeforeTransfer,
    - lancer autant de requêtes spécifiques que nécessaire pour transférer toutes ces "SectionsAffaires" dans la nouvelle table,
    - bien entendu, dans ce cas, il va y avoir de nombreux doublons, lorsque la même section se retrouve 2 fois pour la même affaire.
    Il n'y a pas besoin de faire autre chose que de les ignorer : on veut chaque SectionAffaire une fois, et une seule fois.
    Fichiers attachés Fichiers attachés
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Tout d’abord, milles excuses pour le retard. Préparations des festivités de fin d’année (il faut tout finir tout de suite….)

    Revenons à notre cours.

    Ca y est, ça se complique drôlement!

    Petite modification dans la fonction « BeforeTransfer » pour le transfert ‘Affaires’ .Je penses qu’il y avait un lancement de la requête « V1_V2_n1_01_Affaires_02" de trop.

    Citation Envoyé par Papy Turbo
    Étape suivante : table SectionsAffaires…… Si tu examines les tables de la V1, tu en trouveras 5 qui contiennent des SectionsAffaires, c'est à dire qui contiennent à la fois un codeAffaire et un codeSectionPerFou.
    Les tables concernées sont :
    1-HeurePersonnelAffaire
    2-HeureFournisseurAffaire
    3-HeuresAllouees
    4-AvancementEtudePersonnel
    5-AvancementEtudeFournisseur
    Pour le transfert, utilisation de la fonction « BeforeTransfer » Voir les requêtes « V1_V2_n2_01_SectionsAffaires_01 à 05 »
    Question : A chaque essai, le champ « IdSectionsAffaires » s’incrémente. Ne peut-on pas le faire toujours commencer à 1 ?? (Solution: Vider la table, puis compiler la base ????)

    Transfert de la table « HeurePersonnel » dans la tables « AffaireEmployes-SectionAffaires ».
    Pour cela 2 requêtes sélection « V1_V2_n3_01_Employes-SectionsAffaires », « V1_V2_n3_02_Employes-SectionsAffaires » et requête ajout « V1_V2_n3_03_Employes-SectionsAffaires ».
    Si le raisonnement est correct même principe pour les 4 autres tables restantes !!!

    Sur ce, Meilleurs voeux de bonheur, santé et prospérité pour la nouvelle année.
    -------
    Fichiers attachés : SuiviAffaire_MaJ_V1_V2 2006-12-26.zip (100,1 ko)
    -------

  13. #13
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    D'abord, aucune excuse ne sera acceptée pour aucun retard : j'ai passé moi aussi toute la semaine à me saouler graduellement en prévision des fêtes, alors c'est bien normal qu'on soit tous en retard

    Petite mise au point :
    Les tables temporaires locales sont vidées en même temps que les tables de données du modèle.
    C'est pratique, mais je viens de me rappeler pourquoi je ne faisais pas comme ça dans mes développements :
    - les tables du modèle sont vidées une seule fois, puis envoyées telles quelles, avec le moteur de mise à jour, à l'utilisateur.
    Lorsque l'utilisateur lance ce moteur, la 1ère chose à faire est une copie du modèle. On ne modifie jamais ni sa base à lui, ni notre modèle, sinon, au moindre problème, il serait obligé de recharger toute l'installation pour récupérer un modèle propre.
    L'utilisateur peut faire tourner le moteur autant de fois qu'il veut : le modèle doit rester toujours vide.
    - par contre, à la 2ème exécution (toujours possible), les tables temporaires contiendront les données temporaires du 1er transfert.
    C'est donc là, à chaque exécution, qu'il faut les vider.
    J'ai
    - ajouté un paramètre Optional TempOnly As Boolean à la routine EmptyTables(), pour pouvoir l'appeler au début du transfert,
    - ajouté une remarque dans le code, là où il faudra faire une copie du modèle.
    Accessoirement, j'ai aussi retrié les routines des divers modules, pour garder un ordre logique (VBA > barre d'outils mzTools > Autres utilitaires > Trier les procédures...).

    Maintenant, nos tranferts : impec Ça marche très bien, résultats sans faille.
    J'ai quand même vérifié le tout en refaisant le débogage des 2 nouvelles phases :
    >Transfert vers la table SectionsAffaires
    - point d'arrêt (F9) dans le code de BeforeTransfer(), au dessous du Case "SectionsAffaires",
    - à l'exécution de chaque requête, je note le nombre d'enregistrements qui vont être transférés et surtout le nombre d'erreurs. Ici, elles sont toutes de type "... x enregistrements ... pas ajoutés suite à violation de clés..."
    - après exécution de chaque requête, j'ouvre les tables et je vérifie que tous les couples Affaire-Section sont bien passés une fois chacun,
    - etc.
    Il y a très peu de lignes dans nos tables, donc ça va vite.
    Avec une base pleine (centaines ou milliers de lignes), il aurait fallu construire, après chaque requête, une requête temporaire qui vérifie que chaque couple (clé Affaire/clé Section) de la table source est bien présente dans la destination après cette opération.

    Fastidieux ? Peut être, mais indispensable pour ne pas risquer de passer à côté d'une toute petite erreur non prévue, qui pourrait faire perdre des données (ne serait-ce qu'un seul enregistrement !)

    >Transfert de la table [HeurePersonnelAffaire] vers la table [Employes-SectionAffaires]
    Impeccable. C'est précisément ce qu'il fallait faire :
    - prendre les [HeurePersonnelAffaire]
    - trouver la nouvelle clé correspondant à chaque [SectionAffaire]
    - transférer le tout dans [Employes-SectionAffaires].
    Bon, faut que je justifie ma présence ici quand même , donc, 2 petites 'optimisations' :
    - tu as oublié le Cancel = True, ce qui ne pose aucun problème dans ce cas, mais attention : notre moteur essaye le transfert "de base" après l'exéction de tes requêtes spécifiques !
    - on peut simplifier ta requête (c'est toujours plus facile, quand on passe en second, d'où l'intérêt, comme avec les méthodes agiles, de travailler en binôme) : tu trouveras une requête [V1_V2_n3_00_Employes-SectionsAffaires] qui fait l'équivalent des 3 autres.
    - Enfin, que tu utilises ta requête ou celle-ci, le résultat sera le même. Mais il y a un moyen plus simple d'exécuter une seule requête, en mettant son nom directement dans la table de tables

    Conclusion :
    On n'est pas très loin d'avoir terminé notre 'moteur de transfert' de base.
    N'y a plus qu'à finir les dernières tables sur le même principe, puis on va renettoyer un peu tout ça avant de "l'envoyer à l'utilisateur".

    À toi aussi, et à tous ceux qui nous accompagnent : de très joyeuses fêtes avec plein de petits bugs, pardon, petites bulles dans le champagne et le plein de super applications à développer en 2007, just for fun !
    Fichiers attachés Fichiers attachés
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Citation Envoyé par Papy Turbo
    Conclusion :
    On n'est pas très loin d'avoir terminé notre 'moteur de transfert' de base.
    N'y a plus qu'à finir les dernières tables sur le même principe, puis on va renettoyer un peu tout ça avant de "l'envoyer à l'utilisateur".
    Aucun problème pour la table source ‘1_HeureFournisseurAffaire’ vers la table ‘2_Fournisseurs-SectionsAffaires’ (même raisonnement que pour le transfert ‘1_HeurePersonnelAffaire ‘ vers‘2_Employes-SectionAffaires’)

    Pour le transfert de la table ‘1_HeuresAllouees’ vers la table ‘2_HeuresAllouees-SectionsAffaires’. La table destination contient un champ supplémentaire ‘Datesaisie’ qui ne peut être nul. J’ai décidé d’y mettre la date du jour du transfert.

    Pour le transfert de la table ‘1_AvancementEtudePersonnel’ vers la table ‘2_HeuresPassees-SectionsAffaires-Employes’. La ‘cle metier’ n’oblige de faire 2 requêtes.

    Idem pour le transfert de la table ‘1_AvancementEtudeFournisseur’ vers la table ‘2_HeuresPassees-SectionsAffaires-Fournisseurs’.

    Le petit problème se trouve dans le journal. Vu que je fais une somme, le nombre d’enregistrements transféré n’est plus correct !

    Mais enfin je crois que tout est passé.


    PS : J’ai remarqué un petit hic dans la fonction « OuvrirFichierSpécifique » .
    En passant le nom du fichier dans la variable « LockedFileName », en cliquant juste ouvrir dans la fenêtre de choix de fichier et même si le fichier n’existe pas dans le répertoire scruté, la fonction retourne le même nom de fichier dans la variable « FullPath . « Embêtant non ! Puisqu’il faut refaire un test pour voir si le fichier existe vraiment .( ou je n’ai rien compris à la fonction ??)
    -------
    Fichiers attachés : SuiviAffaire_MaJ_V1_V2 2006-12-28.zip (108,4 ko)
    -------

  15. #15
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Citation Envoyé par Serge57
    Aucun problème pour la table source ‘1_HeureFournisseurAffaire’ vers la table ‘2_Fournisseurs-SectionsAffaires’ (même raisonnement que pour le transfert ‘1_HeurePersonnelAffaire ‘ vers‘2_Employes-SectionAffaires’)

    Pour le transfert de la table ‘1_HeuresAllouees’ vers la table ‘2_HeuresAllouees-SectionsAffaires’. La table destination contient un champ supplémentaire ‘Datesaisie’ qui ne peut être nul. J’ai décidé d’y mettre la date du jour du transfert.
    Impec
    Citation Envoyé par Serge57
    Pour le transfert de la table ‘1_AvancementEtudePersonnel’ vers la table ‘2_HeuresPassees-SectionsAffaires-Employes’. La ‘cle metier’ n’oblige de faire 2 requêtes.

    Idem pour le transfert de la table ‘1_AvancementEtudeFournisseur’ vers la table ‘2_HeuresPassees-SectionsAffaires-Fournisseurs’.
    Ça marche
    Histoire de chipoter, petite optimisation : la requête [V1_V2_n3_00_HeuresPassees-SectionsAffaires-Employes_03] fait la même chose, avec une seule requête.
    Ceci dit, tu as A PRIORI raison de séparer
    - la somme d'abord,
    - l'utilisation ensuite : il arrive souvent que les opérations soient fausses, notamment lorsque plusieurs tables sont
    liées dans la requête : chaque enregistrement peut être démultiplié...
    C'est là que les tests sont vitaux.

    Citation Envoyé par Serge57
    Le petit problème se trouve dans le journal. Vu que je fais une somme, le nombre d’enregistrements transféré n’est plus correct !
    Ça marche aussi
    Là, par contre, comme j'aime bien être sûr, en examinant le log, que tout se passe bien quand même, j'ai rajouté un test sur le nombre total d'heures . Si quelque chose ne passe pas, on le verra.

    Citation Envoyé par Serge57
    Mais enfin je crois que tout est passé.
    Ben, j'crois ben aussi
    Citation Envoyé par Serge57
    PS : J’ai remarqué un petit hic dans la fonction « OuvrirFichierSpécifique » .
    En passant le nom du fichier dans la variable « LockedFileName », en cliquant juste ouvrir dans la fenêtre de choix de fichier et même si le fichier n’existe pas dans le répertoire scruté, la fonction retourne le même nom de fichier dans la variable « FullPath . « Embêtant non ! Puisqu’il faut refaire un test pour voir si le fichier existe vraiment .( ou je n’ai rien compris à la fonction ??)
    Bravo, bien vu : lorsque le fichier n'existe pas, ça plante. Je n'avais pas testé ça parce que j'utilise (presque) la même routine "Fichier > Ouvrir..." dans mes applis.
    Ici, il manquait juste le flag OFN_FILEMUSTEXIST, dans StructFile, avant d'appeler l'Api GetOpenFileName(), pour spécifier qu'on veut bien un fichier existant.
    Du coup, j'ai aussi rajouté OFN_PATHMUSTEXIST.

    -------------------------

    Ben, il ne nous reste plus qu'à nettoyer tout ça (je te laisse choisir entre 1 seule ou 2 requêtes, pour les dernières tables), pour pouvoir ensuite réutiliser le tout le plus facilement possible.


    Allons-y donc pour un mini Cahier des charges, auquel tu peux rajouter ce qui te semble approprié :
    - faire une copie du modèle : si l'utilisateur se plante, il pourra recommencer autant qu'il veut..
    - cacher le 1er onglet, puisque les utilisateurs recevront un modèle déjà vide, et que les tabes temporaires sont bien vidées avant chaque exécution.
    - n'afficher dans le 2ème onglet que ce qui est strictement nécessaire pour l'utilisateur. En fait, j'intervertirais bien les 2 sous-formulaires au niveau 'choix des champs affichés'. Mais surtout : pas de noms de requêtes, ni tables temporaires...
    - rendre le 2ème onglet non modifiable : imagine le patakès si quelqu'un change un nom de table

    Côté application, j'irais bien inclure la classe clApplication et notre fichier journal, histoire d'enregistrer toutes les erreurs non prévues : y a rien de pire qu'un utilisateur qui t'annonce :
    --- j'ai eu un message.
    --- lequel ?
    --- je sais plus, mais c'était un message d'erreur...
    Réponse 1 (standard) :
    ---
    Réponse 2 :
    --- merci de m'envoyer le fichier "MonApp - journal d'erreurs.log" par e-mail

    Du coup, on va rendre systématique la chasse aux erreurs non prévues (ce que j'appelle par ailleurs "Objectif zero bug"), dans les 2 applications.

    Autre chose ?

    -------------------------

    En dernier, on entrera en phase "Support technique" : il est plus que probable que le moteur de mise à jour tombe sur un bec, lors de l'exécution sur une base réelle beaucoup plus grosse que celle qui sert aux essais.
    Dans ce cas, tu pourras
    - repérer le problème,
    - le reproduire dans la base de tests pour que tout le monde en profite,
    - créer une nouvelle version qui corrige également ce problème.

    C'est au fur et à mesure de la découverte de nouveaux problèmes, que notre moteur sera de plus en plus "universel", donc capable de répondre à tous les cas possibles...
    Fichiers attachés Fichiers attachés
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Tout d’abord bonne année 2007 à tous et surtout à Papy Turbo qui me m'aide beaucoup.

    Je ne sais pas si c’est les bulles, le fois gras… mais je bloque partout.

    Je développe :
    Citation Envoyé par Papy Turbo
    Allons-y donc pour un mini Cahier des charges, auquel tu peux rajouter ce qui te semble approprié :
    - faire une copie du modèle : si l'utilisateur se plante, il pourra recommencer autant qu'il veut..
    Pourquoi une copie ? Vu qu’il est possible de vider les bases à chaque relance de l’application.

    Citation Envoyé par Papy Turbo
    - cacher le 1er onglet, puisque les utilisateurs recevront un modèle déjà vide, et que les tables temporaires sont bien vidées avant chaque exécution.
    Si 1er onglet caché, le code ‘EmptyTables’ devient inutilisable …..

    Citation Envoyé par Papy Turbo
    Côté application…….
    Pour mettre en service sur l’application en cours d’utilisation, j’ai beaucoup de travail à faire sur les formulaires et états existant.
    Lors de la première mise en ligne de l’application (cours pt-01) il ne s’agissait que du haut de l’iceberg.
    - Une partie de l'application sert à la saisie des données (que je suis en train de peaufiner avec le turbo formulaire (cours-pt03)
    - Une autre qui sert à la visualisation (pas très bien faite … et qui pourrait faire suite au 'cours pt-03 turbo formulaire' comme le suggérait ‘Tonio-lille’ dans le cours 'Commentaires, remarques et suggestions')
    - et enfin une autre partie au statistique sur les heures (très bancale)


    Donc tant que j'ai un professeur disponible et très compétant je ne lâche pas !!! …….

  17. #17
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    D'abord, pardon pour ce retard : je suis busy, busy, busy, comme disait Maïa l'abeille, et puis, bonne année à toi aussi, bien sûr, et à tous ceux qui souffrent en testant ces formulaires et ce moteur...
    Citation Envoyé par Serge57
    Je ne sais pas si c’est les bulles, le fois gras… mais je bloque partout.
    Va pour les bulles. En ce qui me concerne, par solidarité avec les canards boiteux et surtout en batterie, je suis allergique au foie gras. À mon humble avis, ton problème ne peut venir que de là.
    Citation Envoyé par Serge57
    Pourquoi une copie ? Vu qu’il est possible de vider les bases à chaque relance de l’application.
    Essentiellement parce que ton cas, avec les 2 bases dans le même dossier que l'application, est une aberration.
    Même en monoposte, on stocke généralement
    - les bases de données dans des dossiers qui sont inclus dans une politique de sauvegarde quotidienne (Mes Documents...),
    - les applications dans d'autres dossiers (Program Files...): il est inutile de les sauvegarder quotidiennement. On en garde juste une copie, en cas de crash + le développeur en a toujours une ou 2 autres (lui, il sauvegarde ses sources tous les jours, à chaque modif ! C'est son capital)
    De plus, en réseau, la base est dans un dossier partagé, commun à tous, alors que chaque application est installée sur le poste de chaque utilisateur.
    Donc, le cas 'normal' sera :
    - installation du moteur de mise à jour (alias 'élément essentiel de ton programme d'installation et mise à jour des données' : la version 'pro' peut installer des icônes sur le bureau, un pilote pdf, des dlls, etc. etc.) dans le même dossier que l'application,
    - ce moteur devra donc
    ... se connecter à la base de données,
    ... faire une copie du modèle (déjà vidé) dans le même dossier,
    ... lancer la mise à jour.
    Dans ce cas, tu constates que les seules tables qu'il faut revider systématiquement sont les tables temporaires, locales, dans le moteur de MàJ. Ce que nous avons déjà prévu.
    Citation Envoyé par Serge57
    Si 1er onglet caché, le code ‘EmptyTables’ devient inutilisable …..
    Caché... pour les utilisateurs.
    C'est pour ça que je t'ai proposé de mettre en place une version simplifiée de la classe clApplication, avec un simple 'flag' Debugging.
    Si tu mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        tabWizard.Pages(0).Visible = ThisApp.Debugging
    dans le Form_Load du formulaire, il sera visible pour toi seulement
    Nous n'avons pas encore eu le temps, mais tu découvriras un bon nombre de fonctions qui peuvent utiliser cet indicateur.
    Ne serait-ce que quand nous allons mettre en place un vrai contrôle d'erreur : l'idéal, en cas d'erreur non prévue, est que le code :
    - pour un utilisateur : affiche le message d'erreur (sans le n°, ni la source...), et propose les 3 choix possibles (Abort, Retry, Ignore), puis enregistre le tout dans le journal (pour nous),
    - pour un programmeur : affiche le + d'info, puis fait un Resume pour s'arrêter sur la ligne qui plante : tu peux alors insérer le code nécessaire pour gérer cette nouvelle erreur.
    C'est ce que nous verrons dès que nous serons revenus à l'aplication pour insérer un code d'erreur systématique.
    Ceci ne représente que 2 exemples de tout ce qu'on peut adapter au fait que l'utilisateur est un programmeur ou pas
    Y en a beaucoup d'autres, que tu découvriras à l'usage.
    Citation Envoyé par Serge57
    Pour mettre en service sur l’application en cours d’utilisation, j’ai beaucoup de travail à faire sur les formulaires et états existant.
    Lors de la première mise en ligne de l’application (cours pt-01) il ne s’agissait que du haut de l’iceberg.
    - Une partie de l'application sert à la saisie des données (que je suis en train de peaufiner avec le turbo formulaire (cours-pt03)
    - Une autre qui sert à la visualisation (pas très bien faite … et qui pourrait faire suite au 'cours pt-03 turbo formulaire' comme le suggérait ‘Tonio-lille’ dans le cours 'Commentaires, remarques et suggestions')
    - et enfin une autre partie au statistique sur les heures (très bancale)


    Donc tant que j'ai un professeur disponible et très compétant je ne lâche pas !!! …….
    Bien, mais les autres formulaires, en particulier tout ce qui concerne la visualisation, ne concernent en rien la base de données.
    Rien ne t'empêche donc de tester la mise à jour des données entre l'ancienne version et la nouvelle : ça doit marcher.
    Je comprends bien que tu devras encore revoir l'ensemble de l'application, pour la passer à la nouvelle version, mais attention, on ne va pas non plus refaire toute ton application ici, en ligne.
    On n'abordera que les techniques de base, et à toi ensuite de les adapter.
    Donc, il faut que tu fasses tes tests en réel, et, si quelque chose plante, nous
    - ajouterons le cas (une ou plusieurs tables, avec quelques enregistrements à la 'Titi-toto-tata') dans les bases de test,
    - chercherons la solution ensemble, pour que le moteur s'enrichisse.
    Ceci n'est pas fermé, ni réservé à Serge57 : tous ceux qui souhaitent tester ce type de moteur avec leur propre base, et qui tombent sur un os, peuvent soumettre des exemples.
    À condition quand même de ne pas nous faire télécharger 200 mo de données, et de bien cerner le problème, merci d'avance
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  18. #18
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    Citation Envoyé par Papy Turbo
    Donc, il faut que tu fasses tes tests en réel, et, si quelque chose plante, nous
    - ajouterons le cas (une ou plusieurs tables, avec quelques enregistrements à la 'Titi-toto-tata') dans les bases de test,
    - chercherons la solution ensemble, pour que le moteur s'enrichisse.
    J’ai fait des tests sur ma base. Et ….il y a un petit hic sur la table « affaire » champ « désignation ». Nous l’avons réduit en ‘texte’ de 77 caractères. Lors du transfert j’ai une erreur 3163 (champ trop petit).En examinant le contenu (type mémo), certaines désignations contiennent des sauts de ligne, ou elles sont très longues. Si trop de caractères, je ne vois pas quoi faire ?

    Pour le reste(pour ma base)tout me semble OK.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    abWizard.Pages(0).Visible = ThisApp.Debugging
    j’ai intégré le code dans mon formulaire

    Citation Envoyé par Papy Turbo
    - ce moteur devra donc
    1... se connecter à la base de données,
    2... faire une copie du modèle (déjà vidé) dans le même dossier,
    3... lancer la mise à jour.
    Pour la remarque 2 je ne vois pas comment faire ?
    Faut-il contrôler si le fichier existe déjà dans le répertoire en question ? si oui, l’ effacer ?

    Citation Envoyé par Papy Turbo
    Bien, mais les autres formulaires, en particulier tout ce qui concerne la visualisation, ne concernent en rien la base de données.
    OK, c’est hors sujet. Je vaiis essayer de me reconcentrer sur le cours.

  19. #19
    Membre expérimenté
    Avatar de Papy Turbo
    Homme Profil pro
    Développeur Office/VBA
    Inscrit en
    Mars 2004
    Messages
    822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Office/VBA
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 822
    Points : 1 709
    Points
    1 709
    Par défaut
    Citation Envoyé par Serge57
    J’ai fait des tests sur ma base. Et ….il y a un petit hic sur la table « affaire » champ « désignation ». Nous l’avons réduit en ‘texte’ de 77 caractères. Lors du transfert j’ai une erreur 3163 (champ trop petit).En examinant le contenu (type mémo), certaines désignations contiennent des sauts de ligne, ou elles sont très longues. Si trop de caractères, je ne vois pas quoi faire ?
    77 caractères, ça me paraissait un peu zarbi , mais effectivement, c'est passé à 70.
    C'est à toi, en tant qu'utilisateur, de décider :
    - soit tu veux tronquer les anciens titres, en ne gardant que les 70 premiers caractères. Tu peux alors copier tout l'ancien titre dans le champ Observations, en plus de ce qui s'y trouve déjà. Ce champ est toujours un mémo, ce qui permettra à l'utilisateur de récupérer le contenu de l'ancien titre et de nettoyer tout ça...
    - soit tu veux, avant de publier cette nouvelle base, augmenter le nombre de caractères du titre ? mais, comme annoncé, attention. C'est un champ indexé, donc l'index va s'alourdir.

    Quant aux sauts de ligne, tu veux les garder (et agrandir le contrôle dans le formulaire, pour les montrer), ou les supprimer (avec Replace()) pour qu'on voit tout sur une ligne ?
    Citation Envoyé par Serge57
    Papy Turbo a écrit :
    - ce moteur devra donc
    1...
    2... faire une copie du modèle (déjà vidé) dans le même dossier,
    3...

    Pour la remarque 2 je ne vois pas comment faire ?
    Faut-il contrôler si le fichier existe déjà dans le répertoire en question ? si oui, l’ effacer ?
    Il n'y a qu'en le faisant que tu verras ce qu'il faut faire
    - une copie avec FileCopy (le plus simple).
    - sûr, la 2ème fois va se poser le problème : si le fichier existe déjà, tu peux soit le supprimer, soit demander confirmation à l'utilisateur ,soit renommer l'ancien en "*.old" (mais que faire si y a déjà un "*.old" ?) ?
    Quelque chose dans le genre : if Dir(...)>"" Then If MsgBox(...)=vbYes Then Kill ... me paraît assez simple.

    En fait, toutes mes remarques, aujourd'hui, ne semblent pas apporter beaucoup. Tu dois bien sûr, avoir une idée de ce que tu peux faire, des diverses solutions possibles. Mais ce n'est qu'en se lançant dans une solution, puis en la testant, que tu trouveras les bonnes réponses...
    Développement Office, support technique, assistance, sur place (Loire atlantique, Vendée, Maine et Loire) ou à distance.

  20. #20
    Membre du Club
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2006
    Messages : 79
    Points : 67
    Points
    67
    Par défaut
    En fait, toutes mes remarques, aujourd'hui, ne semblent pas apporter beaucoup. Tu dois bien sûr, avoir une idée de ce que tu peux faire, des diverses solutions possibles. Mais ce n'est qu'en se lançant dans une solution, puis en la testant, que tu trouveras les bonnes réponses...
    Je me suis lancé dans une solution.
    Création d’une routine ‘CopieModeleBase ()’ . Qui se trouve à la fin du module de classe ‘clApplication’.
    Le lancement de cette routine ce fait avant le contrôle et le réajustement des connections des tables attachées dans la fonction ‘App_Init’

    Problèmes :
    1 - Je ne sais pas comment faire pour trouver la variable du chemin de l’ancienne base ‘PathAncienneBase’ puisqu 'elle n'est pas encore connectée.
    2 – et j'impose le nom de la base modèle ‘\SuiviAffaire_BDD_V2’.

    Pour le reste, ça à l’air de tourner.
    -------
    Fichiers attachés : SuiviAffaire_MaJ_V1_V2 2007-02-05.zip (117,5 ko)
    -------

Discussions similaires

  1. Mise à jour structure base de données
    Par engi dans le forum Langage SQL
    Réponses: 2
    Dernier message: 23/10/2007, 17h11
  2. Mise à Jour Champ Base de Donnée
    Par arjo54 dans le forum IHM
    Réponses: 0
    Dernier message: 10/10/2007, 15h38
  3. [MySQL] Mise à jour dynamique base de données
    Par Lili72430 dans le forum PHP & Base de données
    Réponses: 1
    Dernier message: 28/09/2007, 12h36
  4. Requête de mise à jour - Ouverture base de données
    Par ade94 dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 31/05/2007, 16h50
  5. Problème de mise à jour de base de données
    Par poirier dans le forum ASP
    Réponses: 2
    Dernier message: 26/05/2004, 11h38

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