Recherche de la lettre d'une colonne

Bonjour,

Comme je trouve toujours réponse à mes questions de béotien, je continue.

Je cherche la lettre d'une colonne.

En procédant ainsi :

Ligne1.Find(What:=Col_Cible, LookAt:=xlPart).Activate
    Lettre_Col_Cible = Split(Selection.Address, "$")(1)

J'obtiens la réponse P: (avec le signe ":")

En procédant ainsi :

 Ligne1.Find(What:=Col_Cible, LookAt:=xlPart).Activate
    ActiveCell.Select
    Lettre_Col_Cible = Split(Selection.Address, "$")(1)

J'obtiens la bonne réponse P (sans ":")

Je ne comprends pas ce que l'instruction ActiveCell.Select vient faire la dedans.

Merci pour votre aide.

Salut Dach2,

pour trouver la lettre d'une colonne spécifique j'utilise ceci mais il y a d'autres formulations...

Target.Column, tu l'auras compris, est le numéro de colonne...

sCol= Split(Columns(Target.Column).Address(ColumnAbsolute:=False), ":")(1)

A+

D'accord curulis57,

Mais ça n'est pas ma question.

Merci quand même.

Bonsoir, Salut Curulis !

C'est toujours une erreur de travailler à coups d'Activate et Select...

Mais pourquoi as-tu besoin de la lettre de colonne ? On s'en passe parfaitement !

Cordialement.

Salut Dach2,

Bien le bonjour MFerrand,

j'imagine que le deuxième procédé provient d'un copier-coller d'un code trouvé ici où là...

Code de novice qui apprend à se dépatouiller...

C'est en forgeant qu'on devient forgeron!

A+

C'est en forgeant qu'on devient forgeron!

Certainement !

Je me souviens avoir traité une fois un classeur dont un nom de feuille était particulièrement long. Pour ne pas avoir à l'écrire, j'ai nommé une cellule de la feuille pour atteindre la feuille par [CRef].Worksheet, sans utiliser son nom. Et depuis j'ai trouvé tellement pratique de pouvoir se passer des feuilles que j'ai quasiment généralisé...

Si le numéro de colonne, toujours assez facile à obtenir; ne suffit pas, il existe divers moyens d'accéder à la colonne sans chercher la lettre et sans même se préoccuper de savoir où se trouve la colonne.

Bonne soirée.

Bonjour à tous les 2 (curulis57 et MFerrand),

Nombre de mes codes sont effectivement des copier/coller de codes trouvés par ci par là, et aussi de codes générés par la fonction "Enregistrer une macro".

Avec tous vos bons conseils, je progresse quand même, et en quelques semaines, j'ai pu ainsi diviser le nombre de lignes de mes codes par 10 au moins.

Et c'est effectivement en forgeant qu'on devient forgeron.

Pour répondre à la question de MFerrand, si je recherche la lettre de la colonne, c'est parce que je recherche la première cellule vide de cette colonne.

J'ai bien le sentiment que mon code est celui d'un débutant, mais je ne demande qu'à apprendre. Je serai très heureux de me passer des Select et Activate.

Voici ce code (je souhaite positionner le curseur sur la première cellule vide de la colonne "Client")

Sub Recherche_Vide()

    Range("A1").End(xlToRight).Columns.Select
    Lettre_DerCol = Split(Selection.Address, "$")(1)
    Set Ligne1 = Range("A1:" & Lettre_DerCol & 1)

    Const Col_Cible As String = "Client"
    Ligne1.Find(What:=Col_Cible, LookAt:=xlWhole).Activate
    ActiveCell.Select
    Lettre_Col_Cible = Split(Selection.Address, "$")(1)
    Numéro_Col_Cible = ActiveCell.Column

    If Not IsEmpty(Cells(Numéro_Col_Cible)) Then Set Lig_Cible = Cells(Numéro_Col_Cible).End(xlDown).Offset(1)
    Numéro_Lig_Cible = Lig_Vide.Row

    MsgBox("Lettre_Col_Cible = " & Lettre_Col_Cible)     'Revoie "Q:" si l'instruction ActiveCell.select est absente (!)

    Range(Lettre_Col_Cible & Numéro_Lig_Vide).Select   

End Sub

Merci pour vos bons conseils.

Salut Dach2,

une façon de faire...

Un double-clic déclenche la macro.

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'
Cancel = True
On Error Resume Next
iCol = Cells.Find(what:="Client", lookat:=xlWhole).Column
If iCol > 0 Then
    sCol = Split(Columns(iCol).Address(ColumnAbsolute:=False), ":")(1)
    iRow = Range(sCol & Rows.Count).End(xlUp).Row + 1
    Range(sCol & iRow).Select
End If
On Error GoTo 0
'
End Sub

A+

16rowselect.xlsm (14.15 Ko)

Bonjour,

Tu devrais rapidement voir qu'à coups de Select, on rame, et en plus on voit plus difficilement les erreurs.

D'abord ton erreur sur P:, elle est générée par ta première ligne, tu sélectionnes la colonne, l'adresse de la sélection renvoyée par Address va donc être $P:$P. Tu peux rapidement voir que logiquement en splittant sur "$" l'élément d'indice 1 sera P:.

Tu ne déclares pas tes variables, donc déjà tu ne les types pas, et elles seront toutes de type Variant. Il est préférable de les déclarer et typer sauf lorsqu'on veut ou doit avoir un Variant (car l'accès au type Variant est plus lent, et cela peut jouer quelques autres tours...) et de les déclarer en début de procédure, car VBA réserve l'espace mémoire nécessaire pour chaque variable et ce sera plus homogène s'il fait ça en une fois.

Ensuite tu dois veiller à les initialiser : Lig_Vide qui logiquement devait accueillir un objet Range ne l'est pas, donc Lig_Vide.Row aura quelque difficulté à renvoyer un numéro de ligne !

Tu sélectionnes la cellule dont la valeur est "Client" en ligne 1, puis tu testes qu'elle n'est pas vide ? Si elle l'était, il n'y aurait pas "Client"... !

Une fois les erreurs rectifiées tu auras utilisé 11 lignes de code pour sélectionner la première cellule vide dans la colonne P. Comme sélectionner la cellule pour ne rien faire n'est pas a-priori l'objectif, la vraie question est : que veux-tu mettre dans cette cellule ? Pour VBA, tu lui dis : telle cellule, y mettre ceci, il le fait, il n'a pas besoin de plus, et toi tu n'auras pas bougé, tu ne te seras pas démené à parcourir ton tableau en long et en large pour arriver jusqu'à la cellule en question.

Ton code reste en outre un peu ambigu. Si tu cherches la dernière ligne du tableau dans la colonne P (Client), il faut que ta colonne P soit homogène, sans vide, sans quoi xlDown n'est pas adéquat, et que ton tableau comporte au moins une ligne servie en plus de la ligne d'en-tête, pour que xlDown fonctionne correctement. C'est pourquoi on lui préfère généralement xlUp, plus sûr.

Par contre, s'il s'agit de trouver un trou dans la colonne à l'intérieur du tableau, xlDown devient plus adéquat...

Mais il y a d'autres façons de trouver la première ligne vide après un tableau de données, notamment si ton tableau ne comporte pas de coupure marquée en ligne, ....Range("A1").CurrentRegion.Rows.Count +1 te la fournira. Et il faut savoir si ton tableau occupe une plage normale ou est constitué en tableau Excel (qui d'une part ne réagit pas de la même façon, et d'autre part auquel on a d'autres moyens d'accéder).

Enfin l'abus de Select, conduit à ne pas qualifier ses expressions, c'est à dire que les objets Range que tu sélectionnes ne sont pas rattachés explicitement à la feuille qui les contient, ce qui conduit VBA à remonter à chaque fois à l'objet Application pour rechercher quel est l'élément actif susceptible de contenir la plage recherchée, ce qui nécessairement ralentit l'exécution.

En supposant un tableau sur plage normale et qu'on veuille cibler la première cellule vide sous le tableau dans la colonne Client :

Sub Recherche_Vide()
    Dim n%, k%
    With ActiveSheet
        On Error Resume Next
        k = .Rows(1).Find("Client", , , xlWhole).Column
        If Err.Number <> 0 Then
            MsgBox "Pas de colonne client !", vbCritical, "Erreur"
            Exit Sub
        End If
        n = .Cells(.Rows.Count, k).End(xlUp).Row + 1
        .Cells(n, k) = "???"
    End With
End Sub

On peut faire avec 2 variables (ligne et colonne de la cellule cherchée), à quoi bon en utiliser plus !

En mettant la feuille active (on est supposée y être, sinon il faudra la désigner par son nom) sous bloc With, VBA la met en mémoire pour y accéder le plus rapidement et toute expression commençant par un point à l'intérieur du bloc réfère à cet objet. On gagne en écriture et en rapidité.

On va rechercher "Client" sur la ligne 1 de la feuille, en prenant la précaution de mettre cette recherche sous gestion d'erreur, car si pas trouvé... ! On occupe quelques lignes à gérer le cas erreur pour la signaler à l'utilisateur et sortir proprement... mais si trouvé, k est initialisée et la proc. continue.

On cherche la dernière ligne dans la colonne (avec xlUp, plus sûr), supposée ne pas comporter de vides et on ajoute 1.

Et on cible la cellule : (n, k) à laquelle on peut directement affecter une valeur.

Cordialement.

edit : Salut Curulis !

Salut les matinaux!

ça me turlupinait...

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'
Dim rCel As Range
'
Set rCel = Cells.Find(what:="Client", lookat:=xlWhole)
If rCel <> "" Then rCel.End(xlDown).Offset(1, 0).Select
'
End Sub

Plus c'est court, plus j'aime!

Mais à sécuriser...

A+

Voilà, le temps d'un petit café pour réaligner les neurones...

Comme le dit si bien MFerrand, autant y mettre directement une valeur plutôt que simplement sélectionner la cellule...

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
'
Dim rCel As Range
'
Set rCel = Cells.Find(what:="Client", lookat:=xlWhole)
If rCel <> "" Then Range(Split(rCel.Address, "$")(1) & Rows.Count).End(xlUp).Offset(1, 0).Select
'
End Sub

Me plaît bien, ce petit code...

A+

Re,

Une version pour le cas d'un tableau Excel :

Sub Recherche_Vide()
    Dim n%, k%
    With ActiveSheet.ListObjects(1)
        On Error Resume Next
        k = WorksheetFunction.Match("Client", .HeaderRowRange, 0)
        If Err.Number <> 0 Then
            MsgBox "Pas de colonne client !", vbCritical, "Erreur"
            Exit Sub
        End If
        With .DataBodyRange
            n = .Rows.Count + 1: If n = 2 And .Cells(1, k) = "" Then n = 1
            .Cells(n, k) = "???"
        End With
    End With
End Sub

Normalement, on raccourcirait en utilisant le nom du tableau mis automatiquement par Excel qui correspond aux données (DataBodyRange), utilisable en VBA de la même façon que les noms de plages. Mais la recherche sur la ligne d'en-tête oblige à passer par l'objet ListObject...

Particularités : on suppose qu'on ne connait pas l'emplacement du tableau dans la feuille, et on ne s'en occupe pas, on se contente de se référer au tableau. En conséquence on utilise Match sur la ligne d'en-tête du tableau qui renverra un numéro de colonne relatif au tableau.

Pour la ligne, on se cadre sur les données et on prend le nombre de lignes +1, avec vérification que si le tableau n'a encore aucune donnée la première ligne est encore vide mais existe dans le tableau, donc si on trouve 2, on vérifie qu'en 1 il y quelque chose, sinon on ramène à 1.

Et la cellule visée est définie par rapport à la plage de donnée (adresse relative).

Cordialement.

Bonjour à tous les 2 (curulis57 et MFerrand),

Et merci pour avoir passé du temps sur mon cas. Et j'apprend plein de trucs.

Il faudrait juste que vous dormiez un peu(premiers conseils donnés après minuit, derniers dès 07h30 !).

Merci MFerrand pour le cours très complet. Pour répondre à 2 de tes questions :

  • Je cherche bien la première cellule vide de ma colonne "Client". Il peut justement y avoir en aval des cellules avec des noms de clients. Toutes les cellules vides de cette colonne sont en anomalie. Je les cherche donc une par une, en commençant par la première (d'où le xlDown).
  • A la fin de la macro, le curseur étant positionné sur la cellule vide, je la remplis manuellement avec le nom du client, que je devine en fonction des informations contenues dans les cellules adjacentes. Je ne connais donc pas à priori le nom du client, je ne peux donc pas indiquer à la macro ce qu'elle doit faire).
Je lance la macro autant de fois que nécessaire (en moyenne 3 à 4 fois pour un tableau de 3000 lignes), jusqu'à ce qu'elle positionne le curseur sur la dernière ligne du tableau. Après corrections manuelles, aucun client ne manque à l'appel.

Encore merci pour vos propositions de code.

Rechercher des sujets similaires à "recherche lettre colonne"