FERMETURE AUTOMATIQUE CLASSEUR EXCEL AVEC ALARME

NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011 - 20 avril 2010 à 21:22
CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 - 26 avril 2010 à 01:11
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/51629-fermeture-automatique-classeur-excel-avec-alarme

CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 1
26 avril 2010 à 01:11
Merci à vous, et au plaisir de nouvelles rencontres sur le forum.
NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011
26 avril 2010 à 00:05
Merci, bonne continuation à toi aussi Flocreate.
Flocreate Messages postés 300 Date d'inscription lundi 17 juillet 2006 Statut Membre Dernière intervention 27 mai 2012 3
25 avril 2010 à 19:09
CerberusPau ta remarque est fort juste. ^^
bonne continuation a tous.
NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011
23 avril 2010 à 21:20
No problem ! On est là pour le partage.

Je suis heureux d'avoir pu aidé.
CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 1
23 avril 2010 à 19:56
S Nikator, je souscris, et saches que ton conseil "Type Etat" me rend de grands services, et a pris la place qui lui est dûe dans toute mon appli : au feu les Form MemData !
Encore merci de ton aide et de ta disponibilité (je vais modifier la Source en conséquence)

Cdt

PS: En fonction de ton analyse du fichier que je t'ai envoyé en MP, je la complèterai également pour proposer, si tu es d'accord, la modification concernant la possibilité de pouvoir choisir le type d'alarme sonore souhaité.
NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011
23 avril 2010 à 19:40
Tu as bien raison CerberusPau, nous nous sommes, dans un sens, éloigné du sujet. Quand à continuer sur le bar, pourquoi pas, mais je pense qu'on a fait le tour.
Cela dit, ce fut intéressant, nous avons put partager des points de vue assez différents, ce qui nous a permis d'élargir nos horizons.
CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 1
23 avril 2010 à 15:08
Bon, on va peut être ralentir un peu les ardeurs...
Je n'aurai jamais pensé que cette modeste source puisse générer des commentaires aussi étendus.
Qu'on me permette seulement de rappeler qu'elle concerne du "VBA", pour un niveau "débutant", faisant appel à des API ultra classiques, un nombre de ligne serré et une action bien spécifique.
Le 1er commentaire de S Nikator colle parfaitement à cette démarche et me parrait tout à fait opportun.

Pour la suite (moi_même compris), sans nous écarter du thème, nous explorons d'autres "nouveaux horizons" qui peut être auraient une meilleure place sur un Forum ou au Bar. Pourquoi d'ailleurs ne pas nous y retrouver, ou Poster sur ce sujet, si intéressant?
Je ne voudrais surtout froisser personne, mais vous remercier tous (à nouveau) pour votre regard critique et constructif ; et bien entendu, je n'aurai pas ici la prétention de vouloir clore en une quelconque façon la poursuite de tout commentaire!
Cdt
Flocreate Messages postés 300 Date d'inscription lundi 17 juillet 2006 Statut Membre Dernière intervention 27 mai 2012 3
23 avril 2010 à 09:17
"le timer au 1/1000 ça avait de l'importance sous win95" et ca en a encore moins sous VBA ^_^

"SetTimer/KillTimer" a ba voui ct bien celle la ^_^ (juste pour rapel)
mTime (module /!\ pas de classe)
Option Explicit
Private Declare Function SetTimer Lib "user32" (ByVal Hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
Private Declare Function KillTimer Lib "user32" (ByVal Hwnd As Long, ByVal nIDEvent As Long) As Long
Private lTimerId As Long
'Purpose : Stops the timer routine
'Inputs : N/A
'Outputs : Returns True if the timer routine was stopped
Function EndTimer() As Boolean
If lTimerId Then
lTimerId = KillTimer(0&, lTimerId)
lTimerId = 0
EndTimer = True
End If
End Function
'Purpose : Starts the continuous calling of a private routine at a specific time interval.
'Inputs : lInterval The interval (in ms) at which to call the routine
'Outputs : N/A
Sub StartTimer(lInterval As Long)
If lTimerId Then
'End Current Timer
EndTimer
End If
lTimerId = SetTimer(0&, 0&, ByVal lInterval, AddressOf TimerRoutine)
End Sub
'Purpose : Routine which is called repeatedly by the timer API.
Public Sub TimerRoutine(ByVal lHwnd As Long, ByVal lMsg As Long, ByVal lIDEvent As Long, ByVal lTime As Long)
'TIMER_CLICK
End Sub

"mais il faut payer la licence" pour ma part, quand je suis entré dans mon entreprise (je suis apprenti) on m'a dit tu vois les 4 macros là, ben elles marchent plus et on sait par pkoi. Ta mission et tu vas l'accepter, c de nous arranger tout ça. Après un état des lieux, je me suis rendu compte que chaque utilisateur avait bidouillé une tite version dans son coincoin. Deplus, les fichiers comportant la macro étaient copiés collés chaque mois --> grossi concidérablement la taille des fichiers... J'ai dit si vous voulez je vous fait un truc mieux mais ca veux dire que ce serra du VB6. Il ont dit, ok tu as 3 mois pour nous prouver ce que tu avance. Depuis mon boulo c'est de faire du VB6 ^_^ (ça fait 2 ans 1/2 maintenant).
Pour moi l'ingénieur(ou le technicien) a pour mission de faire ce qu'on lui demande mais sans oublié qu'il a un devoir de conceil...
NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011
23 avril 2010 à 01:39
Flocreate, pour le timer au 1/1000 ça avait de l'importance sous win95 mais c'est pas vraiment l'OS qui a changer la donne, c'est les processeurs. Maintenant on tape dans le code sans jamais vraiment s'occuper du "temps réel". On oublierait presque la différence entre un timer et un thread.

Pour l'API dont tu parles (SetTimer/KillTimer), regarde le 3ème commentaire de ce poste, elle est utilisée.

Quand à VB6 tu as raison, mais il faut payer la licence, et la majorité des entreprises préfèrent se rabattre sur une solution moins couteuse, utilisé le pack office qu'elle utilise déjà. C'est le point de non retour...
Flocreate Messages postés 300 Date d'inscription lundi 17 juillet 2006 Statut Membre Dernière intervention 27 mai 2012 3
23 avril 2010 à 00:48
^_^ je viens de passer une journée terrrrrible a CAUSE d'excel ^_^

NikatorS:"le concept du timer qui se réglait au millième de seconde" eu je voudrais pas être raba joie mais question gestion du temps faut pas chercher on travail sous windows ^^

sinon, pour faire une tempo en VBA, il y a une API windows. (me souviens plus du nom mais ca doit se trouver easy)
L'avantage c'est qu'on peut faire une tempo "~précise~" rebouclante et sans contrôle (sans form)
L'inconvénient c'est que l'utilisation est plus lourde à implémenter. (adressoff donc passage par un module etc ...)

C'est vrai que excel a du bon. C'est utilisable par la pluspart des glandus du mulo et même qu'ils peuvent faire des macros. mais après c bibi les aprentis qu'on apelle quand ca marche plus ou alléatoirement ^^
je vous laisse imaginer une ligne de production qui référence les données critiques d'anomalie dans un fichier excel. 70 personnes peuvent potentiellement ouvrir le fichier en même temps...

nan vraiment je trouve l'idée de ce post vraiment interressante, je vais me pencher dessus.
En y réfléchissant d'avantage, plutôt que d'utiliser une "macro" il serrait ptet possible de faire une apli VB6 (ou autre) qui scrute les processus du PC. Si ya un ou pls excels on récupère le handle et on se débrouille pour trouver la liste des fichiers ouverts dedans.
Enfin, on gère le timeOut.
CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 1
22 avril 2010 à 10:00
Exact,
Je suis VOLONTAIREMENT resté sous 2003 car je n'ai eu que des déboires (énormes!) à vouloir passer tous les fichiers de 2003 en 2007 et faire migrer l'entreprise (Toutes les macros Word, Excel, Access étaient à revoir de fond en comble!)
C'est vrai que j'aurai dû préciser.
Mais pour "OnTime" (dans Excel 2003), je confirme : Certes pas de 1000ème de seconde (!) mais on n'en a pas besoin pour lancer une tâche différée comme dans ce code. Pour le décompte des dernières secondes, j'ai d'ailleurs procédé de la même manière dans ma précédente Source sur ce sujet, mais l'affichage du décompte est évidemment nettement plus stable avec "Application.Wait" retenu ici. Il est bien entendu que dans ce code, Tp180s doit être de type Variant.


Aide VB sur OnTime, méthode:

Cette méthode programme l'exécution d'une procédure à un moment précis (soit à une heure précise soit après l'écoulement d'un délai précis).

expression.OnTime(EarliestTime, Procedure, LatestTime, Schedule)
expression Obligatoire. Expression qui renvoie un objet Application.

EarliestTime Argument de type Variant obligatoire. Heure à laquelle vous voulez que la procédure s'exécute.

Procedure Argument de type String obligatoire. Nom de la procédure à exécuter.

LatestTime Argument de type Variant facultatif. Heure maximale à laquelle la procédure peut être exécutée. Par exemple, si vous affectez à l'argument LatestTime la valeur EarliestTime + 30 et que Microsoft Excel n'est pas en mode Ready, Copy, Cut ou Find au moment EarliestTime parce qu'une autre procédure est en cours d'exécution, Microsoft Excel attendra la fin de la procédure pendant 30 secondes. Si Microsoft Excel ne se trouve pas en mode Ready dans les 30 secondes, la procédure ne sera pas exécutée. Si vous ne spécifiez pas cet argument, Microsoft Excel attendra jusqu'à ce que la procédure puisse être exécutée.

Schedule Argument de type Variant facultatif. Cet argument a la valeur True pour programmer une nouvelle procédure OnTime. Il a la valeur False pour effacer une procédure précédemment définie. La valeur par défaut est True.

Notes
Utilisez Now + TimeValue(time) pour programmer une procédure à exécuter après un certain délai (à partir de maintenant). Utilisez TimeValue(time) pour programmer une procédure à exécuter à un moment précis.

Exemples
Cet exemple montre comment exécuter my_Procedure dans 15 secondes.

Application.OnTime Now + TimeValue("00:00:15"), "my_Procedure"

Cet exemple montre comment exécuter my_Procedure à 17 heures.

Application.OnTime TimeValue("17:00:00"), "my_Procedure"

Cet exemple montre comment annuler le paramétrage de OnTime de l'exemple précédent.

Application.OnTime EarliestTime:=TimeValue("17:00:00"), _
Procedure:="my_Procedure", Schedule:=False


Cdt
NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011
21 avril 2010 à 23:04
J'ai surfer un brin, et voici ce que j'ai trouvé.

Pour Microsoft, OnTime est un timer, mais ne s'utilise pas de la même manière d'un logiciel à un autre.
Dans Word il est impossible de stopper le timer une fois lancer et ne s'exécutera qu'une seul fois, après il faut le relancer. Perso, j'appel pas ça un timer, mais bon...
Pour Excel, le timer peut être stopper mais lui aussi ne s'exécute qu'une seul fois (soupir d'agacement). Et histoire d'en rajouter, il te dise que tu peux choisir le jour et l'heure d'exécution. Je crois que sûr le coup, il on vraiment oublier le concept du timer qui se réglait au millième de seconde.

Par contre, un détail est intéressant pour Word, le site insiste pour que l'on écrive le chemin complet de la macro comme ceci :
Application.OnTime When:=TimeValue("1:30 pm"), Name:="VBAProj.Module1.Start"
Ça sous-entend que l'on pourrait lancer une macro d'un autre fichier. L'idée est à creuser.

Après ça Microsoft dit plus grand chose mais les blogs eux donnent de précieuses informations ; Notamment que "When" doit être de type Variant quand on lance le timer et de type string quand on l'arrête. Intéressant non ?!!

Je me dis donc, que si maintenant il y a une différence de réaction pour la même fonction, c'est que nous n'avons pas la même version. Je suis sous 2007, et toi ?

Après cette rapide recherche, mon seul regret c'est que toute cette littérature est en anglais et donc difficile d'accès.

Allez ! au plaisir.
Bye
CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 1
21 avril 2010 à 22:21
Flocreate, bonjour et merci de ton commentaire.
Tu fais fort, mais je te comprends on ne peut mieux, car c'est justement parceque j'ai ce problème que j'ai proposé ce bout de code qui n'est qu'un faible partie d'une appli qui approche ce problème.
Juste pour info, car ça n'est pas l'objet ici, dans mon appli, AUCUN des fichiers qui sont "surveillés" n'est ouvert directement, mais TOUJOURS par un fichier de lancement. A l'ouverture, un *.txt spécifique au fichier surveillé est généré (détruit à la fermeture), et les infos de "qui ouvre" et "comment le joindre" peuvent facilement être récupérées et données via le fichier de lancement.
S'il s'agit d'un "oubli", après avertissement SONORE, le fichier bloqué est sauvé et enregistré proprement. Dans ces conditions, on peut mettre un fichier Excel, NON partagé à disposition d'utilisateurs en réseau (D'expérience, la gestion en partagé n'est hélas JAMAIS faite correctement par les utilisateurs).
L'appli en question est lourde et très spécifique, j'ai juste mis (trop vite!) en Source des petites parties sur lesquelles j'avais beaucoup cherché.
Quant à ta remarque sur "l'Excellisation" en Entreprise, c'est, je crois, dû au fait qu'Excel est quand même un superbe outil, mieux "compris" (!) des utilisateurs que d'autres logiciels, Acces en tête. Effectivement il y a beaucoup à dire là dessus!
Cdt
CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 1
21 avril 2010 à 21:57
Heuh....
L'intérêt, c'est justement d'éviter un timer, en appelant :
130.Application.OnTime Tp180s, "AlerteFin", , False
qui ferme le OnTime quand on quitte.
Moi, ça ne se "rouvre" pas.
Mais j'ai peut-être ai-je mal compris...

Pour T, Tp10s et Wbc, j'aurai pu effectivement les mettre en Dim, mais j'utilisais ces variables ailleurs: Je ne maîtrise vraissemblablement pas la différence entre Explicit + Dim et Explicit + Public... faut que j'aille voir un tuto quelque part!

Quant aux User, j'ai suivi a remarque et ça fonctionne, je ne le soupçonnais pas et en ai pris bonne note.

Enfin, le Lecture seule, dans mon appli, ce fichier ne l'est jamais, mais effectivement il fallait prévoir que pour une autre appli, il puisse l'être.

Merci encore.
Flocreate Messages postés 300 Date d'inscription lundi 17 juillet 2006 Statut Membre Dernière intervention 27 mai 2012 3
21 avril 2010 à 21:54
bonjour,
une idée fort intéressante ^^
Dans ma boîte, ils ont la manie (affreuse a mon gout) de tout metre dans des fichiers excel et en particulier des données utiles à plusieurs utilisateurs.

On pourrait étayer un peut plus l'idée.
Il faudrait que la gestion ne soit pas dans un fichier mais en tant que macro globale a tous les classeurs.
Il faudrait que la macro se lance au démarrage d'une instance d'excel

Avec une classe cSPY
comprenant le nom d'un classeur
son identifiant unique et inchangeant dans l'instance
sa date et heure d'ouverture

A chaque ouverture d'un classeur on initialise un objet cSPY que l'on stoque
A chaque fermeture d'un classeur on détruit la classe cSPY associée

On trouve un moyen pour détecter l'inactivité sur un classeur (par classeur ou sur tous les classeurs ...)

On applique le warning (par balloon et systray ?) puis on quite le classeur.
Avec sauvegarde (mais locale, faut pas écraser l'originale sans demander l'avis >_< )

On peut même utiliser un fichier de config ".ini" pour définir le temps pour la détection, le son a jouer et encore + mieux
"une liste d'exclusion de fichiers" c'est a dire la liste des noms de classeurs a ne pas prendre en compte pour la détection / fermeture.

bon ca c la version simple, on peut imaginer encore mieux avec envoie a un serveur de l'information d'appropriement d'un classeur. comme ca on sait c qui qui bloque le fichier pour tout le monde >_<

enfin, avoir un moyen de désactiver ou empêcher notre fonction de s'appliquer a un classeur
(ajouter une entrée temporaire a la liste d'exclusion par exemple ^^)

bon c juste une idée comme ca. si j'avais du temps je pourrais en faire des choses ^^
NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011
21 avril 2010 à 19:50
Pour le point 1, CerberusPau, ok c'est logique.
Mais pour le point 2, je reste pas d'accord. Puisque ma variable "MemData" est public, tu peux l'appeler de n'importe où. Ce n'est pas la peine d'utiliser une UserForm.

Bon je continue sur ma lancé, car j'ai testé ce code plus en profondeur, aujourd'hui.
3) Les variables Tp10s, WbC et T sont public ce qui n'est pas nécéssaire mais la raison doit être la même que pour 1). J'ai quand même un gros doute pour WbC.
4) La fonction Application.OnTime n'est pas un timer mais plutôt une tâche planifier. Autre problème du à OnTime, si l'événement ne s'est jamais produit une fois, on ne peut le désactiver. Résultat : si le fichier à été fermé il se rouvre.
Il faut donc utiliser un vrai Timer.
5) Si le fichier est en lecture seul, il n'y a de raison de chercher à le fermer.

Private AlerteFinID As Long
'************************************************************************************
Public Declare Function SetTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long, _
ByVal uElapse As Long, _
ByVal lpTimerFunc As Long) As Long
Public Declare Function KillTimer Lib "user32" ( _
ByVal HWnd As Long, _
ByVal nIDEvent As Long) As Long
'************************************************************************************

Sub StartTempo()
'=> Lancement de la durée d'accès libre (5 minutes avant alerte de relance)
Dim Minutes As Single, Secondes As Single, Durée As Single

If ThisWorkbook.ReadOnly = True Then Exit Sub ' Le fichier est en lecture seule, il n'y a pas de raison de le fermer

Minutes = 5
Secondes = 0
Durée = Minutes * 60 + Secondes 'définit la durée de 300 secondes avant de lancer la prodédure de fermeture automatique
AlerteFinID = SetTimer(0&, 0&, Durée * 1000&, _
AddressOf AlerteFin) 'appelle la procédure de fermeture automatique
MemData.TpIn = True 'tempo AlerteFinID activée
End Sub
'************************************************************************************

Sub Relancer()
'=> Arrêt du processus automatique de fermeture et relance

Alerter.Hide

FermerAlerteFin 'arrêt de tempo AlerteFinID si engagée
MemData.TpIn = False 'RAZ tempo AlerteFinID
MemData.TpDe = False 'RAZ tempo Tp10s
StartTempo 'engage la relance
End Sub
'************************************************************************************


Sub AlerteFin(ByVal HWnd As Long, ByVal uMsg As Long, ByVal nIDEvent As Long, ByVal dwTimer As Long)
'=> Message de Relance (Arrêt Automatique engagé dans les 10 secondes)

MemData.TpIn = False 'tempo AlerteFinID échue
MemData.TpDe = True 'tempo Tp10s activée
Alerter.Show 'affichage du temps restant et du bouton de relance
Décompter 'lance le décompte final
End Sub
'************************************************************************************

Sub StopTempo()
'=> Arrêt du processus automatique de fermeture

FermerAlerteFin 'arrêt de tempo AlerteFinID si engagée
MemData.TpIn = False 'RAZ tempo Tp300s
MemData.TpDe = False 'RAZ tempo Tp10s
End Sub
'************************************************************************************

Sub FermerAlerteFin()
If ThisWorkbook.ReadOnly = True Then Exit Sub ' Le fichier est en lecture seule, il n'y a pas eu de raison de le fermer

'On Error Resume Next
KillTimer 0&, AlerteFinID 'arrêt du Timer "AlerteFinID"
End Sub
'************************************************************************************

Si je vois autre chose demain, je te fais signe.
CerberusPau Messages postés 377 Date d'inscription lundi 3 avril 2006 Statut Membre Dernière intervention 22 août 2018 1
21 avril 2010 à 09:43
Remarques toujours pertinentes : Tu nous y a habitué, S Nikator!
C'est vrai: Avec ma façon d'extraire des bouts de code d'une application que j'ai créée pour le proposer en source, j'oublie de simplifier...
1° Dans mon appli, il y a une deuxième boucle d'analyse des classeurs ("esclaves") ouverts et la fermeture auto peut être "dirigée" vers l'un d'eux, avant de fermer ThisWorkbook
2° Textbox créées car je peux être amené à les appeler par une autre appli qui doit voir si une des tempo tourne et bloquer son rebouclage.
NikatorS Messages postés 147 Date d'inscription mercredi 18 septembre 2002 Statut Membre Dernière intervention 15 avril 2011
20 avril 2010 à 21:22
Ca y est, je viens de pomper ta source !
Le résultat est nikel ! Pile-poil ce que j'en attendais.

Il y a cependant deux points à travaillez.
1)
Workbooks("Tempo.xls").Save => ThisWorkbook.Save
Workbooks("Tempo.xls").Close => ThisWorkbook.Close
Ainsi, si on renomme ton fichier, le code plante pas.

2)
"MemData" est une UserForm
Là j'ai envie de dire "Pas bien !! Scandale !!" Mais bon, je dirais rien ;-) juste que ça prend de l'espace pour rien.
Déclares plutôt une structure et remplaces la nature de tes variables, de String à Boolean.

Type Etat
Mem1 As Boolean
Mem2 As Boolean
End Type
Public MemData As Etat

Puis à l'utilisation :

MemData.Mem1 = False 'RAZ Tempo Tp180s
MemData.Mem2 = False 'RAZ Tempo Tp10s

Voilà, j'espère que ça te sera utile.

S Nikator