Execution macro automatique, changement valeur
Bonjour,
Je dispose d'un fichier avec 400 lignes et une vingtaine de colonnes. Pour le moment, j'ai une macro qui enregistre des infos de ce tableau dans d'autres fichiers excels qu'il crée s'ils n'existent pas et les modifie si les données du tableau source changent. Le problème c'est que pour l'instant pour le faire cela ouvre et recherche chaque fichier même si je ne change qu'une ligne du tableau. Cela prend donc environ 5 min. Je précise que pour le moment j'actionne la macro avec un bouton.
Je souhaiterai faire en sorte que la macro vérifie les données dont la valeur a changé et qu'elle mette à jour les dossiers s'y rapportent uniquement.
Comment puis-je faire ?
Je joins mes fichiers pour vous donner une idée des tableaux ainsi que la macro dans la liste client :
Option Explicit
Sub test3()
Dim Sh1 As Worksheet, Sh2 As Worksheet, Wb1 As Workbook, Wb2 As Workbook, Ch1$, Ch2$, i&, j%, b%
'chemin vers le doossier client à adapter
Ch1 = "C:\Users\DerJul\Desktop\Stage L3\internet\clients\mission comptable\"
'nom complet classeur matrice à adapter
Ch2 = "C:\Users\DerJul\Desktop\Stage L3\internet\Matrice prévisions clients internet.xls"
'déclaration classeur et feuille données client
Set Wb1 = ThisWorkbook
Set Sh1 = Wb1.Worksheets("Feuil1")
'pour chaque ligne de la feuille données client
For i = 4 To Sh1.Cells(Rows.Count, 1).End(xlUp).Row
'si le classeur portant le nom du client n'existe pas à l'endroit spécifié
If Dir(Ch1 & Sh1.Cells(i, 1) & ".xlsm") <> "" = False Then
Workbooks.Open Ch2 'ouvrir le classeur matrice
Set Wb2 = Workbooks("Matrice prévisions clients internet.xls")
Set Sh2 = Wb2.Worksheets("prévisions en cours")
'remplir les informations dans le classeur matrice
Sh2.Cells(2, 2) = Sh1.Cells(i, 1)
Sh2.Cells(3, 2) = Sh1.Cells(i, 3)
Sh2.Cells(5, 2) = Sh1.Cells(i, 24)
Sh2.Cells(6, 3) = Sh1.Cells(i, 7)
'sauvegarder le classeur matrice sous le nom du client
Wb2.SaveAs Ch1 & Sh1.Cells(i, 1) & ".xlsm", FileFormat:=52
'pour xls ActiveWorkbook.SaveAs Ch1 & w.Cells(i, 1) & ".xls", FileFormat:=56
'pour xlsx : ActiveWorkbook.SaveAs Ch1 & w.Cells(i, 1) & ".xlsx", FileFormat:=51
Else 'sinon
Workbooks.Open Ch1 & Sh1.Cells(i, 1) & ".xlsm" 'ouvrir le classeur client
Set Wb2 = Workbooks(Sh1.Cells(i, 1) & ".xlsm")
Set Sh2 = Wb2.Worksheets("prévisions en cours")
'vérifier les infos et actualiser si nécessaire
If Sh2.Cells(2, 2) <> Sh1.Cells(i, 1) Then
Sh2.Cells(2, 2) = Sh1.Cells(i, 1)
b = True
End If
If Sh2.Cells(3, 2) <> Sh1.Cells(i, 3) Then
Sh2.Cells(3, 2) = Sh1.Cells(i, 3)
b = True
End If
If Sh2.Cells(5, 2) <> Sh1.Cells(i, 24) Then
Sh2.Cells(5, 2) = Sh1.Cells(i, 24)
b = True
End If
If Sh2.Cells(6, 3) <> Sh1.Cells(i, 7) Then
Sh2.Cells(6, 3) = Sh1.Cells(i, 7)
b = True
End If
'sauvegarder si au moins une modif
If b Then Wb2.Save
End If
'fermer le classeur créé ou modifié
Wb2.Close
Next i
End SubMerci de votre aide
Bonjour,
Est-ce que sur ton fichier principal l'on peu ajouter une colonne en Y par exemple, masquée si tu veux même,?
Cette colonne servirait à noter la date du fichier de données associé .
il suffirait de tester si la date du fichier disponible est la même que celle de la colonne Y.
Si cette solution te conviens je peux regarder pour l'intégrer dans ton code , code qu'il faudrait d'ailleurs nettoyer et optimiser
Salut DerJul et le forum
Tu travailles en xlsm (version 2007 et suivantes), je n'ai que 2003. Donc, je ne peux donner que ce que je ferais à un fichier xlsComment puis-je faire ?
Clic-Droit sur le nom de l'onglet => menu contextuel>>Visualiser le code
Case de Gauche, avec le menu Déroulant : Worksheet
Case de droite avec le menu déroulant : Change
Tu te retrouves avec une macro Worksheet_Change qui se lance à chaque sortie du mode édition de cellules.
Ton code sera de ce style :
Private Sub Worksheet_Change(ByVal Target As Range)
'Déclaration =====================================
Dim Sh1 As Worksheet, Sh2 As Worksheet, Wb1 As Workbook, Wb2 As Workbook, Ch1$, Ch2$, i&, j%, b%
Dim Cel As Range, Plage As Range
'Validité ========================================
Set Plage = Intersect(Target, Union(Columns(1), Columns(3), Columns(7), Columns(24)))
If Plage Is Nothing Then Exit Sub
'Traitement =====================================
For Each Cel In Plage
'travail à faire
End If
End SubSi Target (variable contenant les cellules modifiées, mise à jour par Exccel) contient des cellules des colonnes 1, 3, 7, 24, les mettre dans Plage
Si Plage n'est pas vide, s'occuper de chacune d'elle (travail à faire ).
Je ne peux pas aller plus loin, parce qu'il faut raisonner différemment quand on utilise une macro à lancement automatique :
- Quelque soit le nombre de cellules modifiées (target peut concerner plusieurs cellules par copier/coller), elle doit assurer son travail => c'est la raison de la boucle Cel.
- Je veux modifier les cellules 1, 3, 7 et 24 d'une même ligne : soit je fais un savant copier/coller et ça marche. Mais c'est complexe. Ce qui va se passer, c'est que je vais, généralement, modifier une cellule, puis la suivante, puis la troisième, puis la dernière. Pour moi, c'est une modif unique. Mais pour Excel, cela représente 4 modifs distinctes. On pourrait interpréter le changement de ligne des cellules qui sont modifiées. Mais, on ne peux s'y fier, un Enter est si vite arrivé.
- On peut stocker les lignes ayant subies une modification, et sur un autre évènement (changement de feuille, fermeture du classeur, etc...) déclencher les modifications du/des classeur(s). Ou avec simplement un bouton.
A+
Bonjour Misterno, Gorfael et vous autres
Après réflexion et quelques recherches et je voudrai savoir s'il est possible d'avoir une macro qui me fasse ceci : je me disais qu'il existait peut-être un moyen d'afficher une valeur (0 ou 1) dans une colonne à la fin de mon tableau de ma liste clients ou la valeur 1 apparaitrait pour chaque modification de ligne et qu'ainsi la macro mettrait à jour uniquement les lignes où la case serait remplie avec un 1.
Je ne sais pas si c'est très clair ? N'hésitez pas à me demander des éclaircissements.
Misterno : Comment puis-je optimiser cette macro ?
Merci de votre aide
Salut DerJul et le forum
C'est plus dur de définir ce qu'on veut réellement que de le coder
Private Sub Worksheet_Change(ByVal Target As Range)
'Déclaration =====================================
Dim Cel As Range, Plage As Range, x
'Validité ========================================
Set Plage = Intersect(Target, Range([A2], Range("Y" & Cells(Rows.Count, "A").End(xlUp).Row)))
If Plage Is Nothing Then Exit Sub
'Traitement =====================================
For Each Cel In Plage
Cells(Cel.Row, "Z") = 1
Next Cel
End SubSi on édite une cellule de la plage A2 à (Y et dernière ligne non vide en A), mettre 1 dans la colonne Z
À mettre dans le module de la feuille concernée. Dans ce que tu nous a donné, dans le module lié à Feuil1 du fichier liste clients essai internet 3.xlsm (si j'ai bien compris)
Petite remarque : sur cette feuille, les lignes sont séparées en deux couleurs clair pour les paires et foncées pour les impaires. Je ne te souhaites pas la suppression d'un client
Il existe des possibilités avec des MFC qui maintiennent la différence de couleurs des lignes. par exemple : =IMPAIR(LIGNE())=LIGNE()
A+
Bonjour,
En déplaçant mon tableau de la liste clients de 2 lignes vers le haut et avec ce code que l'on m'a donné, la colonnes Y prends la valeur 0 à l'ouverture du fichier et 1 à chaque modification de ligne, le but étant de mettre à jour les lignes avec 1 en colonne Y.
Je n'arrive pas à écrire quelque chose (où alors je ne sais pas où le placer dans les feuilles/workbook etc..) qui me fasse "si 1 appliquer le programme i" , le programme i étant celui mettant à jour les fichiers liés.
Voici le code dans ThisWorkbook :
Option Explicit
Private Sub Workbook_Open()
Dim w1 As Worksheet, Rw&, Cl%
Set w1 = Worksheets("Feuil1")
Rw = w1.Cells(Rows.Count, 1).End(xlUp).Row
Cl = w1.Cells(1, Columns.Count).End(xlToLeft).Column
w1.Range(w1.Cells(2, Cl), w1.Cells(Rw, Cl)) = 0
End Sub
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Dim w1 As Worksheet, Rw&, Cl%, i&
Set w1 = Worksheets("Feuil1")
Rw = w1.Cells(Rows.Count, 1).End(xlUp).Row
Cl = w1.Cells(1, Columns.Count).End(xlToLeft).Column
For i = 2 To Rw
If w1.Cells(i, Cl) = 1 Then Call test(i&)
Next i
End SubEt le code dans Feuil1 :
Option Explicit
Sub test(i&)
Dim Sh1 As Worksheet, Sh2 As Worksheet, Wb1 As Workbook, Wb2 As Workbook, Ch1$, Ch2$, j%, b%
'chemin vers le doossier client à adapter
Ch1 = "C:\Users\DerJul\Desktop\Stage L3\internet\clients\mission comptable\"
'nom complet classeur matrice à adapter
Ch2 = "C:\Users\DerJul\Desktop\Stage L3\internet\Matrice prévisions clients internet.xls"
'déclaration classeur et feuille données client
Set Wb1 = ThisWorkbook
Set Sh1 = Wb1.Worksheets("Feuil1")
'pour chaque ligne de la feuille données client
'si le classeur portant le nom du client n'existe pas à l'endroit spécifié
If Dir(Ch1 & Sh1.Cells(i, 1) & ".xlsm") <> "" = False Then
Workbooks.Open Ch2 'ouvrir le classeur matrice
Set Wb2 = Workbooks("Matrice prévisions clients internet.xls")
Set Sh2 = Wb2.Worksheets("prévisions en cours")
'remplir les informations dans le classeur matrice
Sh2.Cells(2, 2) = Sh1.Cells(i, 1)
Sh2.Cells(3, 2) = Sh1.Cells(i, 3)
Sh2.Cells(5, 2) = Sh1.Cells(i, 24)
Sh2.Cells(6, 3) = Sh1.Cells(i, 7)
'sauvegarder le classeur matrice sous le nom du client
Wb2.SaveAs Ch1 & Sh1.Cells(i, 1) & ".xlsm", FileFormat:=52
'pour xls ActiveWorkbook.SaveAs Ch1 & w.Cells(i, 1) & ".xls", FileFormat:=56
'pour xlsx : ActiveWorkbook.SaveAs Ch1 & w.Cells(i, 1) & ".xlsx", FileFormat:=51
Else 'sinon
Workbooks.Open Ch1 & Sh1.Cells(i, 1) & ".xlsm" 'ouvrir le classeur client
Set Wb2 = Workbooks(Sh1.Cells(i, 1) & ".xlsm")
Set Sh2 = Wb2.Worksheets("prévisions en cours")
'vérifier les infos et actualiser si nécessaire
If Sh2.Cells(2, 2) <> Sh1.Cells(i, 1) Then
Sh2.Cells(2, 2) = Sh1.Cells(i, 1)
b = True
End If
If Sh2.Cells(3, 2) <> Sh1.Cells(i, 3) Then
Sh2.Cells(3, 2) = Sh1.Cells(i, 3)
b = True
End If
If Sh2.Cells(5, 2) <> Sh1.Cells(i, 24) Then
Sh2.Cells(5, 2) = Sh1.Cells(i, 24)
b = True
End If
If Sh2.Cells(6, 3) <> Sh1.Cells(i, 7) Then
Sh2.Cells(6, 3) = Sh1.Cells(i, 7)
b = True
End If
'sauvegarder si au moins une modif
If b Then Wb2.Save
End If
'fermer le classeur créé ou modifié
Wb2.Close
End Sub
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim Cl%, c As Range
Cl = Cells(1, Columns.Count).End(xlToLeft).Column
For Each c In Target
If c.Row > 1 And c.Column < Cl And Cells(c.Row, 1) <> "" Then
Cells(c.Row, Cl) = 1
End If
Next c
End SubLe 0 et le 1 si modification fonctionnent mais pas le :
For i = 2 To Rw
If w1.Cells(i, Cl) = 1 Then Call test(i&)
Next i
End SubDans ThisWorkbook.
Comment puis-je faire ?
-- 04 Juil 2011, 14:37 --
Finalement j'ai mis le code de test (i) dans un module standard et changé (i&) en (i) pour le call test et ça fonctionne
Merci
- Messages
- 9'245
- Excel
- Vista Office 2007FR
- Inscrit
- 08/12/2007
- Emploi
- retraité Sce.Méthodes
si c'est résolu