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 :

Code pour remplir des cellules non basé sur les colonnes [XL-2007]


Sujet :

Macros et VBA Excel

  1. #1
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut Code pour remplir des cellules non basé sur les colonnes
    Bonjour,

    Etant novice en VBA, cela fait un moment que je cherche une solution pour écrire un code de remplissage de cellule qui ne se base pas les colonnes mais sur des noms données aux colonnes.

    Je m'explique : Je voudrais remplir différentes cellules d'un tableau à la dernière ligne utilisée a l'aide d'un UserForm, par contre, lorsque j'insère une colonne manuellement dans le fichier. toutes les données importées à l'arrière sont décalées d'une cellule.

    J'ai nommé mes différents colonnes dans le tableur (ex : Nom colonne D = Emetteur et nom colonne O = Date_E))



    Voici un morceau de mon code actuel. (désolé, je ne sais pas comment insérer un morceau de code dans une liste numérotée)



    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
    'Correspond au programme du bouton VALIDER
    Private Sub CommandButton1_Click()
    Dim L As Integer
    Dim Commentaire As String
    Commentaire = TextBox4.Text
    Dim estouvert As Integer
    Dim fich As Workbook
     
     
    If MsgBox("Etes-vous certain de vouloir INSERER cette Non-Conformité ?", vbYesNo, "Demande de confirmation") = vbYes Then
     
    'Verification si "Tbx source" est ouvert sinon l'ouvrir
    estouvert = False
    For Each fich In Workbooks
    If fich.Name = "Tbx source.xlsm" Then estouvert = True
    Next
    If estouvert = False Then Workbooks.Open ("c:\CHEMIN\Tbx source.xlsm")
     
     
    'Insertion des données dans "Tbx source"
    L = Workbooks("Tbx source.xlsm").Sheets("tbx source").Range("D65536").End(xlUp).Row + 1 'Permet de se positionner sur la dernière ligne de tableau NON VIDE
    Workbooks("Tbx source.xlsm").Sheets("tbx source").Range("D" & L).Value = Label1
    Workbooks("Tbx source.xlsm").Sheets("tbx source").Range("O" & L).Value = Label4
     
     
    End If
    End Sub
    Merci pour votre aide.
    Philippe

  2. #2
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 940
    Points : 28 938
    Points
    28 938
    Billets dans le blog
    53
    Par défaut
    Bonjour,
    Je m'explique : Je voudrais remplir différentes cellules d'un tableau à la dernière ligne utilisée a l'aide d'un UserForm, par contre, lorsque j'insère une colonne manuellement dans le fichier. toutes les données importées à l'arrière sont décalées d'une cellule.
    Pour rendre dynamique ce type d'action, je préconise l'utilisation de la fonction EQUIV (MATCH en version anglaise et VBA) ou la méthode Find de l'objet Range. Dans ces deux cas, en faisant une recherche sur l'étiquette de colonne nous pourrons connaître le n° de la colonne désirée.
    Exemple avec Match
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Sub test()
     Dim rng As Range, rng_Column As Range, ColumnPosition As Long, c As Range
     Const SearchValue As String = "Adresse"
     Set rng = ThisWorkbook.Worksheets("Membre").Range("A1").CurrentRegion ' Equivalent à Ctrl + A ou Ctrl + *
     ColumnPosition = Application.WorksheetFunction.Match(SearchValue, rng.Resize(1), 0) ' Position de l'étiquette en ligne 1 
     Set rng_Column = rng.Columns(ColumnPosition).Cells
     For Each c In rng_Column ' parcoure l'ensemble des cellules de la colonne
      Debug.Print c.Value
     Next
    End Sub
    La procédure ci-dessus sélectionne (variable Objet nommée rng_Column) la colonne dont l'étiquette de colonne est Adresse.
    Ainsi lors de l'insertion d'une voire plusieurs colonnes, il n'y aura aucun problème pour la sélectionner
    Nom : Exemple match.jpg
Affichages : 852
Taille : 44,3 Ko

    On n'est bien entendu pas obligé de passer par une variable objet intermédiaire
    Voici un autre exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Sub test()
     Dim rng As Range, ColumnPosition As Long, c As Range
     Const SearchValue As String = "Adresse"
     Set rng = ThisWorkbook.Worksheets("Membre").Range("A1").CurrentRegion
     ColumnPosition = Application.WorksheetFunction.Match(SearchValue, rng.Resize(1), 0)
     For Each c In rng.Columns(ColumnPosition).Cells
      Debug.Print c.Value
     Next
    End Sub
    Et j'ajouterais qu'idéalement on devrait faire en sorte de n'utiliser que la partie Data, c'est à dire à partir de la ligne 2. Il faut alors utiliser les propriétés Offset et Resize combinées.
    Exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Sub test()
     Dim rng As Range, ColumnPosition As Long, c As Range
     Const SearchValue As String = "Adresse"
     Set rng = ThisWorkbook.Worksheets("Membre").Range("A1").CurrentRegion
     ColumnPosition = Application.WorksheetFunction.Match(SearchValue, rng.Resize(1), 0)
     With rng ' Utilise uniquement la partie données
      Set rng = .Offset(1).Resize(.Rows.Count - 1)
     End With
     For Each c In rng.Columns(ColumnPosition).Cells
      Debug.Print c.Value
     Next
    End Sub

  3. #3
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 906
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 906
    Points : 8 539
    Points
    8 539
    Par défaut
    Salut

    Pour ma part je conseille l'utilisation des tableau (Onglet Insertion->Tableau)
    Tu peux ensuite le renommer en cliquant n'importe où dans le tableau, un onglet spécifique va apparaitre dans le bandeau excel avec des options.

    Pour ce qui est de l'utilisation dans le code ça ressemble à ça

    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
        'On pointe sur le tableau pour simplifier les écritures
        With Feuil1.ListObjects("Tab_Traitement")
            'On boucle sur les lignes du tableau Tab_Traitement
            For Each TheRow In .ListRows
                'On regarde si la colonne création contien quelques choses
                NonCreer = .ListColumns("Création").DataBodyRange.Cells(TheRow.Index, 1) = ""
     
                'On mémorise le pilote et on regarde si affecté
                Pilote = .ListColumns("Pilote").DataBodyRange.Cells(TheRow.Index, 1) 'Cells(i, 20).Value
                PiloteChoisi = Pilote <> ""
     
                'On teste si la ligne doit être traité
                If NonCreer And PiloteChoisi Then
                    ' Entre les données de la NC dans les variables
                    DateCode = .ListColumns("N° NC").DataBodyRange.Cells(TheRow.Index, 1) 'Cells(i, 2).Value
                    DateNC = .ListColumns("DATE").DataBodyRange.Cells(TheRow.Index, 1) 'Cells(i, 5).Value
                    Reference = .ListColumns("PRODUIT").DataBodyRange.Cells(TheRow.Index, 1) 'Cells(i, 6).Value
                    Designation = .ListColumns("DESIGNATION").DataBodyRange.Cells(TheRow.Index, 1) 'Cells(i, 7).Value
                    Fournisseur = .ListColumns("CLIENT").DataBodyRange.Cells(TheRow.Index, 1) 'Cells(i, 8).Value
                    Effet = .ListColumns("NC détectée").DataBodyRange.Cells(TheRow.Index, 1) 'Cells(i, 9).Value
    Si tu veux un exemple complet voila la discussion d'où est issu le morceau de code.

    ++
    Qwaz

  4. #4
    Rédacteur
    Avatar de Philippe Tulliez
    Homme Profil pro
    Formateur, développeur et consultant Excel, Access, Word et VBA
    Inscrit en
    Janvier 2010
    Messages
    12 940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur, développeur et consultant Excel, Access, Word et VBA

    Informations forums :
    Inscription : Janvier 2010
    Messages : 12 940
    Points : 28 938
    Points
    28 938
    Billets dans le blog
    53
    Par défaut
    Bonjour Stéphane,
    C'est effectivement une autre solution tout aussi intéressante.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Merci à vous pour vos réponses...

    @Qwazerty : Pour un novice, cette solution parait plus simple à mettre en œuvre. Par contre, pourriez-vous juste me donner la syntaxe pour une entrée de donné dans ce type de tableau du style :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Sheets("Feuil1").Range("D" & L).Value = ComboBox3.Value.
    Merci.

  6. #6
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 906
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 906
    Points : 8 539
    Points
    8 539
    Par défaut
    Salut

    Tout simplement en inversant les termes de l'exemple donné au dessus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    DateCode = .ListColumns("N° NC").DataBodyRange.Cells(TheRow.Index, 1)
    Devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    .ListColumns("N° NC").DataBodyRange.Cells(TheRow.Index, 1) = DateCode
    Voila un exemple concrêt
    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
    Sub teste()
    'Déclaration d'un objet Row (qui représente une ligne du tableau
    Dim NewRow As ListRow
     
        'On simplifie l'écriture (attention Feuil3 est le codeName de la feuille pas le nom contenu dans l'onglet sous Excel (voir image liée au poste
        With Feuil3.ListObjects("Tab_Taux")
            'On créee une nouvelle ligne et on la pointe avec NewRow
            Set NewRow = .ListRows.Add
     
            'On renseigne les données
            'dans la 1ère cellule de la nouvelle ligne
            .ListColumns("NomDeLaColonne").DataBodyRange.Cells(NewRow.Index, 1) = label1.Text
            'Puis dans la cellule suivante
            .ListColumns("NomDeLaColonne").DataBodyRange.Cells(NewRow.Index, 2) = Label3.Text
     
            '[...]
     
            'Si tu veux supprimer une ligne
            .ListRows.Item(2).Delete
     
        End With
    End Sub
    N'hésite pas à utiliser l'aide VBE pour savoir à quoi correspondent les différents membre (touche F1).
    DataBodyRange par exemple ne tient pas compte de l'entête du tableau, uniquement des données.

    Pour le codeName c'est ici que ça se passe
    Nom : 2015-01-18_134906.png
Affichages : 892
Taille : 14,2 Ko

    ++
    Qwaz

    @Philippe Tulliez : Oui j'aime bien utiliser les tableaux, ils offrent de bonnes possibilités et le code s'en trouve simplifié. Je trouve que ça a été développé intelligemment.
    J'ai pas testé l'écriture sur le blog, je ferais peut-être un petit billet s'il n'y a pas déjà des choses

  7. #7
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Merci, je crois que j'ai compris. Demain matin j'essaye d'adapter mon code et je vous tiendrais au courant.

  8. #8
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Help.....Je ne m'en sors pas.....

    J'ai essayé la solution de Qwazerty et je n'arrive toujours pas à remplir les cellules de mon tableau proprement. sans utiliser la méthode " cells(1,1)"

    J'ai créé deux petits fichiers tout basiques.

    Est-ce que quelqu'un pourrais juste, SVP, me coder ces deux affectations de cellule pour que j'ai un exemple de syntaxe.
    Est-ce qu'il est possible d’insérer une ligne sous la dernière ligne remplie du tableau destination avant l'écriture dans celle-ci ?

    Pour rappel, je voudrais pouvoir par la suite insérer de nouvelles colonne dans mon tableau sans être obligé de réaffecter tout le code d'insertion des valeurs dans mon fichier destination.

    Merci d'avance.

    Philippe.
    Fichiers attachés Fichiers attachés

  9. #9
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 906
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 906
    Points : 8 539
    Points
    8 539
    Par défaut
    Salut

    J'ai pas compris pourquoi il y avait deux fichiers, aucun ne contient une macro qui pourrait ressembler à un essai, c'est dommage.

    Voila le morceau de code que j'avais mis au dessus adapté
    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
    'Déclaration d'un objet Row (qui représente une ligne du tableau
    Dim NewRow As ListRow
     
        'On simplifie l'écriture (attention Feuil3 est le codeName de la feuille pas le nom contenu dans l'onglet sous Excel (voir image liée au poste
        'Ici tu changes le nom de ta feuille qui contient le tableau, donc Feuil1 à la place de feuil3 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
        'Tu changes le nom de ton tableau, ici c'est Tableau1 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
        With Feuil1.ListObjects("Tableau1")
            'On créee une nouvelle ligne et on la pointe avec NewRow
            Set NewRow = .ListRows.Add
     
            'On renseigne les données
            'dans la 1ère cellule de la nouvelle ligne
            'Ici le nom de ta 1ère colonne
            .ListColumns("NdC").DataBodyRange.Cells(NewRow.Index, 1) = "Marcel"
            'Puis dans la cellule suivante
            'La 2ème colonne
            .ListColumns("TdP").DataBodyRange.Cells(NewRow.Index, 1) = "NC externe" 'ici j'avais fait une boulette
     
            '[...]
     
            'Si tu veux supprimer une ligne
            '.ListRows.Item(2).Delete
     
        End With
    J'avais fait une erreur dans une des ligne de saisie, pour que tu comprennes mieux voila le détail

    Cette partie pointe la colonne TdP, c'est à dire l'entête et les données de la colonne.

    Ici on dit à VBA que ne souhaite travailler que sur les données (il laisse tomber l'entête)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    .Cells(NewRow.Index, 1)
    Ici on lui précise que dans les données de la colonne, on souhaite mettre à jour la cellule qui se trouve en ligne NewRow.Index et en colonne 1 (forcement puisqu'on travail uniquement sur les données d'une colonne), donc ici on aura toujours 1 dans ce cas de figure)

    J'espère que ça ira avec ces explication, si tu n'y arrive pas, propose nous le code que tu as fait en précisant ou cela te pose problème.

    ++
    Qwaz

  10. #10
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Qwazerty,

    J'ai commencer à adapter ton code à mon application, et j'ai une erreur de compilation : Référence incorrecte ou non qualifiée à la ligne 40.
    Cela vient surement que mon Tableau est dans un autre classeur que j'ouvre automatiquement (ligne de code 28 à 33).



    Code 1 : 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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    'Correspond au programme du bouton VALIDER
    Private Sub CommandButton1_Click()
    Dim L As Integer
    Dim Commentaire As String
    Commentaire = TextBox4.Text
    Dim estouvert As Integer
    Dim fich As Workbook
    Dim NewRow As ListRow 'Déclaration d'un objet Row (qui représente une ligne du tableau
     
    'JE/JP option button obligatoire
    Dim x As Object, UneOptionAuMoins1 As Boolean
     
    UneOptionAuMoins1 = False
    For Each x In Frame3.Controls
      UneOptionAuMoins1 = UneOptionAuMoins1 Or x.Value
    Next x
     
    If Not UneOptionAuMoins1 Then
      MsgBox "Veuillez cocher une Entité dans l'onglet Réception !" & vbLf & _
        vbLf & "Validation refusée"
      Exit Sub
    End If
     
     
    If MsgBox("Etes-vous certain de vouloir INSERER cette Non-Conformité ?", vbYesNo, "Demande de confirmation") = vbYes Then
     
    'Verification si "Tbx source" est ouvert sinon l'ouvrir
    estouvert = False
    For Each fich In Workbooks
    If fich.Name = "Tbx source.xlsm" Then estouvert = True
    Next
    If estouvert = False Then Workbooks.Open ("c:\Users\Philippe\SkyDrive\Documents\NC Jone\Tbx source.xlsm")
     
     
     
     
    'Ici tu changes le nom de ta feuille qui contient le tableau, donc Feuil1 à la place de feuil3 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
    'Tu changes le nom de ton tableau, ici c'est Tableau1 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
    With .Feuil2.ListObjects("BdD")
    'On créee une nouvelle ligne et on la pointe avec NewRow
    Set NewRow = .ListRows.Add
     
    'Insertion valeur dans cellules
    .ListColumns("NdC").DataBodyRange.Cells(NewRow.Index, 1) = TextBox1.Value
    .ListColumns("NdP").DataBodyRange.Cells(NewRow.Index, 1) = TextBox2.Value
     
     
            '[...]
     
            'Si tu veux supprimer une ligne
            '.ListRows.Item(2).Delete
     
        End With
     
    'Workbooks("Tbx source.xlsm").Sheets("tbx source").Range("D" & L).Value = Label1
     
     
     
    End If
    End Sub



    J'ai essayé avec :

    Code 1 : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    With Workbooks("Tbx source.xlsm).Feuil2.ListObjects("BdD")

    Mais ça ne marche pas non plus.

    Je ne sais pas comment dire que le Tableau"BdD" est dans un autre classeur.


    Merci d'avance.
    Philippe.

  11. #11
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 906
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 906
    Points : 8 539
    Points
    8 539
    Par défaut
    Salut

    Pense à indenter ton code (placer des tabulation pour décaler l’intérieur des structure.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    Dim aClasseur as Workbook
    '[...]
        If estouvert = False Then Set aClasseur = Workbooks.Open("c:\Users\Philippe\SkyDrive\Documents\NC Jone\Tbx source.xlsm")
     
     
     
     
        'Ici tu changes le nom de ta feuille qui contient le tableau, donc Feuil1 à la place de feuil3 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
        'Tu changes le nom de ton tableau, ici c'est Tableau1 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
        'Ici tu ne précisais pas sur quel classeur tu travailles
        With aClasseur.Feuil2.ListObjects("BdD")
            'On créee une nouvelle ligne et on la pointe avec NewRow
            Set NewRow = .ListRows.Add
    Quand tu utilises Wth, il faut quand même préciser tous les membres, tu avais laissé un .Feuil2 tout seul, mais la feuil2 de quel classeur? il n'y a aucune structure With au dessus pour le préciser (voir l'aide sur With pour plus d'information)

    ++
    Qwaz

  12. #12
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Bonjour Qwazerty,

    Malgré tous tes bon conseils, j'ai encore une erreur (Propriété ou méthode non géré par cet objet) a cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    With TbxSourceClasseur.ListObjects("BdD")
    Je commence à m'arracher les cheveux....
    J'ai retranscris ton code dans un fichier basique ou celui-ci est dans le même classeur que le tableau à remplir et là ça marche du feu de Dieu mais dès que je veux écrire dans un autre classeur ça na marche plus.

    Je te mets mes deux fichiers en Pj.
    Sois clément lorsque tu liras mon code. C'est mon premier code VBA que j'écris (enfin que je recopie à droite à gauche).

    Merci.
    Fichiers attachés Fichiers attachés

  13. #13
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 906
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 906
    Points : 8 539
    Points
    8 539
    Par défaut
    Salut

    Alors je vais noter ce que je vois qui me semble ne pas aller dans l'ordre où je tombe dessus.

    Sur le UserForm, dans la Frame3 (pense à renommer pour donner des noms explicite), les radioboutons qui se trouve dedans ne sont pas totalement configuré (surtout dans le Frame2 qui contient différents groupes), il faut renseigner la propriété GroupeName, comme ça il ne peut y avoir qu'un seuil radiobouton cocher sur l'ensemble des radioboutons ayant le même GroupeName.
    En complément, tu peux mettre un des radiobouton à la valeur true, ainsi tu peux te passer du teste en début de code pour savoir si une option à été choisi.
    Si tu souhaites pouvoir faire plusieurs choix, je te conseilles d'utiliser les CheckBox qui sont plus adapter à un tel besoin.

    Pour le reste j'ai mis des commentaires directement dans le code, tu as de la lecture .

    Pense à indenter ton code avec des tabulations, c'est très important de prendre ce réflexe dès le début, ça te permet de savoir où tu te trouve dans la structure de ton code et de voir si tu as bien refermé toute tes structure (If, With, ...).

    Voila le code et je te joins le fichier modifié

    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    Option Explicit
     
     
     
    Private Sub UserForm_Initialize()
     
        'Récupération du Username dans feuille de données
        With ThisWorkbook.Sheets("Données")
            Label1.Caption = .Range("RécupUserName").Value
            Label4.Caption = .Range("Date").Value
            'Label10.Caption = .Range("ChronoMax").Value + 1 'je la met en commentaire car la cellule contient une erreur de lien, je te laisse la réactiver
            ComboBox2.Value = .Range("Secteur").Value
        End With
     
    End Sub
     
    'Correspond au programme du bouton VALIDER
    Private Sub CommandButton1_Click()
    Dim L As Integer
    Dim Commentaire As String
    Dim EstOuvert As Integer 'Toujours une majuscule dans une variable (ça permet de repérer dans le code une variable mal orthographié)
    Dim Fich As Workbook
    Dim TbxSourceClasseur As Workbook
    Dim NewRow As ListRow 'Déclaration d'un objet Row (qui représente une ligne du tableau
     
    'JE/JP option button obligatoire
    'Ici autant déclarer xCtrl comme étant un controle (+ un nom explicite, sachnat que xCtrl est souvent utilisé dans les code comme étant une variable de type Integer)
    Dim xCtrl As Control, UneOptionAuMoins1 As Boolean
    Dim iCtrl As Integer
     
    'Déclaration Mail
    Dim MailAd As String
    Dim Msg As String
    Dim Subj As String
    Dim URLto As String
     
     
        'initialisation des valeurs
        Commentaire = TextBox4.Text
        UneOptionAuMoins1 = False
     
        'On regarde si une sélection à bien été faite
        For Each xCtrl In Frame3.Controls
                'UneOptionAuMoins1 = UneOptionAuMoins1 Or xCtrl.Value
                If xCtrl.Value Then
                    UneOptionAuMoins1 = True
                    'On quitte la boucle, inutile d'aller plus loin
                    Exit For
                End If
        Next xCtrl
     
        If Not UneOptionAuMoins1 Then
            MsgBox "Veuillez cocher une Entité dans l'onglet Réception !" & vbLf & _
            vbLf & "Validation refusée"
            Exit Sub
        End If
     
     
        If MsgBox("Etes-vous certain de vouloir INSERER cette Non-Conformité ?", vbYesNo, "Demande de confirmation") = vbYes Then
     
            'Verification si "Tbx source" est ouvert sinon l'ouvrir
            EstOuvert = False
            For Each Fich In Workbooks
                If Fich.Name = "Tbx source.xlsm" Then EstOuvert = True
            Next
            'Ici remet le code comme tu as besoin, je modifie uniquement pour coller par rapport à l'emplacement de mon fichier
            'Ici il faut aussi prendre en compte le fichier ouvert et le pointé via la variable TbxSourceClasseur
            If EstOuvert = False Then
                Set TbxSourceClasseur = Workbooks.Open(ThisWorkbook.Path & "\Tbx source.xlsm") '("c:\Users\Philippe\SkyDrive\Documents\NC Jone\Tbx source.xlsm")
            Else
                Set TbxSourceClasseur = Workbooks("Tbx source.xlsm")
            End If
            'On simplifie l'écriture (attention Feuil3 est le codeName de la feuille pas le nom contenu dans l'onglet sous Excel (voir image liée au poste
            'Ici tu changes le nom de ta feuille qui contient le tableau, donc Feuil1 à la place de feuil3 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
            'Tu changes le nom de ton tableau, ici c'est Tableau1 (c'est mieux de les renommer pour que ce soit plus explicite dans le code)
            'Tu nas pas précisé de Feuille ici, il faut Classeur.Feuille.ListObject
             With TbxSourceClasseur.Sheets("tbx Source").ListObjects("BdD")
            'On créee une nouvelle ligne et on la pointe avec NewRow
                Set NewRow = .ListRows.Add
     
            'Insertion valeur dans cellules
                .ListColumns("NdC").DataBodyRange.Cells(NewRow.Index, 1).Value = TextBox1
                .ListColumns("NdP").DataBodyRange.Cells(NewRow.Index, 1).Value = TextBox2
                .ListColumns("Désignation").DataBodyRange.Cells(NewRow.Index, 1).Value = TextBox3
                .ListColumns("Qté").DataBodyRange.Cells(NewRow.Index, 1).Value = ComboBox1.Value
                'Attention à l'orthographe des noms de colonnes
                .ListColumns("Seteur").DataBodyRange.Cells(NewRow.Index, 1).Value = ComboBox2.Value
                .ListColumns("Défaur").DataBodyRange.Cells(NewRow.Index, 1).Value = ComboBox3.Value
                .ListColumns("Emetteur").DataBodyRange.Cells(NewRow.Index, 1).Value = Label1
                .ListColumns("Chrono").DataBodyRange.Cells(NewRow.Index, 1).Value = Label10
                .ListColumns("Date_E").DataBodyRange.Cells(NewRow.Index, 1).Value = Label4
     
                'Il faut absolument renommer tes composants, ça te permettra une meilleur lecture de ton code
                'Ensuite on peut essayer de rendre le code plus léger
     
                'Si il n'y a que deux choix, tu peux faire comme ça (il faut dans ce cas qu'un bouton soit défini à true par défaut)
                'Pour ma part jepense que les optionbouton sont fait pour avoir un bouton coché par défaut,
                'Si tu ne veux pas de valeur par défaut il faut activer la propriété TripleState de l'option bouton pour que l'utilisateur puisse le passer à l'état non coché (dans ce cas la, il faudra modifier la ligne suivante qui ne fonctionnera plus).
                .ListColumns("Entité").DataBodyRange.Cells(NewRow.Index, 1).Value = IIf(OB_JP.Value, "JP", "JE")
                'If OB_JP.Value = True Then .ListColumns("Entité").DataBodyRange.Cells(NewRow.Index, 1) = "JP"
                'If OB_JE.Value = True Then .ListColumns("Entité").DataBodyRange.Cells(NewRow.Index, 1) = "JE"
     
                If TextBox4 > "" Then .ListColumns("Défaut").DataBodyRange.Cells(NewRow.Index, 1).Comment.Text Text:=Commentaire 'Remplit le commentaire
     
                'Avec plusieurs choix, tu peux faire une boucle
                For iCtrl = 1 To 3
                    If Me.Frame2.Controls("OB_T" & CStr(iCtrl)).Value Then
                        .ListColumns("MT").DataBodyRange.Cells(NewRow.Index, 1).Value = "T" & iCtrl
                        Exit For
                    End If
                Next
     
                'If OB_T1.Value = True Then .ListColumns("MT").DataBodyRange.Cells(NewRow.Index, 1) = "T1"
                'If OB_T2.Value = True Then .ListColumns("MT").DataBodyRange.Cells(NewRow.Index, 1) = "T2"
                'If OB_T3.Value = True Then .ListColumns("MT").DataBodyRange.Cells(NewRow.Index, 1) = "T3"
     
                'Inutile de mettre OB.value = true, le "= true" est sous entendu puisque .value est une valeur boolèenne, donc si .value = true renvoie False, c'est que .value = False et donc autant utiliser directement .value... :) Si c'est pas claire redemande j'expliquerais plus en détail.
                .ListColumns("MC").DataBodyRange.Cells(NewRow.Index, 1).Value = IIf(OB_C1.Value, "C1", "C2")
                'If OptionButton9.Value = True Then .ListColumns("MC").DataBodyRange.Cells(NewRow.Index, 1) = "C2"
     
                'Je te laisse faire une boucle ici et renommer tes controls
                If OB_I1.Value = True Then .ListColumns("MI").DataBodyRange.Cells(NewRow.Index, 1).Value = "I1"
                If OB_I2.Value = True Then .ListColumns("MI").DataBodyRange.Cells(NewRow.Index, 1).Value = "I2"
                If OptionButton12.Value = True Then .ListColumns("MI").DataBodyRange.Cells(NewRow.Index, 1).Value = "I3"
                If OptionButton13.Value = True Then .ListColumns("MI").DataBodyRange.Cells(NewRow.Index, 1).Value = "I4"
                If OptionButton14.Value = True Then .ListColumns("MI").DataBodyRange.Cells(NewRow.Index, 1).Value = "I5"
                '[...]
     
                'Si tu veux supprimer une ligne
                '.ListRows.Item(2).Delete
     
            End With
     
     
            'Vider cellules feuille "formulaire"
            'Toujours préciser le classeur
            With ThisWorkbook.Sheets("formulaire")
                .Range("A3:e3").ClearContents
                .Range("A8:e8").ClearContents
                .Range("A14:e14").ClearContents
                .Range("A26:e26").ClearContents
     
                'remplissage feuille "formulaire"
                'Plutôt que Cells dans un cas comme celui la Range est plus adapté il permet une meilleur lecture du code
                'Il est préférable de précisé .Text ou .Caption ou ... ça évite les mauvaise surprise.
                .Range("A8") = Label4.Caption
                .Cells(8, 2) = TextBox1.Text
                .Cells(8, 3) = ComboBox2.Value
                .Cells(8, 4) = Label1.Caption
                .Cells(8, 5) = TextBox2.Text
     
                .Cells(14, 2) = TextBox3.Text
                .Cells(26, 2) = TextBox4.Text
                .Cells(3, 5) = Year(Label4.Caption) & "/" & Label10.Caption
     
     
     
                MsgBox ("Non-Conformité enregistrée") 'Vous informe la NC est insérée dans votre tableau Excel.
     
                'ça fonctionne ça? de décharger le formulaire qui contient le code qui est en cours d'execution ?
                'Unload Me 'Ferme le formulaire
                Me.Hide 'cache juste le formulaire
     
                'Commande pour impression
                .Visible = 1
                .Activate 'Select, Activate fonctionne même si le classeur qui contient la feuille à selectionner n'est pas actif (Select plante dans ce cas)
                'previsualisation
                'Unload Me 'Tu l'as déjà fait
                .PrintPreview
                'pour impression directe enlever le ' devant la ligne suivante et le mettre sur la ligne précédente
                '.PrintOut
            End With
     
            With ThisWorkbook.Sheets("Données")
                'Envoi automatique de mail
                MailAd = .Range("T1").Value
                Subj = .Range("T2").Value
                Msg = Msg & .Range("T10").Value
                URLto = "mailto:" & MailAd & "?subject=" & Subj & "&body=" & Msg
                'ActiveWorkbook.FollowHyperlink Address:=URLto
                ThisWorkbook.FollowHyperlink Address:=URLto
     
                ThisWorkbook.Sheets("Formulaire").Visible = 0
                'Tu peux utiliser les CodeName des feuille, ici j'ai modifié celui de l'onglet d'accueil, tu peux faire de même pour tes autres feuilles, ça allége le code
                F_Accueil.Activate
                'ThisWorkbook.Sheets("Acceuil").Select
            End With
     
        End If
    End Sub

    ++
    Qwaz
    Fichiers attachés Fichiers attachés

  14. #14
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Salut,
    "
    Juste Waouh... Je ne sais pas comment te remercier. J'ai plus appris avec ton code et tes annotations qu'en une semaine de "copiage/collage" de code.
    Je suis entrain de travailler et de comprendre tes remarques, faire une boucle, renommer mes objets.

    J'ai trouvé deux trois trucs qui je dois encore paramétrer comme renvoyer la valeur d'une textebox comme "nombre" ( dans ma colonne "Chronologie") ; edit : ce point est réglé

    Je n'arrive plus à récupérer le n°chrono du classeur "Tbx source" si celui-ci n'est pas ouvert. J'ai donc une erreur dans mon label10 qui est lu à l'initialisation de mon UserForm et me donne une erreur.


    Il faut que je refasse fonctionner cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    If TextBox4 > "" Then .ListColumns("Défaut").DataBodyRange.Cells(NewRow.Index, 1).Comment.Text Text:=Commentaire
    'ça fonctionne ça? de décharger le formulaire qui contient le code qui est en cours d’exécution ? bein oui, ça fonctionnait. cela me permettait de vider le Userform sans être obliger de le fermer et de le ré-ouvrir. Connais-tu un autre moyen pour faire ça ?


    Je ne comprends pas trop ce morceau de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    .ListColumns("MC").DataBodyRange.Cells(NewRow.Index, 1).Value = IIf(OB_C1.Value, "C1", "C2")

    Comment sait-on que l'on doit utiliser les CodeName ou le nom des onglets ?

    Voila, c'est tout pour ce soir. Je continuerais demain.

    Philippe.

  15. #15
    Expert éminent
    Avatar de Qwazerty
    Homme Profil pro
    La très haute tension :D
    Inscrit en
    Avril 2002
    Messages
    3 906
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : La très haute tension :D
    Secteur : Service public

    Informations forums :
    Inscription : Avril 2002
    Messages : 3 906
    Points : 8 539
    Points
    8 539
    Par défaut
    SAlut

    Pour le chrono, vérifie le lien de ta cellule qui pointe dans ton autre classeur.
    Pour voir les liens externe à ton fichier, va dans le bandeau sur l'onglet Données -> Modifier les liens d'accès et regarde si les classeur sources pointés sont bien les bons.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
                If TextBox4.Text > "" Then
                    .ListColumns("Défaut").DataBodyRange.Cells(NewRow.Index, 1).AddComment Commentaire 'Remplit le commentaire
                End If
    Refasse fonctionner ? ou fonctionner tout court ? Comment.Text modifie le texte d'un commentaire existant il me semble.

    Méaculpa pour le Unload, je n'avais pas prit le temps de tester la ligne, en effet ça ne pose pas de problème... étrange.

    IIF permet de condenser une structure If ... else ...
    IIF(Teste, valeur si vrai, valeur si faux)
    IIF est une fonction qui effectue un teste, si le teste retourne vrai IIF retourne "valeur si vrai", sinon elle retourne "valeur si faux"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    .ListColumns("MC").DataBodyRange.Cells(NewRow.Index, 1).Value = IIf(OB_C1.Value, "C1", "C2")
    Ici on teste si OB_C1 est coché, si c'est vrai IIF retourne C1, si c'est faux IIF retourne C2.
    (un petit coup de F1 t'apportera les détails)


    Le CodeName peut être utiliser dans n'importe quel code interne au classeur, il représente une variable locale. Perso je l'utilise le plus souvent possible.
    Avantages :
    • Pas besoin de déclarer le classeur sur lequel on travaille Thisworkbook. Le CodeName étant une variable locale Thisworkbook est sous entendu, ce qui n'est pas le cas de Sheets("...") qui lui prend en compte le classeur actif.... ce qui ne revient pas du tout au même. Ne pas préciser le classeur de travail est à mon sens une erreur.
    • C'est généralement plus court que décrire Thisworkbook.Sheets(".....")
    • Si l'utilisateur change le nom de l'onglet sous Excel... ça ne pose aucun problème.

    A ma connaissance, tu ne peux pas l'utiliser lorsque tu travailles dans un autre classeur que celui ou se trouve ta macro (exemple dans ton code)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    With TbxSourceClasseur.Sheets("tbx Source").ListObjects("BdD")
    ++
    Qwaz

  16. #16
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Salut,

    En ce qui concerne le Chrono, celui-ci se met à jour seulement si le fichier "tbx source" est ouvert. Au pire,j e l'ouvre et je le referme en début de code.
    Il faut que je rebosse la-dessus, à moins que tu as une idée sur le sujet.

    Pour le commentaire, j'avait oublié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    .ListColumns("Défaut").DataBodyRange.Cells(NewRow.Index, 1).AddComment
    avant la ligne pour "écrire le commentaire...."

    Merci pour toutes tes explications qui m'ont été très utiles, même capitales.....

    Encore ce "gentil" n°chrono et j'aurais fini mon projet. Je pourrais alors marquer ce post comme résolu.

    Philippe.

  17. #17
    Membre à l'essai
    Homme Profil pro
    Responsable de Production
    Inscrit en
    Janvier 2015
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Responsable de Production
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2015
    Messages : 25
    Points : 11
    Points
    11
    Par défaut
    Salut Qwazerty,

    Merci encore pour ton aide. J'ai réussi à boucler mon projet.

    La récup du n°Chrono se fait par une commande ADODB.Recordset que j'ai mise en place grâce à un autre fil de discussion.

    Ici : http://www.developpez.net/forums/d14...lasseur-ferme/

    Maintenant je vais peut-être réussir à remplir tout le fichier source sans l'ouvrir.

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

Discussions similaires

  1. [XL-2013] Copier uniquement des cellules non vides sur un autre classeur
    Par tonyfrost dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 20/06/2014, 22h54
  2. [AC-2003] operation sur les ligne et non pas sur les colonnes
    Par omarnigth dans le forum Requêtes et SQL.
    Réponses: 6
    Dernier message: 21/11/2011, 21h25
  3. [XL-2000] Créer une oite de dialogue pour remplir des cellules excel
    Par lionel2b dans le forum Excel
    Réponses: 2
    Dernier message: 19/02/2010, 10h39
  4. [XL-2003] action sur des cellules non vides
    Par bosk1000 dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 25/05/2009, 15h33
  5. Code pour copier des cellules si elles respectent une condition
    Par octane dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 14/11/2008, 06h53

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