Que choisir pour extraire de Excel et afficher dans Excel?
Résolupijaku Messages postés 13513 Date d'inscription Statut Modérateur Dernière intervention -
- Que choisir pour extraire de Excel et afficher dans Excel?
- Word et excel gratuit - Guide
- Liste déroulante excel - Guide
- Si et ou excel - Guide
- Déplacer colonne excel - Guide
- Excel trier par ordre croissant chiffre - Guide
54 réponses
Le problème porte sur l’extraction aléatoire de 15 questions parmi 12 feuilles thématiques dans Excel, puis leur affichage sur une interface unique, avec les réponses Vrai/Faux et un indice de certitude. La solution proposée privilégie un formulaire UserForm en VBA pour afficher les questions une par une, avec une liste déroulante permettant de choisir la feuille source (1 à 12). Des exemples et des codes commentés ont été fournis pour illustrer l’option, et des mécanismes d’archivage temporaire ou de suivi des résultats sur une feuille dédiée ont été évoqués. Pour avancer, il est recommandé de concevoir le formulaire, de coder la sélection aléatoire et l’affichage séquentiel, puis d’ajouter progressivement l’archivage et le suivi des réponses si nécessaire.
Pour te répondre, non il s'agit toujours de bureautique. Certains parlent de programmation de "bas étage", perso je ne trouve pas. Tu peux te créer de vrais outils de travail qui te permettent un gain de temps considérable.
Voilà à demain.
Tout dépend de ce que vous souhaitez...
Personnellement, je trouve ça plus convivial de le faire par un formulaire de type UserForm.
Faut s'y connaitre un minimum en VBA, mais ça peut être sympa à créer puis exploiter.
Je t'ai bricolé cet exemple. Il est très incomplet mais te donne une idée de ce que l'on peux faire.
Si tu es intéressé on développera.
Tu dis.
Celui-ci tu trouveras tout le code commenté.....
Dans les commentaires du module1, tu trouveras 3 questions et une amélioration à faire absolument.
Dis moi...
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionAlors, ce qu'il faudrait pour bien faire (voilà, ...ça commence..), c'est que le bouton radio soit initialisé après une réponse. En effet, le candidat pourrait valider sa réponse sans se rendre compte qu'il ne vient pas de cliquer. Très bien le tableau inséré avec les indices! Ce que je vais faire maintenant est d'aller extrapoler d'après ton code pour des données de ma feuille (voir si j'y arrive). Je dois me rendre compte le + rapidement possible des difficultés pour finaliser. Je m'en vais donc dans ton code et commentaires. Merci!
01/01/2013¤35¤0 ==> Le 01/01/2013 - 35 pts / 75 - 0 = éliminatoire
02/12/2012¤45¤1 ==> Le 02/12/2012 - 45 pts - 1 = non éliminé
C'est + simple à mettre en place.....
Ce serait super bien de faire comme tu le proposes. Je voulais aussi te dire que le Form qui était resté à l'écran après 2 échecs d'envoi, après la correction du SMTP il a envoyé. Il permet donc d'être cliqué plusieurs fois. De la sorte, si la réponse pop de Win tarde, la personne pourrait recliquer plusieurs fois et envoyer plusieurs messages les mêmes...
Sub EnregistreResultats(Nom As String, Article As String, Result As Integer, Elim As Byte)
Dim Lig As Integer, Col As Integer, Pos As Integer, NbrCar As Integer
Dim Score
'Dans la feuille "Résultats"
With Sheets("Résultats")
'on cherche la ligne ou en colonne A on a le nom de l'utilisateur
Lig = .Columns(1).Cells.Find(Nom, Lookat:=xlWhole).Row
'on cherche la colonne ou dans la 1ere ligne on a le nom de l'article
Col = .Rows(1).Cells.Find(Article, Lookat:=xlWhole).Column
'Si la cellule d'intersection lig col est vide
If .Cells(Lig, Col) = "" Then
'on y enregistre : la date + ¤ + le résultat
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
Else 'sinon, si elle n'est pas vide
'On regarde si la note précédente était éliminatoire
If Right(.Cells(Lig, Col), 1) = 0 Then
'Si c'est le cas, et que la note du jour n'est pas éliminatoire
If Elim = 1 Then
'Cas : ce jour non éliminatoire ; jour précédent éliminatoire
'ON REMPLACE
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
Exit Sub
Else
'Cas : ce jour éliminatoire ; jour précédent éliminatoire
'ON VERIFIE LE SCORE
Pos = InStr(.Cells(Lig, Col), "¤") + 1
NbrCar = InStr(InStr(1, .Cells(Lig, Col), "¤") + 1, .Cells(Lig, Col), "¤") - (InStr(1, .Cells(Lig, Col), "¤") + 1)
Score = Mid(.Cells(Lig, Col), Pos, NbrCar)
'si le score de la cellule est, inférieur au résultat du jour
If Score < Result Then
'on enregistre, dans la cellule : la date + ¤ + le résultat
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
Exit Sub
End If 'dans le cas contraire (résultat inférieur) on ne fait rien
End If
Else
'Cas : ce jour éliminatoire ; jour précédent non éliminatoire
'ON N'ENREGISTRE PAS
If Elim = 0 Then Exit Sub
End If
'Cas : ce jour non éliminatoire ; jour précédent non éliminatoire
'ON VERIFIE LE SCORE
'on extrait le score de la cellule
Pos = InStr(.Cells(Lig, Col), "¤") + 1
NbrCar = InStr(InStr(1, .Cells(Lig, Col), "¤") + 1, .Cells(Lig, Col), "¤") - (InStr(1, .Cells(Lig, Col), "¤") + 1)
Score = Mid(.Cells(Lig, Col), Pos, NbrCar)
'si le score de la cellule est, inférieur au résultat du jour
If Score < Result Then
'on enregistre, dans la cellule : la date + ¤ + le résultat
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
End If 'dans le cas contraire (résultat inférieur) on ne fait rien
End If
End With
End Sub
Ce code doit être appelé depuis une procédure de l'UserForm "Questionnaire". J'ai choisit d'enregistrer lors de l'envoi du mail, mais tu peux très bien choisir autre chose (créer un nouveau bouton etc...). Quoiqu'il en soit, voici la procédure d'appel de cette Sub :
Dim Nom As String, Article As String, Resultats As Integer, Elim As Byte Nom = Label19.Caption Article = ComboBox1.Value Resultats = TextBox4.Value If Eliminatoire = False Then Elim = 1 Else Elim = 0 EnregistreResultats Nom, Article, Resultats, Elim
Ce qui peux donner, dans l'événement "clic" sur le bouton "envoyer les résultats" :
'Clic sur Envoyer les résultats"
Private Sub CommandButton4_Click()
Dim Expedit As String, Destinat As String, CopieA As String
Dim Nom As String, Article As String, Resultats As Integer, Elim As Byte
'Si l'utilisateur n'a pas répondu à 15 questions on quitte on n'envoie rien
If Cpt <> 15 Then MsgBox "Vous n'avez pas répondu aux 15 questions.": Exit Sub
'***** A ADAPTER : mettre les adresses mails des expéditeurs, destinataires et copies
Expedit = "xxxxx.xxxxxx@xxx.fr"
Destinat = "franck.xxxxxxxxxxx@xxx.fr"
CopieA = "xxx.xxxxxxxxxxxxxxx@xxx.fr"
EnvoiMail Expedit, Destinat, CopieA
'On place les résultats dans la feuille "résultats"
'si ceux ci sont les meilleurs pour ce candidat
Nom = Label19.Caption
Article = ComboBox1.Value
Resultats = TextBox4.Value
If Eliminatoire = False Then Elim = 1 Else Elim = 0
EnregistreResultats Nom, Article, Resultats, Elim 'cf Module1
'on efface le contenu de la feuille "Questions deja posees"
With Sheets("Questions deja posees")
.Cells.Clear
End With
'on règle le boolean Eliminatoire = false
Eliminatoire = False
End Sub
- dans VB => Questionnaire => clic-clic pour afficher le code et insérer tes bouts de codes mais qui, dans le Post contiennent des coupure pour tes tes explications. Pourrais-tu, Franck, m'envoyer tout le code du Questionnaire (ancien et modifié?) ici j'ai peur de planter mais surtout d'introduire des erreurs qui n'apparaîtront pas directement...
Quant au score, c'est ok mais j'attends de vérifier que ça va bien car, dans "Resultats" j'ai encollé après "Option Explicit" ton codeWith Sheets("Résultats")
'on cherche la ligne ou en colonne A on a le nom de l'utilisateur
Lig = .Columns(1).Cells.Find(Nom, Lookat:=xlWhole).Row
'on cherche la colonne ou dans la 1ere ligne on a le nom de l'article
Col = .Rows(1).Cells.Find(Article, Lookat:=xlWhole).Column
'Si la cellule d'intersection lig col est vide
If .Cells(Lig, Col) = "" Then
'on y enregistre : la date + ¤ + le résultat
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
Else 'sinon, si elle n'est pas vide
'On regarde si la note précédente était éliminatoire
If Right(.Cells(Lig, Col), 1) = 0 Then
'Si c'est le cas, et que la note du jour n'est pas éliminatoire
If Elim = 1 Then
'Cas : ce jour non éliminatoire ; jour précédent éliminatoire
'ON REMPLACE
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
Exit Sub
Else
'Cas : ce jour éliminatoire ; jour précédent éliminatoire
'ON VERIFIE LE SCORE
Pos = InStr(.Cells(Lig, Col), "¤") + 1
NbrCar = InStr(InStr(1, .Cells(Lig, Col), "¤") + 1, .Cells(Lig, Col), "¤") - (InStr(1, .Cells(Lig, Col), "¤") + 1)
Score = Mid(.Cells(Lig, Col), Pos, NbrCar)
'si le score de la cellule est, inférieur au résultat du jour
If Score < Result Then
'on enregistre, dans la cellule : la date + ¤ + le résultat
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
Exit Sub
End If 'dans le cas contraire (résultat inférieur) on ne fait rien
End If
Else
'Cas : ce jour éliminatoire ; jour précédent non éliminatoire
'ON N'ENREGISTRE PAS
If Elim = 0 Then Exit Sub
End If
'Cas : ce jour non éliminatoire ; jour précédent non éliminatoire
'ON VERIFIE LE SCORE
'on extrait le score de la cellule
Pos = InStr(.Cells(Lig, Col), "¤") + 1
NbrCar = InStr(InStr(1, .Cells(Lig, Col), "¤") + 1, .Cells(Lig, Col), "¤") - (InStr(1, .Cells(Lig, Col), "¤") + 1)
Score = Mid(.Cells(Lig, Col), Pos, NbrCar)
'si le score de la cellule est, inférieur au résultat du jour
If Score < Result Then
'on enregistre, dans la cellule : la date + ¤ + le résultat
.Cells(Lig, Col) = Date & "¤" & Result & "¤" & Elim
End If 'dans le cas contraire (résultat inférieur) on ne fait rien
End If
End With
End SubEnfin, relativement à l'enregistrement des résultats, le code se termine ainsi...objMessage.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = "25"
objMessage.Configuration.Fields.Update
objMessage.Send
MsgBox "Vos résultats ont bien été transmis."
Exit Sub
errorHandler:
MsgBox Err.Description
End Sub
Sub EnregistreResultats(Nom As String, Article As String, Result As Integer, Elim As Byte)
Dim Lig As Integer, Col As Integer, Pos As Integer, NbrCar As Integer
Dim Scoresoit donc par "Dim score"au lieu du précédent "End Sub" Pour t'éviter de m'expliquer et que je réagisse aux explication (on voit ici que ça devient compliqué) ce srait mieux que, si tu veux bien, me renvoies ton Form. Pour y insérer mes données je dispose maintenant de l'entraînement suffisant pour effectuer les opérations.
Malheureusement je ne peux rien pour toi sur ce point...
Peut être une autre façon de procéder serait d'envoyer, non pas en copie, mais en destinataire supplémentaire...
Comme ceci (là ou tu as mis tes adresses) :
Expedit = "franck.111111@xxxxx.fr" Destinat = "xxxx.xxxxxx@xxxxx.fr, yyyyyyyy.yyyy@yyyyy.com" CopieA = "" EnvoiMail Expedit, Destinat, CopieA
Qu'entends tu par "obtenir un enregistrement"?
Plusieurs possibilités :
1- stocker les questions/réponses des candidats dans une feuille
avantage : tu conserves une trace de tout
inconvénient : risque qu'à terme ton fichier soit énorme, lent etc.
2- envoyer par mail les questions-réponses de chaque tests,
avantage : tu conserves une trâce de tout
inconvénient : ta boîte mail risque de péter une durite...
3- imprimer une feuille par test avec les questions et réponses
avantage : tu conserves une trâce de tout (j'l'ai pas déjà dit?), le candidat peut repartir avec ses résultats.
inconvénient : tu tues la forêt équatoriale...
4- autre solution : dis moi ce que tu envisageais...
Dim Ligne As Long
Ligne = Range("A" & Rows.Count).End(xlUp).Row + 1
Tu écris le nom du gars en colonne A :
Range("A" & Ligne) = Me.Label19.Caption
Ensuite, à chaque réponse, tu enregistres dans la cellule qui se trouve à la ligne "Ligne" et à la première colonne vide à droite... Soit :
Dim Col As Integer Col = Cells(Ligne, Cells.Columns.Count).End(xlToLeft).Column + 1
Ce qui doit te donner un code complet voisin de :
Code à placer dans la procédure Private Sub UserForm_Initialize() :
Dim Ligne As Long
With Sheets("Archives")
Ligne = .Range("A" & Rows.Count).End(xlUp).Row + 1
.Range("A" & Ligne) = Me.Label19.Caption
End With
Code à placer dans le clic du bouton :
Dim Ligne As Long
Dim Col As Integer
With Sheets("Archives")
Ligne = .Range("A" & Rows.Count).End(xlUp).Row
Col = .Cells(Ligne, Cells.Columns.Count).End(xlToLeft).Column + 1
.Range("A" & Ligne) = Me.Label19.Caption
.Cells(Ligne, Col) = Reponse
End With
Attention, je n'ai rien testé!
Pour archiver, nous avons besoin de quels renseignements :
- NOM Prénom,
- Date,
- Nom du questionnaire (pour retrouver les questions...)
- Les réponses du gars aux 15 questions.
La feuille archive se compose donc de :
- colonne A : NOM PRénom
- colonne B : Date,
- colonne C : Nom du questionnaire,
- colonnes de D à R : colonnes ou on va inscrire les réponses des questions de 1 à 15
Pour coder cela :
On a besoin du numéro de la ligne, dans la feuille archive, ou stocker les résultats. Cette ligne est la première ligne vide. On en a besoin dans :
- l'initialisation de l'Userform,
- le clic sur le bouton.
Comme elle doit rester en mémoire tout le temps d'exécution, il convient de la placer en entête du module de l'UserForm Questionnaire.
Tu verras donc, en tête du code de "Questionnaire" :
Option Explicit 'ça y était déjà... Dim LignArchive As Long
Une fois ceci fait, on se pose la question :
Quand a t'on besoin de recalculer le numéro de la première ligne vide colonne A Feuille "Archive"?
- Lors de l'initialisation de l'Userform,
- Lors d'un clic sur le bouton "Evaluer un autre article",
- Pour être sur de nous, lors d'un clic sur le bouton "Envoyer les résultats".
Donc, dans ces trois procédures de l'USF Questionnaire, nous allons ajouter ces 3 lignes :
With Sheets("Archive")
LignArchive = .Range("A" & Rows.Count).End(xlUp).Row + 1
End With
Ensuite, avec ce numéro de ligne, il nous faut stocker, dans la feuille archive :
- le nom,
- la date,
- le nom du questionnaire.
Quand faire cela???
Lorsque le candidat choisit son questionnaire
avantage : même s'il ne finit pas de répondre, cela sera archivé.
Genre s'il change de questionnaire sans avoir répondu à une seule question, la feuille archive aura tout de même les colonnes A, B et C de remplies et donc tu le sauras...
Donc, dans la procédure :
'En cas de changement de choix d'article : Private Sub ComboBox1_Change()
inscrit ces quelques lignes :
'on enregistre le nom, la date et le questionnaire dans la feuille archive
With Sheets("Archive")
.Range("A" & LignArchive).Value = Me.Label19.Caption
.Range("B" & LignArchive).Value = Date
.Range("C" & LignArchive).Value = ComboBox1.Value
End With
Ne reste plus qu'à écrire, dans cette même ligne, les réponses à chaque clic sur "valider". Profitons en pour stocker, dans ces mêmes cellules :
- le degré de certitude choisi ==> pour cela, il nous faut une nouvelle variable numCertitude...
- le score obtenu par réponse
Dans la procédure :
'Lors d'un clic sur le bouton "valider une réponse" : Private Sub CommandButton1_Click()
Après le traitement "fausse réponse" et "bonne réponse" et avant l'effacement des optionbutton.value :
ajouter :
'On stocke les réponses+degré de certitude + résultat
Dim ColonnArchive As Integer
With Sheets("Archive")
ColonnArchive = .Range("IV" & LignArchive).End(xlToLeft).Column + 1
.Cells(LignArchive, ColonnArchive) = Reponse & "¤" & numCertitude & "¤" & Points
End With
Après cela, ne reste plus qu'à exploiter ces résultats... Pour cela, il nous faut :
- un 3ème userform,
- une nouvelle feuille que tu pourrais imprimer...
Je m'y penche ce matin.
J'ai vu l'exemple. Oui! ça me plaît! Entre temps j'avais penché aussi sur l'UserForm et j'avais commenté par expérimenter les commandes de VBA (je suis sur Office 2000 professionnel). J'arrive à quelque chose (dans l'utilisation de ces commandes) et concluant dans mes essais. De votre côté vous en êtes à un autre stade... L'exemple (sans doute rapide pour vous mais pour moi y arriver il y a un délai) montre bien le profil d'une solution élégante. Ainsi, dans une telle perspective, partant de votre exemple (si je peux en modifier le code), je peux extrapoler aux dénominations réelles relatives à mes questions. Une manière de dire que je ne m'attends pas à "du tout cuit dans mon assiette".
Là où je ne saurais pas de si tôt en sortir se serait au niveau de l'application dans l'UserForm de la formule suivante qui résout dans Excel (écrite hier par Bruce Willix de la communauté de ce site): =SI(A2=B2;SI(C2=1;0;SI(C2=2;3;SI(C2=3;4;SI(C2=4;5))));SI(C2=1;0;SI(C2=2;-1;SI(C2=3;-2;SI(C2=4;-5))))). En conclusion, merci donc de votre disponibilité et compétence. J'opte pour votre suggestion de déployer la solution via un UserForm
Tu va sur ce site, créer un lien vers ton fichier, reviens ici coller ton lien dans une réponse...
- pourquoi des boutons "vrai" "faux" associés à des checkbox...
Dans ce cas, il convient d'utiliser le contrôle adapté, soit des optionbutton... Dans l'exemple, j'ai affecté, à leurs propriétés groupename la même valeur (GP1) pour signifier qu'un seul peux être actif.
- pourquoi un bouton certitude? totalement inutile. Suffit de mettre dans la propriété caption de la frame2 : certitude.
- ton barème peux très bien être inclus dans un label.
Après faut adapter le code du bouton valider...
Ton fichier