VBA : Perte focus pendant macro [Résolu]

Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
- - Dernière réponse : cs_Jack
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
- 9 juin 2009 à 16:13
Salut ta tou(te)s

J'ai un petit soucis qui m'énerve :
J'ai confectionné une macro sous Word 2003 qui prend quelques minutes à s'exécuter.
Pendant le déroulement de la macro, si l'utilisateur ouvre une autre instance de Word, la macro réoriente ses écritures sur cette nouvelle instance et, bien sûr, ça fait tout dérailler.
Je cherche donc le moyen de canaliser les instructions vers le document que j'ai ouvert et pas un autre.
Je m'y prends peut-être mal, c'est pour cela que je m'en remets à vos opinions.

Voilà comment je m'y prends :
   ' Création d'un nouveau document
    Dim monDoc As Document
 
   Set monDoc = New Document
    monDoc.Activate

et quand je veux écrire une ligne, par exemple un titre
    With Selection
        .TypeText TEXT:=Titre                      ' Ecrit Titre
        .TypeParagraph                             ' Passe à la ligne
        .MoveUp Unit:=wdLine, Count:=1             ' Remonte
        .Style = monDoc.Styles(wdStyleHeading1)    ' Format "Titre 1" ou "Heading 1"
        .MoveDown Unit:=wdLine, Count:=1           ' Redescend
    End With

Le problème donc, c'est que l'objet Selection est unique pour toutes les sessions de Word et que l'ouverture d'un nouveau Doc prend le focus.
J'ai tenté de le remplacer par monDoc.Application.Selection, mais cela n'a bien sûr rien changé.

Alors avant de pondre une usine à gaz pour bloquer le système pendant l'exécution de la macro, je m'en retourne vers vos opinions et expériences.

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

<hr />Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Afficher la suite 

Votre réponse

20 réponses

Meilleure réponse
Messages postés
13368
Date d'inscription
lundi 13 décembre 2004
Dernière intervention
3 février 2018
3
Merci
salut,

comme tu as dû le lire, la MSDN indiqué :





Référence du développeur
Word,

----

Selection,
objet



Représente la sélection actuelle
d'une fenêtre ou d'un volet. Une sélection représente soit une zone sélectionnée
(mise en surbrillance) du document, soit le point d'insertion si aucune partie
du document n'a été sélectionnée. Il ne peut y avoir qu'un seul objet
Selection par volet, et un seul objet Selection peut être actif
dans l'ensemble de l'application.
Remarques

Utilisez la propriété Selection pour renvoyer l'objet
Selection. Si vous n'utilisez aucun qualificateur d'objet avec la
propriété Selection, Microsoft Office Word renvoie la sélection figurant
dans le volet actif de la fenêtre du document actif. L'exemple suivant montre
comment copier la sélection actuelle du document actif.

<hr size ="2" width="100%" />
de ce que j'en comprends çà veut dire qu'on est parfois obligé (propriétés spécifique) d'utiliser l'objet selection, qui est en lecture seule

je vois peu d'issue....
voici ce que j'ai essayé et qui fonctionne sous word 2007
(je te mets le code complet)

çà a le mérite de très peu modifier ton code existant mais en effet on force à sélection à chaque fois

Option Explicit
Dim monDoc As Document

Private Sub Document_Open()
    Set monDoc = New Document
    monDoc.Activate
End Sub

Private Sub CommandButton1_Click()
    With maSelection
        .TypeText Text:="Titre"           ' Ecrit
Titre
        .TypeParagraph                   
' Passe à la ligne
        .MoveUp Unit:=wdLine, Count:=1   
' Remonte
        .Style = monDoc.Styles(wdStyleHeading1) ' Format "Titre 1" ou "Heading 1"
        .MoveDown Unit:=wdLine, Count:=1 
' Redescend
    End With
End Sub

'la bidouille ici
Private Function maSelection() As Selection
    monDoc.Select
    Set maSelection = monDoc.Application.Selection
End Function

<small>[../code.aspx?ID=39466 Coloration VB6, VBA,
VBS]</small>

??
++

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 104 internautes ce mois-ci

Commenter la réponse de PCPT
Messages postés
1839
Date d'inscription
vendredi 13 mai 2005
Dernière intervention
20 novembre 2013
3
Merci
Salut jack, Salut a tous,

une solution a l'aide d'une petit classe

dans un module de classe appeler

WdAppliEvents:

Option Explicit

Public WithEvents Wd As Word.Application
Public ParentDoc As Document

Private Sub Wd_DocumentOpen(ByVal Doc As Document)
    'si l'utilisateur ouvre un doc pendant l'execution d'une macro Application.UserControl sera egale a True
    If Application.UserControl = True Then
        Me.ParentDoc.Activate
    End If
End Sub

dans un module:

Private WdApp As WdAppliEvents

Sub Register_Event_Handler()
    Set WdApp = New WdAppliEvents
    Set WdApp.Wd = Word.Application
    Set WdApp.ParentDoc = Documents("Mondocument.doc") 'nom du document qui doit rester activé
End Sub

A+

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources a aidé 104 internautes ce mois-ci

Commenter la réponse de bigfish_le vrai
Messages postés
271
Date d'inscription
jeudi 5 février 2009
Dernière intervention
26 novembre 2013
0
Merci
Bonjour,

Un truc me turlupine. La perte de focus n'est-elle pas du à :
monDoc.Activate

En effet, en lancant un nouveau doc la propriété activate est modifiée par le nouveau document. Enfin c'est ce qui me semble logique.
Ne peut-on pas verouiller la valeur d'activate?
Ma curiosité m'emporte et j'espere qu'une solution va apparaitre...
En attendant bon courage Jack. Je continue de regarder de mon coté.

HellAngel777
<hr />
Les machines ne font pas d'erreurs
Heureusement nous sommes humains
Commenter la réponse de hellangel777
Messages postés
271
Date d'inscription
jeudi 5 février 2009
Dernière intervention
26 novembre 2013
0
Merci
Re :
J'ai fait quelques petite recherche...
Afin de ne pas perdre le focus dans le cas de l'ouverture d'un nouveau document ne peut on pas faire un ruc de ce genre :

ActiveDocument.ActiveWindow.Previous.Activate

C'est à dire detecter l'ouverture d'un nouveau document et laisser l'activate sur la feuille de la macro ???

HellAngel777
<hr />
Les machines ne font pas d'erreurs
Heureusement nous sommes humains
Commenter la réponse de hellangel777
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Salut et merci de te pencher sur mon cas.
Ton idée de ne pas donner le focus au nouveau document est une idée à creuser.
Mais, à mon avis, puisque "Selection" ne s'adresse qu'au document qui est actif, il va bien falloir lui donner le focus à un moment.
En fait, je suis en train de chercher une astuce de ce genre là :
Quand je crée un tableau dans Word, j'utilise cette syntaxe :
   Dim oTable As Word.Table
   Set oTable = monDoc.Tables.Add(Range:=Selection.Range, _
                          NumRows:=1, _
                          NumColumns:=3, _
                          DefaultTableBehavior:=wdWord9TableBehavior, _
                          AutoFitBehavior:=wdAutoFitFixed)
et quand j'ai besoin de travailler dans le tableau :
   With oTable
      ...
   End With
Dans ce cas là, puisque je m'adresse à un objet, oTable, celui-ci est unique, donc (je pense) pas de problème de focus.

Je voudrais trouver comment m'adresser à mon document sans passer par Selection qui est un objet trop "générique".
Va t-il falloir que je répète sans cesse un  monDoc.Activate  pour être sûr qu'il ait toujours le focus au moment où j'utiliserai Selection ?
Ca me parait bien lourd ...

Vala
Jack, MVP VB
NB : Je ne répondrai pas aux messages privés

<hr />Le savoir est la seule matière qui s'accroit quand on la partage (Socrate)
Commenter la réponse de cs_Jack
Messages postés
271
Date d'inscription
jeudi 5 février 2009
Dernière intervention
26 novembre 2013
0
Merci
Question bête : ton document est enregistré par défaut?
Si c'est le cas la syntaxe :
Documents("NomduDoc.doc").Activate
Ne peut elle pas être utilisée?

 * Je suis entrain de regarder et de creuser l'idée de ne pas donner le focus à la nouvelle feuille. Si j'arrive a quelque chose par ce moyen je te file le code.

HellAngel777
<hr />
Les machines ne font pas d'erreurs
Heureusement nous sommes humains
Commenter la réponse de hellangel777
Messages postés
2117
Date d'inscription
lundi 11 avril 2005
Dernière intervention
14 mars 2016
0
Merci
Bonjour,

Une solution rapide c'est de retenir le nom du document juste après la création pour le rappeler ensuite...
   
mem = monDoc.Name  
Application.Documents(mem).Select

Amicalement,
Us.
Commenter la réponse de us_30
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Non, mon doc n'est enregistré qu'à la fin, mais ce n'est pas un problème, je peux utiliser, de la même manière
   monDoc.Activate
Je voudrais justement éviter de coller à tour de bras des Activate partout (les macros font 2Mo)

(30 min plus tard ...)
Bon, ça y est, j'ai trouvé le moyen :
Dans mes modules, j'ai une quarantaine de procédures (Sub et Function)
Au début de chaque procédure (utilisant Selection), j'ai mis ceci :
   Dim maSelection As Selection
   monDoc.Activate
   Set maSelection = monDoc.Application.Selection
   With maSelection
         ...
   End With
Je déclare un objet qui prend la place de Selection, le programme ensuite ne se réfère qu'à ce nouvel objet maSelection.
Ce qui fait que, même si je donne volontairement le focus à un autre document ouvert en plein milieu de mon code (j'ai fait le test), le programme continue à travailler sur l'objet maSelection --> Plus d'interaction.

Merci beaucoup Hellangel777 pour tes suggestions
Commenter la réponse de cs_Jack
Messages postés
2117
Date d'inscription
lundi 11 avril 2005
Dernière intervention
14 mars 2016
0
Merci
"Non, mon doc n'est enregistré qu'à la fin"


Oui ! Ton document a nécessairement un nom par défaut... "Document1" par exemple... qu'il soit enregistré à la fin fermeture avec un autre nom ne pose de problème...  Donc si tu utilises une variable global pour retenir le nom, tu n'as plus de souci. Ensuite ta proposition ne fait que la même chose (retenir la référence de la selection en memoire)... mais en plus compliqué... mais si tu préfères...

Amicalement,
Us.
Commenter la réponse de us_30
Messages postés
13368
Date d'inscription
lundi 13 décembre 2004
Dernière intervention
3 février 2018
0
Merci
posts croisés, oublié de refresh ^^

un activate avec un select c'est pas bête non plus oui



Private Function 
maSelection() 
As 
Selection



    monDoc.Activate

    monDoc.Select




    Set maSelection = monDoc.Application.Selection
End Function
Commenter la réponse de PCPT
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
lol, merci PCPT
Je vais quand même essayer de faire un Select sans faire de Activate parce que, conséquence du forçage de Activate, c'est que pendant l'exécution de la macro, le clavier est dirigé vers le document en cours d'élaboration, donc un jour ou l'autre, ils (les utilisateurs) vont se faire avoir.

us_30 : Ce que je veux dire, c'est qu'il n'est pas nécessaire de mémoriser le nom temporaire de ce document puisque j'ai déjà un objet, monDoc, qui pointe dessus, sans avoir besoin de préciser son nom. C'est encore plus facile !
Commenter la réponse de cs_Jack
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Et bah, et c'est logique :
monDoc.Select  sélectionne le contenu entier de mon document.
Donc quand j'utilise cette méthode en plein milieu, les écritures qui suivent remplacent les premières.
Donc, le .Activate est obligatoire, hélas.
Commenter la réponse de cs_Jack
Messages postés
13368
Date d'inscription
lundi 13 décembre 2004
Dernière intervention
3 février 2018
0
Merci
et avec un petit monDoc.Application.Selection.MoveEnd dans la fonction?
Commenter la réponse de PCPT
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
grrrrrr² : j'ai perdu ma réponse finale à cause d'un problème de serveur (rageant)

Je disais donc :
Oui, PCPT, cela aurait pu être une solution viable, mais ma sélection se balade dans le document, je n'écris pas toujours à la fin du document.

Sur une suggestion de HellAngel777, j'ai simplifié la chose :
Déclarer 
   Private maSelection As Selection
en tête de mon module (partie déclarations)
puis, juste après avoir créé le nouveau document et l'avoir activé
   Set maSelection = monDoc.Application.Selection
et remplacer Selection par maSelection dans tout mon code.
Bien sûr, il faut penser à faire un
   Set maSelection = Nothing
avant de refermer le document

Cela simplifie la programmation et monDoc garde le focus en permanence.
De ce fait, si j'ouvre une autre instance de Word pendant que mes macros travaillent, je ne peux rien faire dedans puisque je n'ai (presque) jamais le focus.
C'est un peu chiant, mais c'est sécurisant, c'est le principal.

Il en ressort qu'il n'est pas possible de travailler dans un document sans capturer le focus.
C'est comme ça, dommage

En tous les cas, un grand merci à tous !
Et comme je le dis souvent, poser sa question, c'est déjà 50% de la réponse.

(cette fois-ci, je fais un Copier avant de poster)
Commenter la réponse de cs_Jack
Messages postés
22
Date d'inscription
mardi 23 janvier 2007
Dernière intervention
31 mars 2010
0
Merci
Bonjour à tous,




Sinon, il me semble qu'avec l'objet Range on peut réaliser à peu près la même chose qu'avec l'objet Selection.


Mais bon, avec le nombre de Sub et Function que tu as, ça risque d'être
long à modifier, d'autant que je ne suis pas complètement sûr qu'on ait du 1 pour 1 entre les propriétés et méthodes des deux objets...
Commenter la réponse de r1r2
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Très astucieux ça, bigfish_le vrai
Je vais tester ça dans le week-end.
Merci
Commenter la réponse de cs_Jack
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Oups, j'ai oublié r1r2
Hélas, Range n'a pas du tout les mêmes propriétés (j'y avais aussi pensé)
Commenter la réponse de cs_Jack
Messages postés
271
Date d'inscription
jeudi 5 février 2009
Dernière intervention
26 novembre 2013
0
Merci
Bonjour ou rebonjour à tous

Merci de cet échange, riche et constructif.

Bon week end
Commenter la réponse de hellangel777
Messages postés
1839
Date d'inscription
vendredi 13 mai 2005
Dernière intervention
20 novembre 2013
0
Merci
Salut Jack,

j'ai dans l'idée de faire un snippet a partir de ce que je t'ai donné. Est-ce que cela fonctionne bien ?

A+
Commenter la réponse de bigfish_le vrai
Messages postés
14010
Date d'inscription
samedi 29 décembre 2001
Dernière intervention
28 août 2015
0
Merci
Oups, pas essayé, désolé.
Commenter la réponse de cs_Jack

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.