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

Macros et VBA Excel Discussion :

Copier x fois à partir d'une valeur Textbox


Sujet :

Macros et VBA Excel

  1. #21
    Expert éminent

    Homme Profil pro
    Curieux
    Inscrit en
    Juillet 2012
    Messages
    5 141
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Curieux
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2012
    Messages : 5 141
    Points : 9 976
    Points
    9 976
    Billets dans le blog
    5
    Par défaut
    Magistral ... comme toujours


  2. #22
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 433
    Points
    12 433
    Par défaut
    Bonjour,
    La méthode préconisée par Pierre Fauconnier est la bonne et ressemble assez à ce que j'ai eu l'occasion de faire en VB6 pour constituer un "tableau" te textboxes indexées.
    Les méthodes proposées auparavant l'avaient été sur des bases non encore précisées (simples copies répétées), qui avaient même fait penser à un exercice scolaire.
    Il en va maintenant assez différemment. Et nous savons que ce sont des étiquettes.
    Il se peut à ce propos (maintenant que nous savons de quoi il s'agit), que ce soit encore plus simple (toujours avec le mécanisme exposé par Pierre Fauconnier).
    Question, donc, au demandeur :
    - Puisqu'il s'agit d'étiquettes, est-t-il vraiment nécessaire d'éclater en lignes et colonnes (et donc en cellules distinctes) leur texte ? Le texte obtenu par concaténation, avec sauts de lignes de texte dans une seule cellule "étiquette" ne serait-il pas plus satisfaisant (et encore plus simple à traiter) ?
    Cette question n'est pas sans arrière pensée à divers points de vue.

  3. #23
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 129
    Points : 55 942
    Points
    55 942
    Billets dans le blog
    131
    Par défaut
    Si on peut tout mettre dans une seule cellule, cela revient à copier des étiquettes d'une ligne sur une colonne. A priori, et de manière à laisser le code fonctionnel pour des étiquettes de plusieurs lignes/colonnes, il n'est donc pas nécessaire de toucher à la fonction CopyLabel, par exemple. En faisant cela, on perd tout le bénéfice du code tel que je l'ai écrit.

    Les seules modifications à apporter le sont au niveau des adapter (cfr design pattern adapter pour ceux que cela intéresse), c'est-à dire les fonctions Catch.... Ce sont en effet elles qui adaptent les données entre l'interface de saisie et le "code consommateur" des infos saisies. Il suffit alors de "tailler" la plage LabelModel sur une ligne et une colonne et de placer les différentes valeurs récupérées du userform dans la même cellule et les seules modifications de code à réaliser le sont au niveau du bloc ' Transfert des données d'étiquette(j'ai gardé ici le nom de tes combobox, mais il faudra les renommer!!) (idéalement dans un nouvel adapter, c'est-à-dire une nouvelle fonction Catch...) pour se constituer une bibliothèque d'adapter en fonction des modèles d'étiquettes à réaliser.

    C'est là que réside la beauté du code modulaire tel que je l'ai exposé ( et c'est pour cela que j'ai pris le temps de ce "tutoriel"). En fait, il suffit de se créer des adapter qui correspondent aux étiquettes que l'on veut créer et le tour est joué. Si l'on souhaite maintenant mémoriser des modèles à 1 cellules ou à x lignes/y colonnes, il y a très peu à adapter, mais ce ne sera de toute façon qu'au niveau des catch... que des modifications devront être apportées.

    Je proposerai une version (encore plus) générique dans mon tuto...

  4. #24
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Merci Pierre pour c'est longue explication et ce boulot MONSTRUEUX, que tu nous présente. Je ne pensais pas que ma petite question aurait engendré ça . Je n'ai pas encore eu le temps de tout assimiler, ni de tester (j'aime bien comprendre avant). Mais tes explications sont très claires et vont me faire progresser (enfin j'espère retenir ). Je vais tester demain si j'ai le temps.
    Pour répondre à ta question unparia, je n'y avais pas pensé. J'ai prévu de réutiliser celle qui existe déjà et son sous se format. Il faut que je réfléchisse à cette proposition qui pourrait être certainement plus simple. Il y aurait tellement de petit détails à revoir, pour une amélioration digne de ce nom.

  5. #25
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 129
    Points : 55 942
    Points
    55 942
    Billets dans le blog
    131
    Par défaut
    Citation Envoyé par FLoPigloo Voir le message
    Merci Pierre pour c'est longue explication et ce boulot MONSTRUEUX, que tu nous présente.
    J'ai pris énormément de plaisir à le réaliser

    Citation Envoyé par FLoPigloo Voir le message
    Je ne pensais pas que ma petite question aurait engendré ça
    Cela faisait longtemps que j'avais envie, lorsque je voyais des procédures kilométriques et ingérables dans des onclick, d'expliquer "rapidement" comment on pouvait (devait) programmer. Merci à toi d'avoir été celui qui m'a mis le pied à l'étrier...

    Pour ce qui est de la réflexion d'un paria (drôle de pseudo, tout de même), regarde la réponse que j'y apporte. Tu n'a que très peu à changer dans mon code pour y arriver.

    Dans mon tuto, j'aborderai les questions de mises en forme des étiquettes, et ça va me permettre, j'y pense maintenant, d'apporter enfin une partie 2 à mon tuto sur les classes...

  6. #26
    Expert éminent Avatar de casefayere
    Homme Profil pro
    RETRAITE
    Inscrit en
    Décembre 2006
    Messages
    5 138
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Ardennes (Champagne Ardenne)

    Informations professionnelles :
    Activité : RETRAITE
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 138
    Points : 9 548
    Points
    9 548
    Par défaut
    Bonjour à tou(te)s,

    Je pense pouvoir me permettre, ayant participer avec unparia aux premières réponses de dire 2 mots :

    MERCI PIERRE !

  7. #27
    Membre extrêmement actif
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 83
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Points : 12 433
    Points
    12 433
    Par défaut
    Citation Envoyé par FLoPigloo Voir le message
    Merci
    Pour répondre à ta question unparia, je n'y avais pas pensé. J'ai prévu de réutiliser celle qui existe déjà et son sous se format. Il faut que je réfléchisse à cette proposition qui pourrait être certainement plus simple. Il y aurait tellement de petit détails à revoir, pour une amélioration digne de ce nom.
    cela pourrait surtout simplifier l'adaptation aux feuilles d'étiquettes, à partir de ce que l'on constate, centimètre en main, de leur constitution.
    et dans la foulée : décider de leur alignement

    c'est en fait surtout le 1er point, qui peut intéresser dans certains cas inopinés (plus de modèle habituel disponible, etc ...). Mon expérience dans ce domaine m'a appris :
    - qu'il suffisait par exemple d'une rupture de stock pour mettre par terre tous les "modèles" préétablis
    - qu'il était quelquefois difficile de s'y retrouver parmi les modèles préétablis lorsque devenus nombreux. De minuscules différences (marges haute et gauche, écarts latéral et/ou vertical entre étiquettes, etc ...) entre un fournisseur et l'autre pouvaient entraîner des décalages cumulés. Il me fallait alors y aller à tâtons alors qu'un petit outil que l'on renseignait suffisait à établir sans tâtonnements les spécifications adéquates.
    Mais cela n'est pour l'instant qu'un détail.

  8. #28
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Je viens d'essayer le code, tes informations sont super claires mais je dois oublier un truc et je retrouve pas mon erreur. En fait, dès que je clique sur valider ou annuler ça m'affiche le "message copie annuler par l'utilisateur". J'ai essayer d'enlever la ligne Else pour annuler et la pas copie, j'ai lancé le pas à pas mais je n'ai pas trouvé mon erreur. Une idée d'où le problème vient ?

    Si tu veux regarder j'ai essayer de suivre à la lettre ton tuto

    aide - Copie.xlsm

  9. #29
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 129
    Points : 55 942
    Points
    55 942
    Billets dans le blog
    131
    Par défaut
    Salut.

    Dans le code initial de CatchDatasFromUserForm j'avais oublié une ligne de code, mais il me semblait l'avoir corrigée...

    Tu dois ajouter la ligne CatchDatasFromUserForm = True ' Validation du traitement entre les lignes Separator = 2 et Else à la fin de la procédure.

    Attention que tu n'as pas créé ta plage nommmée AlreadyCopied (qui permet de savoir combien d'étiquettes ont été imprimées sur la feuille). Dans le classeur que tu m'as fourni, tu peux par exemple créer cette plage nommée en G1.

    J'ai nommé cette plage et j'ai testé. Ca fonctionne

  10. #30
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Attention que tu n'as pas créé ta plage nommmée AlreadyCopied (qui permet de savoir combien d'étiquettes ont été imprimées sur la feuille). Dans le classeur que tu m'as fourni, tu peux par exemple créer cette plage nommée en G1.
    Effectivement, j'ai oublié mais je ne comprend pas trop cette partie. J'ai essayé de faire Range("AlreadyCopied") = range("G1").
    Mais je pense que je suis loin de comprendre comme doit fonctionner cela.

  11. #31
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 129
    Points : 55 942
    Points
    55 942
    Billets dans le blog
    131
    Par défaut
    Range("AlreadyCopied") fait référence à une plage à laquelle tu as attribué un nom. C'est quelque chose à faire du côté Excel.

    Mais d'abord, pourquoi utiliser une plage nommée? Simplement parce que utiliser range("g1") dans ton code, c'est faire du hard coding, et ça c'est mal . Pourquoi? Parce si par la suite tu réaménages ton classeur et que ce n'est plus la cellule G1 qui contient l'info dont ton code a besoin, mais la cellule k19, tu seras obligé d'aller modifier partout dans ton code range("g1") en range("k19"). En utilisant une plage nommée, tu peux y faire référence dans ton code car même si tu la déplaces, c'est Excel qui se charge de savoir vers quelle cellule pointe le nom. En fait, une plage nommée, c'est un alias de plage qui permet de déplacer la plage sans en changer le nom.

    Pour créer cette plage nommée, et toutes les autres dont tu as besoin, tu peux procéder de deux façons. La plus rapide (mais qui se fait de temps en temps capricieuse sur mon pc), c'est de sélectionner la plage (ici G1) puis de saisir le nom que tu veux lui donner dans la zone de nom qui se situe sur à gauche de la barre de formule (là où on a l'habitude de voir l'adresse de la cellule active) et surtout, après la saisie du nom dans cette zone, de presser ENTER pour enregistrer le nom (très important!!).

    Lorsque c'est fait, tu peux faire référence au nom de la plage plutôt qu'à son adresse, en Excel, par exemple dans des formules, ou en VBA. L'avantage est que si tu déplaces ta plage, le nom "suit" le déplacement pour pointer vers le nouvel emplacement de ta plage. Ton code VBA continuera donc à être fonctionnel.

    Une deuxième solution qui permet des variations intéressantes est de sélectionner la plage, puis via l'onglet Formules du ruban, d'ouvrir le gestionnaire de nom et de remplir les contrôles avec les bonnes données.

    Lorsque j'ai regardé ton classeur tout à l'heure, j'ai vu une panoplie "monstrueuse" de noms pointant vers des références perdues dans le gestionnaire de noms. Ces "fantômes" proviennent probablement de multiples copier-colle, mais ils fragilisent et alourdissent le classeur.

    Pour le projet que tu souhaites développer, je ne saurais trop te conseiller de partir d'un fichier vierge et d'éviter les copier-coller habituels, mais de préférer les collages spéciaux. Attention toutefois que c'est le fait de coller les formules qui apportent ces scories dans le fichier.

  12. #32
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Merci beaucoup de l'aide. C'est bon, le code fonctionne à merveille . Pour tous ce qui des noms dans le gestionnaire des noms, c'est normal j'ai fait une copie de mon fichier de base. Et ils sont tous opérationnel sur celui-ci.
    Une dernière petite question, est-ce que pour checkbox je peux faire en sorte que l'étiquette en plus, est un résultat différent dans la combobox 3 par exemple ? Si je veux faire çà, il faut que je modifie une grande partie du code ?
    je pense que je vais faire sans sinon.
    Et encore merci pour ce tuto

  13. #33
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 129
    Points : 55 942
    Points
    55 942
    Billets dans le blog
    131
    Par défaut
    Citation Envoyé par FLoPigloo Voir le message
    [...]
    Une dernière petite question, est-ce que pour checkbox je peux faire en sorte que l'étiquette en plus, est un résultat différent dans la combobox 3 par exemple ? Si je veux faire çà, il faut que je modifie une grande partie du code ?
    je pense que je vais faire sans sinon.[...]
    Je ne suis pas certain de comprendre ta question. Que veux-tu faire avec l'étiquette?

    Quoi qu'il en soit, les modifications sont normalement minimes et ne concernent que la fonction qui sert d'adapter, c'est-à-dire la fonction Catch.... C'est dans cette fonction que tu gères les données reçues du userform et que tu les prépares pour les envoyer à CopyLabel.

    L'intérêt de la démarche est que tu peux utiliser plusieurs adapters. Il te suffit de créer les userforms correspondant à tes besoins, l'adapter (la fonction Catch... liée à ton userform servant à la préparation des données qui seront utilisées par CopyLabel.

  14. #34
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Ok, je vais réfléchir alors. Ce que je voudrais faire c'est par exemple quand je coche la checkbox, ça m'ajoute une étiquette mais juste avec une combobox qui change par exemple le destinataire qui serait combobox 3.

  15. #35
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 129
    Points : 55 942
    Points
    55 942
    Billets dans le blog
    131
    Par défaut
    Tu voudrais que lorsque tu cliques dans la checkbox, ça ajoute une combobox dans le userform?

  16. #36
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Non, que ça modifie le résultat d'une combobox mais que pour l’étiquette supplémentaire.

  17. #37
    Rédacteur/Modérateur


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 129
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 129
    Points : 55 942
    Points
    55 942
    Billets dans le blog
    131
    Par défaut
    Ok.

    A nouveau, la méthode que j'ai proposée va pouvoir être adaptée à "peu de frais".

    D'abord, deux coquilles se sont glissées dans le code que j'ai proposé dans mes différentes réponses.

    1. GetStartRow
    La fonction ne renvoyait pas toujours la bonne ligne à laquelle il fallait commencer l'impression d'une nouvelle étiquette. Lorsque la dernière ligne n'est pas complète, il faut ajouter 1 au quotient entier du nombre de lignes divisé par le nombre d'étiquettes en côte à côte. Voici le code corrigé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    ' Calcule la ligne de départ de positionnement de l'étiquette
    ' en fonction des étiquettes déjà imprimées
    '
    ' @param CountofLabelsPrinted Nombre d'étiquettes déjà placées
    '
    ' @return Long mentionnant à quelle ligne doit démarrer le positionnement
    Function GetStartRow(CountofLabelsPrinted As Long, SideBySideCount As Long) As Long
      If CountofLabelsPrinted = 0 Then GetStartRow = 1 ' page vierge, on commence à la ligne 1
      If (CountofLabelsPrinted Mod SideBySideCount) = 0 Then ' La dernière ligne est complète
        GetStartRow = CountofLabelsPrinted / SideBySideCount + 1
      Else ' La dernière ligne n'est pas complète
        GetStartRow = Int(CountofLabelsPrinted / SideBySideCount) + 1
      End If
    End Function
    2. TargetClean
    2. Cette fonction utilisait par défaut la feuille active, ce qui était un présupposé inexact car tu dois pouvoir démarrer sans être sur la feuille d'impression. Il faut donc préciser la feuille utilisée. J'ai nommé la feuille d'impression shPrint et j'ai adapté la procédure. Le code corrigé est ci-dessous:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ' Nettoyage de la zone de collage
    ' Placé dans une procédure spécifique pour pouvoir l'adapter facilement
    Sub TargetClean()
      shPrint.Range(shPrint.Range("TargetLabel"), shPrint.Cells(1048576, 16384)).ClearContents
    End Sub

    Voilà pour les quelques corrections.

    A présent, adaptons notre "logiciel" à cette nouvelle demande.

    Je reprends l'idée de ton adaptation: Si la case est cochée dans le userform, on doit imprimer le nombre d'étiquettes mentionné dans le textbox + une étiquette particulière (quelles que soient les particularités de cette étiquette).

    L'idée va donc être de stocker les "patrons" d'étiquettes sur une feuille Excel puis d'imprimer le lot d'étiquettes. On va en quelque sorte créer un batch qu'on lancera lorsque toutes les étiquettes auront été préparées. Je précise ici que l'architecture pourrait être autre que celle que je propose. Mais il me semble que ce que je décris est ce qui permet le plus aisément possible les évolutions de la demande de l'utilisateur

    On va donc avoir besoin:
    • d'un adapter (Une fonction Catch... spécifique et un userform spécifique. Cela permettra d'avoir des modèles pour lesquelles l'étiquette supplémentaire est identique aux autres et un modèle pour lequel elle est différente.
    • D'une feuille de batch dans laquelle on va déposer le modèle de chaque étiquette à imprimer ainsi que la quantité souhaitée. Cette feuille reprendra également les caractéristiques communes à toutes les étiquettes du batch, à savoir le nombre d'étiquettes de front et le séparateur de lignes. Il va sans dire (et donc mieux en le disant) qu'un batch doit évidemment reprendre des étiquettes de même format (même nombre de lignes et même nombre de colonnes). La feuille de batch précisera également si le batch démarre sur une nouvelle feuille ou "en continu";
    • D'une procédure qui nettoie la feuille de batch;
    • d'une procédure qui prépare le batch (PrepareBatch;
    • d'une procédure qui imprime le batch (PrintBatch;
    • d'une procédure qui démarre le batch (RunBatch;



    Comme tu pourrais avoir plusieurs batchs, il sera utile de suffixer les procédures du nom du modèle d'étiquette, par exemple (Ici, j'ai choisi X1).

    Commençons par la feuille de batch (je lui ai donné le codename shBatch_X1).

    On va partir du principe (choix de conception) que les données du batch seront en A2, B2 et C2. La liste d'étiquettes proprement dite commencera en A3, avec le nombre d'étiquettes en A et l'étiquette proprement dite en B (Dans l'illustration ci-dessous, les données en ligne 2 et suivantes seront remplies par la procédure RunBatch_X1).

    Nom : 2016-05-17_140308.jpg
Affichages : 509
Taille : 26,9 Ko

    UserForm du batch X1
    Si le userform n'est pas du tout modifié, tu peux garder le même. Ici, j'ai choisi de créer un nouveau userform pour bien identifier les paires Adapter/Userform (et aussi pour illustrer comment copier un userofm). A toi de voir ce qui convient le mieux. Tu devras évidemment adapter mon code en fonction de tes choix et des noms que tu attribues à tes éléments. Pour copier un userform, tu peux procéder de deux manières différentes:

    Soit tu as un autre classeur ouvert: du classeur "Etiquettes", tu glisses le userform à copier dans le second classeur ouvert. Cette manoeuvre copie le userform dans le second classeur. Tu renommes le userform du classeur Etiquettes avec le nouveau nom uLabelBatch_X1, puis tu glisses le userform du second classeur vers le classeur "Etiquette". Tu récupères ainsi ton premier userform avec son nom d'origine.

    Soit tu n'as pas de classeur ouvert et soit tu en ouvres un et tu procédes comme ci-dessus, soit, par clic droit, tu exportes le userform (= enregistrer), tu le renommes puis tu l'importes.

    Quelle que soit la technique choisie, tu te retrouves alors avec les deux userforms. Dans le cas présent, je n'ai apporté aucune modification au code du userform. A priori, sauf à modifier l'alimentation des combobox, à ajouter ou supprimer des contrôles, le code en lui-même ne devrait pas être modifié.

    Création d'un nouvel adapter

    Ici aussi, je choisis de créer un nouvel adapter pour garder l'ancien et constituer petit à petit un jeu d'adapter pour les différentes situations rencontrées.
    Cet adapter est assez différent du premier. En effet, celui vu précédemment reçoit des arguments ByRef (par référence). Ces arguments ne sont donc pas des copies locales des variables de la procédure Main mais sont les variables de cette procédure. On pouvait procéder ainsi car on n'avait qu'une étiquette à copier. Dans le cas présent, on joue une autre partition. A nouveau, c'est un choix conceptuel. La procédure Catch... aurait pu lancer directement les CopyLabel. Le choix du travail par lot sur une feuille spécifique permet d'illustrer que tu pourrais très bien avoir un batch défini autrement que par des données saisies d'un userform et provenant par exemple d'un fichier XML. En procédant ainsi, tu enrichis ton "logiciel" d'une fonctionnalité supplémentaire qu'il ne possédait pas.

    Bref! Ce nouvel adapter doit recevoir l'emplacement sur la feuille de batch où déposer sa première étiquette. Il n'a plus besoin des autres arguments puisque c'est lui qui va déposer les données sur la feuille de batch. On remarque ici que les modifications interviennent surtout au niveau du transfert des données reçues du userform, puisqu'elles sont maintenant transférées sur la feuille du batch alors qu'avant, elles étaient "utilisées" par Main pour être envoyées vers CopyLabel. ( Je répète que c'est un choix conceptuel, qui a le mérite d'enrichir ton logiciel et de ne pas altérer l'existant).

    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
    44
    45
    46
    47
    48
    49
    50
    ' Fonction de capture des infos du userform pour dépôt des étiquettes dans la batchlist
    ' Cet adapter dépose une ou deux étiquettes dans la batchlist selon que la case +1 est cochée ou non
    ' @param BatchListFirstCell cellule de la batchlist dans laquelle déposer la premiètre étiquette
    ' @param Target Cellule supérieure gauche de la première étiquette copiée
    '
    ' @Return True si la copie doit avoir lieu, sinon False
    Function CatchDatasFromUserFormForBatch_X1(BatchListFirstCell As Range) As Boolean
      Load uLabelBatch_X1 ' Chargement du userform nommé uLabelBatch
      With uLabelBatch_X1
        .TextBox1 = 10 ' Par défaut, le formulaire proposera 10 copies
        .CheckBox1 = True ' par défaut, le +1 sera coché
      End With
     
      uLabelBatch_X1.Show ' Affichage
      ' Traitement en fonction du bouton cliqué (valeur de la variable, ou plutôt de la propriété Choice du formulaire)
      If uLabelBatch_X1.Choice = "Validate" Then
        'Transfert dans la batchlist du nombre d'étiquettes à imprimer
        BatchListFirstCell.Value = uLabelBatch_X1.TextBox1 * 1
     
        ' Transfert de l'étiquette modèle
        With BatchListFirstCell
          .Cells(1, 2).Value = uLabelBatch_X1.ComboBox1.Text
          .Cells(1, 3).Value = uLabelBatch_X1.ComboBox2.Text
          .Cells(2, 2).Value = uLabelBatch_X1.ComboBox3.Text
          .Cells(2, 3).Value = uLabelBatch_X1.TextBox3.Value
          .Cells(3, 2).Value = uLabelBatch_X1.TextBox2.Value
          .Cells(3, 3).Value = uLabelBatch_X1.ComboBox4.Text
          .Cells(4, 2).Value = uLabelBatch_X1.TextBox4.Value
        End With
     
        ' Si case +1 cochée, transfert de la nouvelle étiquette modifiées (la "+1") dans la batchlist
        If uLabelBatch_X1.CheckBox1 Then
          Set BatchListFirstCell = BatchListFirstCell.Offset(4) ' Décalage dans la batchlist pour la nouvelle étiquette
          BatchListFirstCell.Value = 1 ' On n'imprimera qu'une étiquette "en plus"
          ' Transfert des données de l'étiquette supplémentaire (à adapter à ton cas)
          With BatchListFirstCell
            .Cells(1, 2).Value = uLabelBatch_X1.ComboBox1.Text
            .Cells(1, 3).Value = uLabelBatch_X1.ComboBox2.Text
            .Cells(2, 2).Value = uLabelBatch_X1.ComboBox3.Text
            .Cells(2, 3).Value = uLabelBatch_X1.TextBox3.Value
            .Cells(3, 2).Value = uLabelBatch_X1.TextBox2.Value
            .Cells(3, 3).Value = uLabelBatch_X1.ComboBox4.Text
            .Cells(4, 2).Value = "Etiquette + 1" ' A adapter (illustre l'étiquette +1 différente)
          End With
        End If
      End If
     
      CatchDatasFromUserFormForBatch_X1 = (uLabelBatch_X1.Choice = "Validate") 'retour de la fonction selon le bouton cliqué (qui a modifié Choice)
      Unload uLabel1 ' On décharge le formulaire
    End Function

    Procédure BatchClean

    Petite procédure toute simple qui nettoie la feuille de batch. A nouveau, la procédure est isolée car elle pourrait être complexifiée s'il faut garder une mise en forme particulière, par exemple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ' Nettoie la feuille contenant la liste des étiquettes à imprimer en série
    ' Cette liste est située sur la feuille dont le codename est shBatchList
    Sub BatchListClean()
      shBatch_X1.Rows("2:1048576").ClearContents
    End Sub

    Procédure PrepareBatch_X1
    L'adapter doit être appelé par une procédure qui va:
    • Nettoyer la feuille du batch;
    • La préparer avec les données du batch
    • Lancer le Catch... correspondant pour préparer la batchlist


    Cette procédure reçoit la valeur de retour du Catch (On continue où on arrête!). Il faut noter que ce n'est pas ici que le code s'arrête en cas de clic sur "Annuler" du userform. C'est à la procédure de gestion du batch (RunBatch) qu'il revient d'aiguiller en fonction du choix de l'utilisateur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    ' Procédure qui prépare un batch d'impression d'étiquettes du modèle X1
    ' Modèle X1 = étiquette de 4 lignes et 2 colonnes par 3 de front avec 2 lignes de séparation
    ' Reçoit la variable de retour de Catch... et la renverra en retour de fonction
    Function PrepareBatch_X1() As Boolean
      BatchListClean ' Nettoie la batchlist avant de recevoir les nouvelles étiquettes
     
      ' Préparation de la batchlist
      shBatch_X1.Range("a2").Value = 3 ' nombre d'étiquettes de front
      shBatch_X1.Range("b2").Value = 2 ' nombre de lignes Excel entre chaque ligne d'étiquette
      shBatch_X1.Range("c2").Value = "New" ' si New, la feuille d'impression sera remise à zéro
      PrepareBatch_X1 = CatchDatasFromUserFormForBatch_X1(shBatch_X1.Range("a3"))  ' La liste des étiquettes commence en A2. Reçoit la valeur de retour ce Catch...
    End Function

    Lorsque cette fonction aura été exécutée, la feuille du batch sera complétée avec les différentes données. On voit bien ici que deux étiquettes ont été préparées, la première pour être imprimée 10 fois et la seconde 1 fois.
    Nom : 2016-05-17_153355.jpg
Affichages : 516
Taille : 32,0 Ko

    Procédure PrintBatch_X1

    Cette procédure va boucler sur les étiquettes présentes sur la feuille de batch et les envoyer à l'impression via la procédure CopyLabel. Elle est assez simple à comprendre. Elle va regarder s'il faut préparer une nouvelle feuille d'impression, puis déterminer les ligne et colonne de la première étiquette sur la feuille d'impression, après quoi elle bouclera sur les étiquettes présentes sur la feuille de batch

    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
    ' Démarre la batch préparé sur la feuille passée en argument
    '
    ' @param BatchSheet feuille Excel décrivant le batch à imprimer
    Sub PrintBatch_X1(BatchSheet As Worksheet)
      Dim StartRow As Long ' Ligne de démarrage sur la feuille d'impression
      Dim StartColumn As Long ' Colonne de démarrage sur la feuille d'impression
      Dim SideBySideCount As Long ' Nombre d'étiquettes de front
      Dim Separator As Long ' Nombre de lignes de séparation entre étiquettes
      Dim PrintType As String ' New si la feuille d'impression doit être nettoyée avant impression du batch
      Dim LabelRange As Range ' Place de l'étiquette sur la feuille BatchList
      Dim LabelCountRange As Range ' Cellule de la batchlist qui contient le nombre d'étiquette à imprimer
     
      ' Récupération des données du batch
      SideBySideCount = BatchSheet.Range("a2").Value
      Separator = BatchSheet.Range("b2").Value
     
      If BatchSheet.Range("c2") = "New" Then ' si "New", on nettoie la feuille d'impression
        TargetClean ' Nettoyage
        StartRow = 1 ' On commencera en ligne 1
        StartColumn = 1 ' On commencera en colonne 1
        Range("AlreadyCopied").Value = 0 ' Remise à zéro du compteur des étiquettes placées sur la feuille d'impression
      Else
        StartRow = GetStartRow(Range("alreadyCopied").Value, SideBySideCount)
        StartColumn = GetStarColumn(Range("alreadycopied").Value, SideBySideCount)
      End If
     
      ' Impression des étiquettes présentes dans le batch
      Set LabelCountRange = BatchSheet.Range("a3") ' On démarre en A3
      Do While LabelCountRange.Value <> 0 ' Il reste des étiquettes à imprimer
        Set LabelRange = LabelCountRange.Offset(0, 1).Resize(4, 2) ' On définit la plage qui contient les données de l'étiquette
        CopyLabel LabelRange, Range("TargetLabel"), LabelCountRange.Value, SideBySideCount, Separator, StartRow, StartColumn ' Impression
     
        ' Préparation de l'étiquette suivante
        Range("alreadycopied").Value = Range("alreadycopied").Value + LabelCountRange.Value
        StartRow = GetStartRow(Range("alreadyCopied").Value, SideBySideCount)
        StartColumn = GetStarColumn(Range("alreadycopied").Value, SideBySideCount)
        Set LabelCountRange = LabelCountRange.Offset(4) ' On décale de 4 vers le bas pour l'étiquette suivante
      Loop
    End Sub
    Procédure RunBatch_X1

    RunBatch sert simplement à "faire prendre la mayonnaise" en appelant PrepareBatch... puis, si le choix est de valider, en appelant PrintBatch....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ' Préparation et lancement du batch X1
    Sub RunBatch_X1()
      If PrepareBatch_X1() Then
        PrintBatch_X1 shBatch_X1
        MsgBox "Batch Terminé"
      Else
        MsgBox "Batch annulé", vbExclamation
      End If
    End Sub
    Lorsque le traitement est terminé, la feuille d'impression est complétée avec les quantités souhaitées d'étiquettes. On remarque bien les 10 étiquettes semblables suivies de la onzième, la fameuse "+1" de ta demande
    Nom : 2016-05-17_153635.jpg
Affichages : 534
Taille : 104,9 Ko



    On aurait pu faire plus simple!!
    Comme je l'ai dit plus haut, on aurait pu faire en sorte que l'adapter envoie directement les données vers CopyLabel, par exemple. Les modifications du code étaient alors limitées, soit dans l'adapter existant, soit dans une copie effectuée comme expliqué plus haut. Mon choix, en passant par la mise en place d'une procédure de batch, est d'illustrer que d'une demande simple (userform vers feuille Excel), on a pu, grâce à une architecture souple (même si elle paraît complexe), on a pu envisager différents cas, notamment pour la capture des données à imprimer sur les étiquettes, alors que ces modifications auraient été hasardeuses dans une solution "tout dans le bouton".

    Avec le code actuel, on pourrait très bien envisager de recevoir les données du batch sous forme de xml, de fichier txt, de feuille Excel, ...

    Surtout, cette articulation du code autour de procédures ou fonctions "qui ne font qu'une chose" permet une évolution et une adaptation du "logiciel" aux nouvelles demandes des utilisateurs et, notion importante dont je n'ai pas encore parlé, cette architecture permet de "responsabiliser" les différentes fonctions et les différents outils mis en place:
    Catch... a la responsabilité de saisir les données, ni plus ni moins. C'est pour cela que Catch... n'envoie pas directement à CopyLabel, ce n'est pas son rôle;
    Prepare... prépare les données mais ne les imprime pas. A nouveau, ce n'est pas son rôle, comme ce n'est pas son rôle d'arrêter le process si l'utilisateur clique sur Annuler;
    RunBatch... est le "chef d'orchestre" du batch, il demande que l'on prépare, puis il imprime si le choix a été d'imprimer. Il y a une similitude entre Main (vu au début) et RunBatch. Ce sont ces procédures qui articulent le processus et qui distribuent les rôles.

    Finalité de mon intervention
    Mon but ici n'est pas de te créer ton outil (où alors, je t'envoie mon numéro de compte... ), mais bien de montrer comment développer une "application Excel" avec du code VBA. Cette mise en place semble plus lourde que de tout mettre sur le clic d'un bouton de userform, mais les développements vus ici illustrent, du moins je l'espère, que l'on peut, finalement à peu de frais, programmer proprement de de façon à pouvoir faire évoluer la demande et qu'une fois que l'ossature est créée, les modifications sont autrement plus simples que lorsque qu'une procédure "fourre-tout" est utilisée.

    Bon travail pour la suite

  18. #38
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Bonjour,
    Merci encore une fois de cette réponse efficace, je viens d'essayer après quelque modification pour faire fonctionné le tout sur mon ordi, le code fonctionne.
    Mais je sais pas si j'ai fait une boulette. En effet, quand je lance ma macro celle-ci fonctionne, mais elle me propose plus de partir d'une feuille vierge.
    J'ai donc essayer d'intégré ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     Answer = MsgBox("Voulez-vous partir d'une feuille vierge?", vbQuestion + vbYesNo, "Impression étiquettes")
        If Answer = vbYes Then
          TargetClean ' Nettoyage de la plage finale
          StartRow = 1
          StartColumn = 1
          Range("AlreadyCopied") = 0
        Else
          StartRow = GetStartRow(Range("Alreadycopied").Value, SideBySideCount)
          StartColumn = GetStarColumn(Range("Alreadycopied").Value, SideBySideCount)
        End If
    Mais je n'ai pas la fenêtre qui s'ouvre je pense l'avoir mal intégré, ou dois-je l'intégrer. il faut que je rajoute une ligne pour si oui on incrémente new dans la case "C2" ?

    J'ai trouvé désolé du dérangement, j'avais mis Ecrire new automatiquement
    Le code est vraiment court en fait merci beaucoup, ca fonctionne bien j'espère que j'ai rien oublié !!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Answer = MsgBox("Voulez-vous partir d'une feuille vierge?", vbQuestion + vbYesNo, "Impression étiquettes")
        If Answer = vbYes Then
        Sheets("shBatch_X1").Range("c2") = "New"

  19. #39
    Nouveau membre du Club
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Août 2015
    Messages
    37
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Directeur de projet

    Informations forums :
    Inscription : Août 2015
    Messages : 37
    Points : 30
    Points
    30
    Par défaut
    Bonjour,
    La macro fonctionne super bien, facile à modifier, j'ai rajouté quelques petites choses pour améliorer.
    Mais j'ai quand un petit soucis, j'ai des étiquettes qui sont comptées par le batch mais sont vides dans mes plages d'étiquettes. Je pense avoir trouvé pour reproduire le bug, quand j'imprime les étiquettes 2 par 2, la 4 ème est blanche (celle du retour à ligne). Mais si je continue à en imprimer, elle est bien compter.
    Savez-vous d'où le problème peut venir?
    Merci d'avance.

    Nom : bug.png
Affichages : 523
Taille : 20,4 Ko

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Copier un champ à partir d'une valeur recherchée
    Par gilou41 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 03/06/2013, 10h29
  2. Réponses: 3
    Dernier message: 23/06/2006, 11h03
  3. Réponses: 2
    Dernier message: 08/05/2006, 22h27
  4. Copier un fichier à partir d'une URL ?
    Par oulahoup dans le forum ASP
    Réponses: 2
    Dernier message: 18/08/2005, 22h52

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