Userform lent

Résolu/Fermé
JinRo Messages postés 22 Date d'inscription mercredi 29 mai 2013 Statut Membre Dernière intervention 15 décembre 2013 - 23 sept. 2013 à 23:55
 JinRo - 27 mai 2014 à 11:51
Bonjour,

Je suis novice en VBA et j'aurai besoin de votre aide si ce n'est de vos lumières.

Mon fichier ci-joint, https://www.cjoint.com/?3IxwPCc4bsR nous sert au quotidien pour gérer des données et permettre une vérification de l'état de nos assurés rapidement.

Le fichier en soit fonctionne très bien, malheureusement ce qui me pose problème c'est le temps de validation des données que ce soit en créant un nouveau cas ou en saisissant des modifications.

L'Userform permet également de pouvoir consulter certaines données en plaine modification. Exemple, Solde de jour droit doit être le résultat de Droit de joursLAA/LAMAL moins Jours LAA/LAMAL payés cette année et année précédente.

En testant le fichier avec une BDD de 150 lignes, j'ai une latence de 16 sec lors d'une validation. J'aimerai pouvoir accélérer le tout.

J'ai appris y a peu que les macros automatiques ralentissent et alourdissent inutilement le fichier. Malheureusement, en lisant les livres ou autre je n'arrive pas à appliquer certaines des explications ou consignes. La pratique est plus concrète pour moi et compréhensible. C'est pourquoi je m'excuse si ce que vous allez voir vous pique les yeux.

Mon but et de voir améliorer le fichier mais également apprendre des mes erreurs.
D'avance merci de votre aide mais surtout de votre compréhension car il n'est pas évident de faire les choses en autodidacte.

9 réponses

Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
24 sept. 2013 à 10:01
Bonjour,

Une validation (quel bouton) de quel UserForm (il y en a 4) ?

A+
0
JinRo Messages postés 22 Date d'inscription mercredi 29 mai 2013 Statut Membre Dernière intervention 15 décembre 2013
24 sept. 2013 à 10:03
Bonjour dans les Usf IJ et Mandataires quand je fais saisir ou valider une modification j'ai un temps de latence quand la Bdd contient déjà 150 ligne.
0
Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
24 sept. 2013 à 10:16
ça doit être la procédure appelée Calcul_IJAI qui est lente : Place
Application.Calculation = xlCalculationManual au début de celle-ci et
Application.Calculation = xlCalculationAutomatic à la fin

Si cela ne résout pas le problème, espionne les délais des différentes étapes avec un Timer
mouchard=""
t=Timer
mouchard=mouchard & Chr(10) & (Timer-t)
.
.
.
mouchard=mouchard & Chr(10) & (Timer-t)
.
.
.
mouchard=mouchard & Chr(10) & (Timer-t)
.
.
.
MsgBox mouchard
0
JinRo Messages postés 22 Date d'inscription mercredi 29 mai 2013 Statut Membre Dernière intervention 15 décembre 2013
24 sept. 2013 à 10:30
Alors après ton message, j'ai mis application.calculation=xlcalculationmanul et automatic l'un en début et l'autre à la fin de mon module Calcul_ijai.

Mais ça ne change pas le temps.

Pour le timer pourrais-tu m'expliquer comment procéder où le mettre exactement,svp?
0
Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
24 sept. 2013 à 10:48
Quand tu fais t=Timer, c'est comme si tu commençais un chronomètre.
A chaque fois que tu insères le "mouchard", ça te donne les temps intermédiaires
Enfin le MsgBox t'affiche tous les temps intermédiaires

=> Utilise le timer d'abord dans ton UserForm. Si tu vois que la durée d'exécution est principalement due au module Calcul_ijai, supprime le timer de ton UserForm et applique le principe sur Calcul_ijai

Désolé de pas être plus précis, mais sans la BdD, c'est un peu difficile. Toutefois les formules à gogo dans Calcul_ijai me surprennent un peu.
0
Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
24 sept. 2013 à 11:23
Une piste : Range("A" & Cells.Rows.Count).End(xlUp).Row est calculé plein de fois.
Fais peut-être le calcul au début du module
derligne=Range("A" & Cells.Rows.Count).End(xlUp).Row
et utilise derligne.
0
JinRo Messages postés 22 Date d'inscription mercredi 29 mai 2013 Statut Membre Dernière intervention 15 décembre 2013
24 sept. 2013 à 12:39
Encore merci de ton aide!
Je n'avais pas compris que le Range("A" & Cells.Rows.count.End(xlup).Row était recalculé plein de fois. Je n'en avais pas compris la portée.

pour corriger le tir, est-ce que ceci convindrait?

Sub Calcul_IJAI()
Dim i&, fin&
With Sheets("IJ")
fin = Range("A" & Rows.Count).End(xlUp).Row
For i = 2 To 1000
If Cells(i, 1) <> "" Then Cells(i, 4).FormulaR1C1 = "=IF(SUMPRODUCT((Mandataires!R2C1:R5000C1=IJ!RC1)*(Mandataires!R2C4:R5000C4=""En cours""))>0,""En cours"",""Terminé"")"
Next i
End With
End Sub


Maintenant si c'est le cas pour chaque formule devrais-je à chaque fois remettre :
If Cells(i, 1) <> "" Then Cells(i, 4).FormulaR1C1 = "=

avec la formule de calcul que je souhaite ou est-ce que cela alourdirai encore le fichier?
ou alors un
then cells(i, X).FormulaR1C1 = "=


Et pour répondre à ta question les formules à gogo comme tu les as appelé, me permettent de déterminé certains éléments nécessaire au traitement d'un dossier. Et comme je sais que certains sont fortiche pour les supprimer j'ai besoin d'être sûr depouvoir les réintégrer sans avoir à me casser la tête car fichier non protégé.
0
Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
Modifié par Zoul67 le 24/09/2013 à 13:41
1. Range("A" & Cells.Rows.Count).End(xlUp).Row)

Je pensais plus à
derligne=Range("A" & Cells.Rows.Count).End(xlUp).Row
'Indication de l'Etat en fonction du nombre de dossier mandataires pour le même assuré en état "En cours".
Range("D2:D" & derligne).FormulaR1C1 = "=IF(SUMPRODUCT((Mandataires!R2C1:R5000C1=IJ!RC1)*(Mandataires!R2C4:R5000C4=""En cours""))>0,""En cours"",""Terminé"")"
etc.
Ainsi, la dernière ligne n'est calculée qu'une fois. Comme je n'ai pas tes données, je ne peux pas voir si cette solution est efficace.

2. Au sujet de "With"

With est sans effet dans le code que tu as écrit ci-dessus, il faut ajouter un . pour indiquer l'appartenance

3. Autres possibilités d'amélioration

a. Protéger les feuilles ou certaines plages
b. Avoir un onglet caché avec les bonnes formules qui servirait de "modèle". Tu dupliques ce modèle

Au fait...
ça a donné quoi les timers ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
JinRo Messages postés 22 Date d'inscription mercredi 29 mai 2013 Statut Membre Dernière intervention 15 décembre 2013
25 sept. 2013 à 00:00
Rebonjour,

Navré pour le délais de réponse mais le travail et la vie de famille ne m'en a pas trop laissé le temps.

Je vais essayer de répondre à tes questions.

Pour commencer, j'ai essayé de suivre tes conseils pour la modification du Calcul IJAI :
Est-ce que ceci serait plus correct :

Sub Calcul_IJAI()

Dim derligne As Long

derligne = Range("A" & Cells.Rows.Count).End(xlUp).Row

Range("D2:D" & derligne).FormulaR1C1 = "=IF(SUMPRODUCT((Mandataires!R2C1:R5000C1=IJ!RC1)*(Mandataires!R2C4:R5000C4=""En cours""))>0,""En cours"",""Terminé"")"

Range("I2:I" & derligne).FormulaR1C1 = "=SUM(RC[-1]+2)"

'Calcul déterminant le droit pour le paiement des jours LAA/LAMAL

Range("X2:x" & derligne).FormulaR1C1 = "=IF(MONTH(RC[-1])>MONTH(TODAY()),"""",IF(365>=DATEDIF(RC[-1],TODAY(),""d"")-RC[-2],30,IF(730>=DATEDIF(RC[-1],TODAY(),""d"")-RC[-2],60,IF(1095>=DATEDIF(RC[-1],TODAY(),""d"")-RC[-2],90,IF(1095<DATEDIF(RC[-1],TODAY(),""d"")-RC[-2],90,"""")))))"

'Calcul du nombre d'attestation à recevoir pour valider les paiements

Range("AC2:AC" & derligne).FormulaR1C1 = "=SUMPRODUCT((Mandataires!RC[-28]:R[998]C[-28]=IJ!RC[-28])*(Mandataires!RC[-25]:R[998]C[-25]=""En cours""))"

'Calcul du nombre d'attestation reçue

Range("CL2:CL" & derligne).FormulaR1C1 = "=SUMPRODUCT((Mandataires!RC[-89]:R[998]C[-89]=IJ!RC[-89])*(Mandataires!RC[-86]:R[998]C[-86]=""En cours"")*(Mandataires!RC[-84]:R[998]C[-84]=""Reçue""))"

'Indication de la date du dernier paiement effectué pour l'assuré

Range("CM2:CM" & derligne).FormulaR1C1 = "=IF(RC[13]="""","""",INDEX(RC[13]:RC[24],,COUNT(RC[13]:RC[24])))"

'12 calculs pour déternimner le dernier paiement effectué

Range("CZ2:DK" & derligne).FormulaR1C1 = "=IF(RC[-12]="""","""",VALUE(RC[-12]))"

End Sub

En faisant un petit test en effaçant toutes les formules et rien qu'en appelant le module de calcul toutes ces dernières se remettent plus vite. Beaucoup plus vite qu'avant.

Par conséquent, j'ai essayé de le refaire via l'USF. Bien que cela soit plus rapide j'arrive toujours à une certaine latence.

Par rapport au temps de latence j'ai essayé d'utilisé le t=timer mais malheureusement je dois pas savoir l'utiliser correctement ou le placer tout court. navré. J'ai fait un test avec un chrono... (c'est honteux, je sais.)

Pour finir j'en arrive à la conclusion que c'est l'USF lui même qui ne va pas.

https://www.cjoint.com/?3IyxQxdg9pq

là c'est une copie du fichier avec des données bidons si tu es d'accord d'y jeter un coup d'oeil, ça serait sympa.

Au début, j'ai cru que c'était le calcul entre les Textbox qui ralentissaient. Mais même en supprimant ces calculs j'ai toujours les ralentissements.
0
Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
25 sept. 2013 à 09:44
Bonjour,

Tu n'as pas à être désolé, il y a des priorités dans la vie...
Par rapport à l'utilisation de derligne, oui, c'est bien ça.
Il m'a fallu du temps pour comprendre d'où venaient les latences (ça tombe bien, mon PC mettait aussi 13 à 15 s pour la validation d'une modif)... J'ai mis des Times pour voir où se situait le problème. C'est bien les Textbox 8 à 99 qu'il faut recopier qui prennent du temps, mais c'est une opération simple. Il s'agit en fait des recalculs associés qui plombent tout ! C'est donc dans le code du Usf qu'il faut jouer sur le re-calcul auto ou manuel.

Je te laisse les timers pour que tu voies à quoi ça ressemble... et aussi la suppression des Feuil1 (pour que With serve à qqc).

Private Sub Bt2_Click()
Dim t As Double
t = Timer
Dim i&, lig&
Application.Calculation = xlCalculationManual
Sheets("IJ").Activate
If C1.ListIndex = -1 Then MsgBox "Vous n'avez choisi aucun nom dans la liste!" & vbNewLine & "Par conséquent, vous ne pouvez rien faire." & vbNewLine & "Merci de bien vouloir sélectionner un assuré.": Exit Sub
lig = C1.List(C1.ListIndex, 1)

With Feuil1
.Cells(lig, 1) = T1: .Cells(lig, 4) = T3: T1 = "": T3 = ""
.Cells(lig, 3) = T2: .Cells(lig, 5) = C2: T2 = "": C2 = ""
.Cells(lig, 6) = C3: .Cells(lig, 7) = T4: C3 = "": T4 = ""
.Cells(lig, 8) = T5: .Cells(lig, 9) = T6: T5 = "": T6 = ""
.Cells(lig, 10) = T7: .Cells(lig, 11) = C4: T7 = "": C4 = ""
.Cells(lig, 2) = C1: C1 = ""
For i = 8 To 99
.Cells(lig, i + 4).Value = Controls("T" & i).Text: Controls("T" & i) = ""
Next i
End With

Call Calcul_IJAI
Application.Calculation = xlCalculationAutomatic
MsgBox Timer - t
End Sub

A+

PS : tu es sûr que ça fonctionne bien si deux assurés portent le même nom ?
PS2 : est-ce bien judicieux de vider tous les textbox ? Ne vaudrait-il pas mieux une réinit du Usf ?
0
JinRo Messages postés 22 Date d'inscription mercredi 29 mai 2013 Statut Membre Dernière intervention 15 décembre 2013
25 sept. 2013 à 23:51
Bonjour,

Un grand merci à toi pour ton aide. Honnêtement, je ne comprends plus rien tu m'avais déjà proposé la solution :

Application.Calculation= xlcalculationautomatic et manual. Et quand j'ai eu testé cela ne changeait rien... Et pourtant il me semble que j'avais positionné ces commandes comme tu l'as fait dans l'exemple ci-dessus.

En en parlant, avec un collègue de travail, on s'est demandé si l'environnement de travail ne pouvait pas jouer un rôle également. (matériel ou réseau)

Le timer est génial mais comment as-tu compris que c'était les Textbox 8 à 99 qui mettaient concrètement du temps? Car en laissant l'usf tel qu'à l'origine j'ai utilisé le timer est j'obtiens dans le fichier que je t'ai passé 5.863... Mais il ne me donne pas d'autre indication.

Pour répondre à ta première question, je ne rencontre aucun soucis pour retrouver un même assurés et quand bien même il puisse y avoir x fois le même non. Même si cas plus ou moins rare cela se produisait. Je ne reprend pas mes données par la combobox qui référence les données de ma BDD mais par l'USF de recherche qui lui me permet de voir le nombre de possibilité en fonction de la donnée de recherche que je lui ai donné. (Merci à un forumer qui me l'a montré car je galérais pour obtenir un même résultat avec c.offset.) Je t'invite à le tester. (le fichier test ayant été remplis uniquement pour généré le problème de lenteur, on ne peux pas réellement bien s'en rendre compte.)

Pour ta seconde question, je ne dirais qu'une chose. Je n'en sais rien. J'ai cru comprendre qu'il y a plusieurs façon d'arriver à un même résultat tout dépendra de qui fait quoi et comment de ce que j'en comprends.

As mon tour de te demander (encore) quelque chose par rapport à mes usf sachant que je me suis arranger pour passer de l'un à l'autre sans avoir à changer d'onglet ou n'avoir à faire une manipulation compliquée.

Serait-il judicieux de remplacer :
  Sheets("IJ").Activate
par
With ThisWorkbook.Sheets("IJ")
la deuxième solution ne serait-elle pas moins lourde ou me créerait-elle plus d'ennuis?

Encore merci pour ton aide et conseils c'est vraiment très appréciable et sympathique.
0
Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
Modifié par Zoul67 le 26/09/2013 à 01:06
Le timer est génial mais comment as-tu compris que c'était les Textbox 8 à 99 qui mettaient concrètement du temps?
En le disposant autour de la boucle For. (donc pas tout à fait comme dans le code fourni)

Serait-il judicieux de remplacer : Sheets("IJ").Activate par With ThisWorkbook.Sheets("IJ") la deuxième solution ne serait-elle pas moins lourde ou me créerait-elle plus d'ennuis?
Je n'ai aucune certitude là-dessus, mais je pense que l'impact est minime (dans un sens ou dans l'autre)

Bonne nuit
0
eriiic Messages postés 24569 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 28 décembre 2023 7 210
Modifié par eriiic le 26/09/2013 à 23:42
Bonjour,

Dans un 1er temps, pour pas cher :
application.screenupdating=false
au début des codes qui écrivent sur les feuilles.
=false en fin pour la clarté.
Le réactiver temporairement en cours de route si tu as besoin de résultats intermédiaires.

2)dans ton code je vois :
Range("D2:D" & derligne).FormulaR1C1 = "=IF(SUMPRODUCT((Mandataires!R2C1:R5000C1=IJ!RC1)*(Mandataires!R2C4:R5000C4=""En cours""))>0,""En cours"",""Terminé"")"
Sommeprod est extrêmement gourmand en ressources.
Sur 2 colonnes déjà, plus quelques tartines à ailleurs.
Il faut agir dessus.
Dans un premier temps ne le fais pas sur 5000 lignes (1000 lignes pour les autres), mais sur le nombre exact de lignes nécessaires :
derlig=worksheets("ta_feuille").cells(Rows.Count,"A").End(xlUp).Row
"A" étant une colonne avec des données sur toutes les lignes.
Si ça n'est pas suffisant il faut charger la plage de données en mémoire dans un tableau, calculer en interne, et coller le résultat sur la feuille en se passant des formules. En sachant qu'il faudra mettre à jour s'il y a des modifs.

eric

Jamais tu ne répondras à un mp non sollicité...
Bon, ça c'est fait.
0
JinRo Messages postés 22 Date d'inscription mercredi 29 mai 2013 Statut Membre Dernière intervention 15 décembre 2013
30 sept. 2013 à 22:58
Bonsoir à tous deux! J'espère que vous avez passé un bon week-end.
Merci encore pour vos explications et votre aide.

Eriiic pour tout te dire après que Zoul67 m'ait montré comment utilisé :
derligne = Range("A" & Cells.Rows.Count).End(xlUp).Row
Je m'étais dit que ça devait également marché pour les formules à la façon sommeprod. Mais je n'ai pas eu le temps de faire des essaies que tu m'apportais déjà la réponse.

Zoul67, depuis les modifications le fichier tourne impec. Et niveau temps de fonctionnement c'est vraiment génial encore merci.

En revanche est-ce que j'oserai encore abuser de ta/vôtre gentillesse?

Voilà dans le même userform, j'ai essayé de faire que les dates qui se trouvent dans mes textbox se colorent en rouge si la date de la Textbox + 30 jours est plus petite que la date du jour.

J'ai essayé ces deux codes
Private Sub T6_Change()
Dim FirstDate As Date
Dim IntervalType As String
Dim Number As Integer
IntervalType = "d"
FirstDate = IsDate(T6)
Number = 30
If DateAdd(IntervalType, Number, FirstDate) >= Day(Now) Then
T6.ForeColor = vbBlack
Else
T6.ForeColor = vbRed
End If
End Sub

et c'est autre ci :

Private Sub T6_Change()

If IsDate(T6) + 30 >= Day(Now) Then
T6.ForeColor = vbBlack
Else
T6.ForeColor = vbRed
End If
End Sub

Ma Textbox se colore effectivement mais pas pour les bonnes raisons. Auriez-vous l'amabilité de m'expliquer?

D'avance merci.
0
Zoul67 Messages postés 1959 Date d'inscription lundi 3 mai 2010 Statut Membre Dernière intervention 30 janvier 2023 149
30 sept. 2013 à 23:44
Bonsoir,

Je crois que c'est vraiment tout con... Que renvoie la fonction IsDate ? Un booléen ! C'est comme si tu écrivais la question en anglais (enfin presque).
Supprime IsDate, et peut-être Day aussi.
Et mets des espions quand il y a si peu de variables et que le code ne fonctionne pas.

A+
0
Voilà avec du temps de retard...

J'ai trouvé cette solution.

Private Sub T11_Change()
With T11
If IsDate(T11.Value) Then
If CDate(T11) + 5 > DateValue(Now) Then
T11.ForeColor = RGB(0, 0, 0)
Else
T11.ForeColor = RGB(255, 0, 0)
End If
End If
End With
End Sub

Merci encore du temps consacré!
0