Associer des cellules visibles entre elles après un filtre
Bonjour à tous,
Je rencontre un problème sur une macro VBA.
Voici le principe, je filtre en colonne A la date souhaitée. Une fois le filtre effectué je voudrais en colonne C écrire un texte spécifique et rattacher à ce texte la valeur de la cellule B visible.
Par exemple si je filtre pour "décembre" en colonne A, je voudrais avoir en résultat en colonne C : BL-2020-12-3000.
Tout en tenant compte que des cellules en colonne A et B peuvent être vides.
Si vous avez des solutions pour mon problème je suis preneur car je bloque.
Merci d'avance
GuiGui8731
Re-Bonjour,
J'ai réussi à avancer un peu dans la macro et j'arrive à associer du texte avec la valeur de la colonne voulue.
Mon problème maintenant est que seule la valeur de la première ligne trouvée s'associe avec mon texte. Et de ce fait les valeurs suivantes n'ont pas les bonnes valeurs associées.
Comment faire pour que les valeurs s'associent correctement juste avec les données visibles ?
GuiGui8731
Bonjour,
Heureusement qu'on a un 2è aperçu parce que le problème est pas super clair
Cdlt,
Bonjour 3GB,
Désolé si je n'avais pas été assez clair dès le départ.
Je vais essayer d'être plus précis.
La colonne A indique le nombre d'élément et de ce fait sa position.
La colonne B est une colonne qui est remplie manuellement avec des dates.
En colonne C les valeurs sont ajoutées via une autre macro.
Avec ma userform, quand je sélectionne 2020 en textbox.1 et décembre en textbox.2, la macro me filtre mon tableau avec les cellules vides en colonne D et les dates de décembre en colonne B.
S'il y a des cellules vides en colonne D alors il faut remplir cette colonne avec le texte "BL-2020-12-" et la valeur de la cellule C en face de la cellule B.
Quand je fais tourner la macro, la cellule D se remplie bien avec les critères définis au début mais le numéro associé à mon texte n'est pas bon. Seul le premier numéro de la première ligne visible est gardé et associé aux autres cellules.
GuiGui8731
Mais pourquoi toutes ces conditions et ce filtre ? Pourquoi ne pas le faire automatiquement ? Si on a une date en B et une valeur en C, on remplit D ?
Voici une proposition selon ce qui me semble logique, habituelle avec un tableau structuré, le code dans un module normal, l'exécution au clic sur le bouton (par appel de la procédure) sans tenir compte d'un quelconque filtre :
Cdlt,
Bonjour 3GB,
Déjà merci pour ton aide. Ton fichier marche très bien.
Voici mon dernier problème. J'explique la démarche. Chaque ligne correspond à un projet. La colonne A indique la date à laquelle le projet a commencé.
Si je prends le mois de juin, la macro doit me prendre le mois de juin et tous les autres mois avant juin si ceux-ci n'ont pu être terminés à temps, là où il y a une cellule vide en colonne D.
Si il y a des projets datant de mai et avril, le BL en colonne D doit prendre compte ces mois, où la cellule est vide en D, et mettre un BL-2020-06-N° pour les mois d'avril et de mai, qui feront partie de la facturation du mois de juin pour le client.
Si dans la colonne D, une valeur est déjà rentrée, par exemple j'ai fait la facturation pour février, en D je dois avoir pour les projets datant de janvier et février, BL-2020-02-N°. En faisant la facturation pour décembre, je prends en compte tout ce qui est vide en D sans tenir compte des cellules déjà remplies.
J'ai essayé plusieurs tentatives avec ta macro mais celle-ci me remplace les valeurs déjà existantes.
Y a-t-il un moyen pour ne pas changer les valeurs des cellules en D déjà remplie et ne faire que les cellules vides correspondant au mois voulu ? Tout en gardant si possible la petite userform pour décider du mois et de l'année que l'on veut facturer ?
J'espère avoir été clair dans ma demande.
Merci d'avance
GuiGui8731
Bonjour Guigui,
De ce que je comprends, il faut donc ajouter un BL en colonne D :
- si B et C sont remplies,
- si D est vide bien entendu,
- et si la date en B est antérieure au dernier jour du mois désigné avec l'userform ?
Bonjour 3GB,
Si des cellules en D sont vides et que les cellules associées en B et C sont pleines, alors en fonction du mois écrit en TextBox2 et de l'année écrit en TextBox1 il faut que les cellules vides prennent la forme de BL-TextBox1.Value-TextBox2.Value-N°colonneD. En tenant compte des mois antérieurs du mois écrit si les cellules sont vides aussi en D.
Exemple 1 :
Colonne B : Février 2020 / Mars 2020/ Avril 2020
Colonne C : N° associés remplis
Colonne D : Vides
Userform : TextBox1 = 2020 - TextBox2 = Avril
En colonne D je dois avoir : BL-2020-04-N° pour toutes les cellules
Exemple 2:
Colonne B : Février 2020 / Mars 2020 / Avril 2020 / Mai 2020 / Juin 2020
Colonne C : N° associés remplis
Colonne D : BL-2020-04-N° et vides
UserForm : TextBox1 = 2020 - TextBox2 = Juin
En colonne D je dois avoir : BL-2020-06-N° ainsi que le BL pour Avril fait avant et ainsi de suite.
GuiGui8731
Bonjour 3BG,
Après quelques manip avec mes anciennes lignes de codes sous ma UserForm et celles que tu as crées, j'ai réussi à obtenir ce que je veux j'ai l'impression.
Si je filtre en décembre (en spécifiant dans ma userform que je veux ça prenne les cellules entre août et décembre), et que des cellules sont vides en D, il me remplit bien l'ensemble des cellules visibles par le numéro de BL boulu avec le N° en D associé. Et ne remplace pas les cellules en D contenant déjà un BL.
Je te joins le code ci-dessous pour que tu me dises ce que tu en penses :
Sub Decembre()
Dim cc(), i%
If TextBox1.Value <> "" Then
If TextBox2.Value Like "décembre" Or TextBox2.Value Like "12" Then
Worksheets("Feuil2").Range("$A$1:$D$100").AutoFilter Field:=4, Criteria1:="="
Worksheets("Feuil2").Range("$A$1:$D$100").AutoFilter Field:=2, Operator:= _
xlFilterValues, Criteria2:=Array(1, "10/" & TextBox1.Value, 1, "11/" & TextBox1.Value, 1, "12/" & TextBox1.Value, 1, "08/" & TextBox1.Value)
With Worksheets("Feuil2")
'If .FilterMode Then .ShowAllData
With .Range("A2:D60").SpecialCells(xlCellTypeVisible)
ReDim cc(1 To .Rows.Count)
For i = 1 To .Rows.Count
If .Cells(i, 2).Value <> "" And .Cells(i, 3).Value <> "" And .Cells(i, 4).Value = "" Then
cc(i) = "BL" & "-" & Year(.Cells(i, 2)) & "-" & "12" & "-" & .Cells(i, 3)
Else
cc(i) = ""
End If
Next i
.Cells(1, 4).Resize(UBound(cc), 1) = Application.Transpose(cc)
End With
End With
End If
End If
End Sub
GuiGui8731
Re Guigui,
Je te propose quand même ce que j'ai fait même si ça ne correspondra peut-être pas à ton souhait (bien que je pense avoir saisi avec ton dernier exemple le besoin).
Il y a un code dans le module de la feuille 1, propre au commandbutton, qui alimente la combobox d'un nouvel userform (UF_Filtre) avec la liste des mois au format "MM/AAAA". La liste va du mois de la plus petite date de la colonne B au mois du jour. Ensuite, on montre l'userform.
On choisit la période et on clique (petit code dans le module de UF_Filtre qui, au clic, appelle la macro paramétrée - qui dépend de la période choisie avec la combobox - nommée MAJBL).
Cette macro se trouve dans le module BL et prend la colonne D et y remplace les "" répondant aux conditions que tu as énoncées tout à l'heure par BL-AAAA-MM-N°_colC, où AAAA et MM sont respectivement l'année et le mois de la période issue de la combobox.
A toi de voir
Et pour ton code, je pense qu'il vaut mieux réserver les filtres pour les cas où ils sont nécessaires et également éviter les textbox car cela demande de cadrer la saisie (c'est pour ça que je n'en ai pas tenu compte lors de ma première réponse) contrairement à une liste qui a déjà tout verrouillé vu que le choix est limitatif d'entrée. Sinon, on se perd dans la gestion des cas particuliers... Le but étant de parvenir par améliorations successives à rendre les exécutions dynamiques en "éradiquant" tout paramètre fixe, susceptible de provoquer un bug.
Cdlt,
Bonjour 3GB,
Alors là merci beaucoup, ton code fonctionne parfaitement pour ce que je veux faire.
Il peut même être adapté à ma userform si besoin.
Merci beaucoup pour ton aide et ton temps.
GuiGui8731
Nickel ! Je suis content que ça te plaise et que surtout que ça marche comme tu l'attendais !
Bonne continuation !
Re-bonjour 3BG,
Je reviens vers toi pour une question qui doit être simple pour toi.
Je voudrais ajouter un message d'alerte si jamais tous les BL figurent déjà en colonne D.
Si je fais pour décembre par exemple, et que les BL pour décembre sont déjà en colonne D alors message : tous les BL sont déjà présents.
Peux-tu m'aider là-dessus ?
Merci d'avance
GuiGui8731
Salut Guigui,
Oui, normalement, le code mis à jour répond au moins en partie à ton besoin :
Sub MAJBL(periode$)
Dim mois$, annee$, cc, i%, continuer%
mois = Split(periode, "/")(0): annee = Split(periode, "/")(1)
With Worksheets("Feuil1")
If .FilterMode Then .ShowAllData
With .Range("TAB")
If Application.CountIf(.Columns(4), "BL-" & annee & "-" & mois & "-*") > 0 Then
continuer = MsgBox("Cette période a déjà été traitée !" & vbLf & vbLf & "Voulez-vous continuer ?", _
vbInformation + vbYesNo, "Demande de confirmation")
If continuer <> vbYes Then Exit Sub
End If
cc = Application.Transpose(.Columns(4))
For i = 1 To .Rows.Count
If .Cells(i, 2).Value <> "" And .Cells(i, 3).Value <> "" Then
If .Cells(i, 2) < Application.EoMonth(DateSerial(annee, mois, 1), 0) Then
If cc(i) = "" Then cc(i) = "BL" & "-" & annee & "-" & mois & "-" & .Cells(i, 3)
End If
End If
Next i
.Columns(4) = Application.Transpose(cc)
End With
End With
End SubMais, pour l'instant, seule la période demandée est examinée... C'est-à-dire que si tu choisis 12/2020 et qu'il existe un BL avec 2020-12, il y aura le message. Cependant, s'il existe n'en existe pas mais qu'il existe un BL d'une période postérieure (2021-01), il n'y aura pas de message...
Cdlt,
Et au cas où, pour avoir le message quand une période postérieure à déjà été traitée :
Sub MAJBL(periode$)
Dim mois$, annee$, cc, i%
mois = Split(periode, "/")(0): annee = Split(periode, "/")(1)
With Worksheets("Feuil1")
If .FilterMode Then .ShowAllData
With .Range("TAB")
For i = 1 To .Rows.Count
If .Cells(i, 4) <> "" Then
If Split(.Cells(i, 4), "-")(1) * 100 + Split(.Cells(i, 4), "-")(2) >= annee * 100 + mois Then
continuer = MsgBox("Cette période a déjà été traitée !" & vbLf & vbLf & "Voulez-vous continuer ?", _
vbInformation + vbYesNo, "Demande de confirmation")
If continuer <> vbYes Then Exit Sub
Exit For
End If
End If
Next i
cc = Application.Transpose(.Columns(4))
For i = 1 To .Rows.Count
If .Cells(i, 2).Value <> "" And .Cells(i, 3).Value <> "" Then
If .Cells(i, 2) < Application.EoMonth(DateSerial(annee, mois, 1), 0) Then
If cc(i) = "" Then cc(i) = "BL" & "-" & annee & "-" & mois & "-" & .Cells(i, 3)
End If
End If
Next i
.Columns(4) = Application.Transpose(cc)
End With
End With
End SubCdlt,
Bonjour 3BG,
La mise à jour de ton code correspond tout à fait à mes attentes et marche parfaitement.
Encore merci de ton aide pour ce coup.
Bonne fin de weekend à toi.
GuiGui8731
Au cas où, j'ai édité le second code pour alléger la condition... Je ne sais pas si tu as eu le temps de le tester (si c'est le cas, tu es rapide).
Merci, très bon dimanche à toi !