Je suis débutante en VBA et nouvelle dans ce forum.
J'essaye d'élaborer un projet en VBA qui se compose de de 2 userforms:
1. USF1 : Permet de sélectionner / créer une feuille de calcul dans le classeur EXCEL. Une fois le choix de la feuille arrêté, la procédure crée un tableau structuré avec le code:
2. USF2: est un formulaire de saisie, contient les contrôles à remplir avec les données qui seront transférées dans le tableau structuré créé auparavant.
N.B: le choix d'un tableau structuré pour réceptionner les données au lieu d'une simple plage se justifie par la possibilité qu'il offre à étendre la mise en forme au fur et à mesure de la saisie des nouvelles rangées.
Alors, mon application fonctionne correctement dans le classeur où elle a été stockée. Je la teste également à partir d'un autre classeur et elle marche toujours sans aucun souci.
Le problème se pose après conversion de mon classeur en macro complémentaire (.XLAM). En effet, en la distribuant à d'autres utilisateurs, le programme marche et permet de choisir une feuille, d'insérer le tableau, et de saisir une première ligne de données. MAIS, après remplissage des contrôles pour la 2ème ligne, et en cliquant sur le bouton AJOUTER, Excel plante complètement, affiche un message d'erreur et se ferme subitement.
Voici le message d'erreur: Erreur automation, l'objet invoqué s'est déconnecté de ses clients.
D'abord, je n'arrive pas à comprendre comment ma macro peut fonctionner normalement sur un autre classeur et planter quand elle est exécutée à partir d'une XLAM (puisque la macro complémentaire, par construction, fonctionne comme un classeur qui fournit le code mais avec des feuilles masquées!). Et puis, le message d'erreur lui même n'est pas très parlant... ce qui fait que je tourne en rond en butant sur ce problème depuis plus d'une semaine !
Si quelqu'un à une piste de résolution, merci de m'en faire part.
Je me suis permis quelques modifs dans ton code pour exploiter les tables structurées
dans la listbox, la ligne d'entete n'est plus chargée
j'ai ajouté une feuille "Listes" qui te permet de définir les différentes listes qui vont alimenter les combo
beaucoup plus pratique que de faire les listes en dur dans le code
ex: si tu ajoutes une marque.. tu vas devoir aller modifier le code à 3 ou 4 lignes différentes..
alors qu'avec les tables.. il te suffit d'ajouter la nouvelle marque dans la feuille Listes.. et c'est tout..
Bonjour vgendron,
Je pense pas que ce soit le problème.
Normalement la macro complémentaire s'exécute à partir d'un bouton du ruban d'un autre classeur et donc "Activesheet" dans ce cas est la feuille active de ce classeur et non pas celui du classeur .XLAM.
Bonsoir à tous ! @Staple1600 oui bien sur !
Alors en exécutant ma macro pas à pas j'ai pu détecter la ligne où Excel plante (la ligne 19 dans le code ci-dessous):
VB:
Private Sub CommandButton6_Click()
Dim cdt As Boolean
Dim L As Integer
Dim Index As Integer
'Ajouter un nouvel enregistrement à partir des valeurs entrées dans les contrôles
'Gére uniquement le cas des champs vides
'Les autres cas de validation des données sont gérés individuellement
cdt = (ComboBox6 = "") Or (TextBox6 = "") Or (ComboBox8 = "") Or (ComboBox9 = "") Or (TextBox3 = "") Or (TextBox4 = "")
If cdt Then
MsgBox "Veuillez d'abord remplir tous les champs. ", vbInformation, "Attention"
Else
L = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
On Error Resume Next
If ActiveSheet.Cells(L, 1) <> "" Then L = L + 1
With ActiveSheet
.Cells(L, 1) = ComboBox6
.Cells(L, 2) = CDate(TextBox6)
.Cells(L, 3) = CDbl(ComboBox8)
.Cells(L, 4) = CDbl(TextBox3)
.Cells(L, 5) = ComboBox9
.Cells(L, 6) = CDbl(TextBox4)
End With
Call userform_initialize
ComboBox6.SetFocus
UserForm2.Width = Frame2.Width + 25
ActiveSheet.Range("A" & L).Select
ListBox1.ListIndex = 0
End If
End Sub
Déjà puisque il s'agit de ligne
(et donc au cas où)
Enrichi (BBcode):
Private Sub CommandButton6_Click()
Dim cdt As Boolean
Dim L As Long
Dim vIndex As Long
'Ajouter un nouvel enregistrement à partir des valeurs entrées dans les contrôles
'Gére uniquement le cas des champs vides
'Les autres cas de validation des données sont gérés individuellement
cdt = (ComboBox6 = "") Or (TextBox6 = "") Or (ComboBox8 = "") Or (ComboBox9 = "") Or (TextBox3 = "") Or (TextBox4 = "")
If cdt Then
MsgBox "Veuillez d'abord remplir tous les champs. ", vbInformation, "Attention"
Else
L = ActiveSheet.Range("A" & Rows.Count).End(xlUp).Row
On Error Resume Next
If ActiveSheet.Cells(L, 1) <> "" Then L = L + 1
With ActiveSheet
.Cells(L, 1) = ComboBox6
.Cells(L, 2) = CDate(TextBox6)
.Cells(L, 3) = CDbl(ComboBox8)
.Cells(L, 4) = CDbl(TextBox3)
.Cells(L, 5) = ComboBox9
.Cells(L, 6) = CDbl(TextBox4)
End With
Call userform_initialize
ComboBox6.SetFocus
UserForm2.Width = Frame2.Width + 25
ActiveSheet.Range("A" & L).Select
ListBox1.ListIndex = 0
End If
End Sub
Si j'ai bien compté la ligne 19, c'est celle-ci, non ? ComboBox6.SetFocus
Si oui, est-ce qu'il y a bien un ComboBox nommé ComboBox6 dans ton Userform ?
alors la ligne 19 c'est :
.Cells(L, 1) = ComboBox6
quand l'application transfère le contenu de la combobox 6 dans la 1ère cellule de la ligne L
L étant la première ligne vide si on part de haut en bas
Pour simplifier la vérification, je transfère mon fichier ça sera effectivement plus simple.
Le code pour déverrouiller le project est 0000
MErci
Joins plutôt (comme je le disais précédemment) une version XLSM car pour traiter un *.XLAM, on doit d'abord désactiver le mode protégé d'Excel.
(Ce qui est contraignant, et on risque d'oublier de le réactiver ensuite)
je viens de jeter un oeil sur le fichier
quelques remarques
1) tu précises utiliser des tables structurées pour présenter les données==> C'est très bien. sauf que dans le code, (à part la création de la table), nulle part tu exploites cette structure..
tu restes avec L=range("...).end(xlup).row.. pour ajouter une ligne
alors qu'il suffirait de faire
listbojects(1).listrows.add
2) ensuite, il me semble qu'il y a beaucoup de select inutiles
3) il faudrait pouvoir nommer tous les controls de tes formulaires: Plus simple pour s'y retrouver
4) la "petite" animation qui te permet de basculer d'un formulaire à l'autre: perso, ca m'a donné l'impression d'un bug et d'un ralentissement du PC
Bonjour.
Voir s'il n'y aurait pas lieu de passer à False la propriété ShowModal des UserForm.
J'ai vu des Unload Me suivis de UserFormX.Show qui bloquent l'exécution sur ce code d'un objet qui se sera donc effectivement déconnecté au moment où l'exécution pourra enfin reprendre pour pouvoir se terminer …
Salut ! @vgendron merci pour ton retour
Alors pour le tableau structuré voilà le souci que j'ai:
si j'utilise l'instruction listbojects(1).listrows.add j'aurais toujours une dernière ligne VIDE qui fait partie du tableau ( et qui est par conséquent mise en forme) , ce que je souhaite vraiment c'est que le tableau s'ajuste au fur et à mesure de la saisie, càd qu'aucune ligne vide ne fasse partie du tableau
Ensuite, si tu peux m'expliquer d'avantage ta remarque par rapport aux "select inutiles " ça serait sympa
Pour l'animation, c'est un peu pour le fun, mais j'avoue que ça rend pas service à la gestion de la mémoire.
Merci infiniment pour tout ce partage, c'est inestimable
bah non justement... c'est tout l'interet d'avoir des tables structurées : ne pas avoir de ligne vide qui traine inutilement
bon. après; il faut ajouter une ligne QUE si tu as des données à ajouter... evidemment..
pour les select
ca oblige d'etre certain que la feuille sur laquelle tu travailles est bien active..sinon..ca peut entrainer des problèmes
pour s'en affranchir, on passe par des With... end with..
une autre question à se poser
si je ne me trompe pas, il me semble que: ThisWorkbook = le classeur qui contient la macro et activeworkbook = le classeur actif
dans ce code par exemple
VB:
Private Sub CommandButton_ajout_Click()
Dim reponse As Integer
reponse = MsgBox("Créer une nouvelle feuille ?", vbYesNo, "Nouvelle feuille")
If reponse = vbYes Then
Worksheets.Add after:=Worksheets(Worksheets.Count)
Cbx_Feuilles.AddItem Worksheets(Worksheets.Count).Name
Cbx_Feuilles = Cbx_Feuilles.List(Cbx_Feuilles.ListCount - 1)
End If
End Sub
la ligne Worksheets.Add===> comme le classeur parent n'est pas spécifié.. VBA prend quoi. ThisWorkbook ou activeworkbook
dans le cas où tu es avec un classeur XLSM: c'est à priori le meme..donc pas de souci
mais dans le cas où ta macro est dans XLAM...??
Je me suis permis quelques modifs dans ton code pour exploiter les tables structurées
dans la listbox, la ligne d'entete n'est plus chargée
j'ai ajouté une feuille "Listes" qui te permet de définir les différentes listes qui vont alimenter les combo
beaucoup plus pratique que de faire les listes en dur dans le code
ex: si tu ajoutes une marque.. tu vas devoir aller modifier le code à 3 ou 4 lignes différentes..
alors qu'avec les tables.. il te suffit d'ajouter la nouvelle marque dans la feuille Listes.. et c'est tout..