Problème sur différentes macros

Moonshine

XLDnaute Nouveau
Bonjour,

J’ai quelques soucis avec des macros que je tente de mettre en place dans un fichier Excel (que je joins à ce message).
1er problème : lors du double clic dans la colonne H, j’active une première macro (nommée « Indicateur ») qui pose un problème, car je veux ensuite qu’une deuxième macro s’active (macro « Calendar ») dans cette cellule et au niveau du code je n’arrive pas à coder pour qu’à la fin de la macro indicateur la sélection revienne sur la cellule où j’avais cliqué.
2ème problème : il concerne ma macro Calendar, lorsque je clique sur une date dans le calendrier qui s’affiche, si le chiffre que j’ai sélectionné se situe entre 1 et 12, le code me met ce chiffre en mois alors que je le veux en jour. Par contre cela marche comme je veux à partir du 13 du mois…
3ème problème : je souhaiterais faire une macro conditionnelle entre la feuille « Planning général » et « Planning de sortie ». Je voudrais que cette macro recherche dans la feuille « Planning général », colonne G, toutes les dates qui se situent entre celles définies dans la feuille « Planning de sortie » (cellule B2 et D2), et qu’à chaque fois qu’il trouve une date dans la feuille « Planning général », il copie la ligne entière de cette cellule trouvée dans la feuille « Planning de sortie ».

Merci d’avance pour votre patience !
 

Pièces jointes

  • Exemple Excel_1.xlsm
    144.4 KB · Affichages: 57

Gorfael

XLDnaute Barbatruc
Re : Problème sur différentes macros

Salut Moonshine et le forum
J’ai quelques soucis avec des macros que je tente de mettre en place dans un fichier Excel (que je joins à ce message).
Pour qu'on puisse t'aider, il ne suffit pas de donner un code "faux" ! Il faut aussi expliquer ce qu'il est censé devoir faire... sinon, on interprète, avec une chance qu'on réponde juste, mais il y a la Loi de Murphy qui rôde...
1er problème : lors du double clic dans la colonne H, j’active une première macro (nommée « Indicateur ») qui pose un problème, car je veux ensuite qu’une deuxième macro s’active (macro « Calendar ») dans cette cellule et au niveau du code je n’arrive pas à coder pour qu’à la fin de la macro indicateur la sélection revienne sur la cellule où j’avais cliqué.
Solution simple : ne pas utiliser les Select/Activate, qui ne servent qu'à ralentir le code.
2ème problème : il concerne ma macro Calendar, lorsque je clique sur une date dans le calendrier qui s’affiche, si le chiffre que j’ai sélectionné se situe entre 1 et 12, le code me met ce chiffre en mois alors que je le veux en jour. Par contre cela marche comme je veux à partir du 13 du mois…
Là, je ne sais pas, n'ayant pas le problème.

J'ai retravaillé tes macros de la feuille "Planning Général". N'ayant qu'une version 2003, je n'ai touché qu'au code, sans le tester : la conversion me fait des misères et je ne connais pas le but réel des macros
Code:
Sub Date_prévisionnelle()
Dim i As Long
Dim Nb_Lignes As Long

Nb_Lignes = Range("F" & Rows.Count).End(xlUp).Row
i = 6
Range("G6:G500").ClearContents

For i = 6 To Nb_Lignes
    Select Case Range("F" & i)
        Case "Hebdomadaire"
            Range("G" & i) = Range("H" & i) + 7
        Case "Bimensuel"
            Range("G" & i) = Range("H" & i) + 15
        Case "Mensuel"
            'Range("G" & i) = Range("H" & i) + 30
            Range("G" & i) = DateSerial(Year(Range("H" & i)), Month(Range("H" & i)) + 1, Day(Range("H" & i)))
        Case "Trimestriel"
            'Range("G" & i) = Range("H" & i) + 91
            Range("G" & i) = DateSerial(Year(Range("H" & i)), Month(Range("H" & i)) + 3, Day(Range("H" & i)))
        Case "Quadrimestriel"
            'Range("G" & i) = Range("H" & i) + 122
            Range("G" & i) = DateSerial(Year(Range("H" & i)), Month(Range("H" & i)) + 4, Day(Range("H" & i)))
        Case "Semestriel"
            'Range("G" & i) = Range("H" & i) + 182
            Range("G" & i) = DateSerial(Year(Range("H" & i)), Month(Range("H" & i)) + 6, Day(Range("H" & i)))
        Case "Annuel"
            'Range("G" & i) = Range("H" & i) + 365
            Range("G" & i) = DateSerial(Year(Range("H" & i)) + 1, Month(Range("H" & i)), Day(Range("H" & i)))
        Case "Biennal"
            'Range("G" & i) = Range("H" & i) + 730
            Range("G" & i) = DateSerial(Year(Range("H" & i)) + 2, Month(Range("H" & i)), Day(Range("H" & i)))
        Case "Quinquénal"
            'Range("G" & i) = Range("H" & i) + 1827
            Range("G" & i) = DateSerial(Year(Range("H" & i)) + 5, Month(Range("H" & i)), Day(Range("H" & i)))
    End Select
Next
End Sub
Il faut être le plus logique possible : si la variable "i" va de 6 à NB_Lignes, il doit être du même type que NB_Lignes, pour être sûr de ne pas créer un dépassement valeur. Vu que c'est une variable ligne, je la déclare toujours en long.

Se limiter à 65536 lignes, alors que c'est une version Excel supérieure à 2003, c'est se créer des problèmes dans le futur => mieux vaut laisser excel choisir.

Ajouter des nombres de jours quand on parle de mois, années risque des décalages dans le temps(10/01/2011=> on finit au 5/12/2011 et au 29/01/2013, en ajoutant 30 jours chaque mois). Il vaut mieux demander à excel d'ajouter le type de donnée voulue.

Faire une succession de If concernant la même donnée n'est pas la meilleure façon de régler le problème. Je préfère utiliser dans ce cas "Select Case".
Code:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.Column = 8 Then
    Cancel = True
   Indicateur
   Calendar
ElseIf Target.Column = 9 Then
    Cancel = True
    Calendar
End If
End Sub
Mettre Cancel à Vrai annule ce qui se passe en double-cliquant (entrée dans la cellule).

Un exemple de traitement multiple d'une donnée, autre que Select Case. N'aimant pas utiliser ActiveCel, je l'ai remplacée par target.
Code:
Sub Indicateur()
Dim Cel As Range
   
Set Cel = ActiveCell
Rows(Cel).Copy Sheets("Indicateur").Cells(Sheets("Indicateur").Cells.Find("*", , , , , xlPrevious).Row + 1, "A")
Application.CutCopyMode = False
End Sub
Pas sûr de moi sur ce coup, à cause de la méthode Find, mais le principe reste le même : il n'est nul besoin de sélectionner pour copier (à condition que la feuille soit bien spécifiée, si c'est nécessaire).
Code:
Sub Calendar()
Dim Réponse As Integer

Userform1.Show
Réponse = MsgBox(msg, vbYesNo, "La date est-elle correcte ?")
If Réponse = vbNo Then
    MsgBox "Entrer une nouvelle date"
    Userform1.Show
End If
End Sub
Je ne suis pas sûr du but de cette macro : on donne une seconde chance ? Pas très logique, parce que si on se trompe, on n'a pas de troisième possibilité prise en compte. Soit on teste la validité de la date à chaque fois (en sortie de l'USF, ça me semblerai le mieux, avant d'inscrire, ou à chaque inscription), soit on ne teste pas, et on suppose que la personne sera assez intelligente pour vérifier.

3ème problème : je souhaiterais faire une macro conditionnelle entre la feuille « Planning général » et « Planning de sortie ». Je voudrais que cette macro recherche dans la feuille « Planning général », colonne G, toutes les dates qui se situent entre celles définies dans la feuille « Planning de sortie » (cellule B2 et D2), et qu’à chaque fois qu’il trouve une date dans la feuille « Planning général », il copie la ligne entière de cette cellule trouvée dans la feuille « Planning de sortie ».
Module de la feuille "Planning de sortie"
Code:
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Target.address(0, 0) = "B2" Or Target.address(0, 0) = "D2" Then
    Cancel = True
    Userform1.Show
End If
End Sub

Private Sub Worksheet_Change(ByVal Target As Range)
On Error GoTo Err_Worksheet_Change
' en cas d'erreur excel, aller à l'adresse Err_Worksheet_Change
Dim X As Long, Y As Long

If Target.address(0, 0) <> "B2" Or Target.address(0, 0) <> "D2" Then GoTo Sortie_Worksheet_Change
'si l'adresse relative de target différente de B2 et de D2, aller à la sortie
If [B2] <> "" And [D2] <> "" Then
'Si B2 et D2 sont remplies, alors
    If [B2] > [D2] Then
    'si B2 spérieure à D2 (fin avant début de période)
        Application.EnableEvents = False
        'on bloque la gestion des évènements
        MsgBox "La date en D2 doit être supérieure ou égale à celle de B2 !", vbCritical + vbOKOnly, _
                  "Erreur de date"
        'message d'erreur
        [D2] = ""
        'remise à vide de D2
        GoTo Sortie_Worksheet_Change
        'on va directement à la sortie
    End If
    'sinon, si B2 et D2 sont correctes (sous-entendu, puisqu'on est arrivé à cette ligne)
    Y = Range("A1").SpecialCells(xlCellTypeLastCell).Row
    'y=dernière ligne de la feuille
    X = IIf(Y < 8, 8, Y)
    'x= dernière ligne de la feuille si elle est supérieur à 8, sinon 8
    Range("A8:I" & X).Clear
    'on efface de A8:Ix (ancien résultat)
    Y = 8
    With Sheets("Planning général")
    'Feuille en préfixe pour les instruction commençant par "."
        For X = 6 To .Cells(Rows.Count, "G").End(xlUp).Row
        'Pour X=6 à dernière non vide de G de la feuille "Planning général" (mise en préfixe)
            If [B2] <= .Cells(X, "G") And .Cells(X, "G") <= [D2] Then
            'si B2=<Gx=<D2, alors
                .Rows(X).Copy Rows(Y)
                'Copier la ligne sur la ligne Y
                Y = Y + 1
                'augmenter de 1 Y
            End If
        Next X
    End With
End If
Sortie_Worksheet_Change:                                    'Adresse de sortie
Application.EnableEvents = True                             'Rétablir gestion évènements
Exit Sub                                                    'sortir
Err_Worksheet_Change:                                       'adresse de gestion d'erreur
MsgBox Err.Description, , "Erreur Excel n°" & Err.Number    'message (descrpition+numéro d'erreur)
Resume Sortie_Worksheet_Change                              'continuer à l'adesse de sortie
End Sub
J'utilise deux macros automatiques : la première, tu connais
la seconde se lance quand on modifie la feuille (quand on passe la feuille en mode Édition)
-On vérifie qu'on a changé soit B2, soit D2 => si aucun n'est vide, on vérifie que la période commence avant de finir => si ce n'est pas le cas, on efface D2 et on sort
- on efface les anciennes lignes
- on copie les lignes de la feuille "Planning général" sur la feuille active (Planning de sortie)
Comme j'ai renseigné la macro, le code devrait être suffisamment explicite.
Attention toutefois, je ne l'ai pas testé (code simple, et problèmes venant du passage de 2007/2010 à 2003 fréquents). Mais une erreur esr si vite arrivée...
A+
Edit : adresse relative s'écrit .address(0,0)
 
Dernière édition:

Moonshine

XLDnaute Nouveau
Re : Problème sur différentes macros

Gorfael,
Je me suis penchée sur ce que tu m'as donné. Merci pour les corrections concernant le calcul des dates, c'est très utile.
Ensuite, pour la macro "Indicateur", j'ai essayé la tienne, les cellules que je voulais ne sont pas copiées.. En fait le code que l'on m'avait donné était bien, sauf ce que j'ai mis en rouge :
Sub Indicateur()

a = ActiveCell.Row
Rows(a).Select
Selection.Copy
Sheets("Indicateur").Select
num = Sheets("Indicateur").Cells.Find("*", , , , , xlPrevious).Row
Sheets("Indicateur").Cells(num + 1, 1).Select
ActiveSheet.Paste
Sheets("Indicateur").Cells(num + 1, 1).Select
Sheets("Planning général").Select
Sheets("Planning général").Cells(6, 8).Select
Application.CutCopyMode = False

End Sub
A la place de ce 6 ( qui était un test), il me faudrait mettre un code du genre "coordonnées de ligne de la cellule double cliquée"

Enfin, j'ai essayé ta macro pour la page "planning de sortie". En fait je voudrais qu'elle s'active lors du clic sur mon bouton "actualiser", je n'ai pas réussi à modifier ton code pour ça...

Merci pour ton aide !
 

Gorfael

XLDnaute Barbatruc
Re : Problème sur différentes macros

Salut Moonshine et le forum
Application directe de la Loi de Murphy :p

si c'est bien de la macro Worksheet_Change que tu parles :
Code:
Sub Test()
Dim X As Long, Y As Long

If [B2] <> "" And [D2] <> "" Then
'Si B2 et D2 sont remplies, alors
    If [B2] > [D2] Then
    'si B2 spérieure à D2 (fin avant début de période)
        MsgBox "La date en D2 doit être supérieure ou égale à celle de B2 !", vbCritical + vbOKOnly, _
                  "Erreur de date"
        'message d'erreur
        [D2] = ""
        'remise à vide de D2
        Exit Sub
        'on va directement à la sortie
    End If
    'sinon, si B2 et D2 sont correctes (sous-entendu, puisqu'on est arrivé à cette ligne)
    Y = Range("A1").SpecialCells(xlCellTypeLastCell).Row
    'y=dernière ligne de la feuille
    X = IIf(Y < 8, 8, Y)
    'x= dernière ligne de la feuille si elle est supérieur à 8, sinon 8
    Range("A8:I" & X).Clear
    'on efface de A8:Ix (ancien résultat)
    Y = 8
    With Sheets("Planning général")
    'Feuille en préfixe pour les instruction commençant par "."
        For X = 6 To .Cells(Rows.Count, "G").End(xlUp).Row
        'Pour X=6 à dernière non vide de G de la feuille "Planning général" (mise en préfixe)
            If [B2] <= .Cells(X, "G") And .Cells(X, "G") <= [D2] Then
            'si B2=<Gx=<D2, alors
                .Rows(X).Copy Rows(Y)
                'Copier la ligne sur la ligne Y
                Y = Y + 1
                'augmenter de 1 Y
            End If
        Next X
    End With
Else
    MsgBox "vous n'avez pas rempli B2 ou D2"
End If
End Sub
N'ayant plus de lancement automatique, je peux supprimer la gestion des erreurs.
Il me semble préférable que ton bouton lance une macro qui lancera les autres, une par une.
A+
 

Moonshine

XLDnaute Nouveau
Re : Problème sur différentes macros

parfait c'est exactement ça! merci beaucoup. désolée de ne pas avoir été assez explicite la première fois! Sinon pas d'idées pour coder qqch qui trouve le numéro de la ligne de la cellule sur laquelle j'ai cliqué ?
Bonne soirée !
 

Discussions similaires

Réponses
5
Affichages
220

Statistiques des forums

Discussions
312 361
Messages
2 087 626
Membres
103 611
dernier inscrit
sebboes