VBA : Perte focus pendant macro

Résolu
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 - 5 juin 2009 à 10:11
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur 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)

20 réponses

PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
5 juin 2009 à 12:22
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>

??
++
3
bigfish_le vrai Messages postés 1835 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 20 novembre 2013 15
5 juin 2009 à 14:15
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+
3
hellangel777 Messages postés 267 Date d'inscription jeudi 5 février 2009 Statut Membre Dernière intervention 26 novembre 2013 1
5 juin 2009 à 10:28
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
0
hellangel777 Messages postés 267 Date d'inscription jeudi 5 février 2009 Statut Membre Dernière intervention 26 novembre 2013 1
5 juin 2009 à 10:37
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
0

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

Posez votre question
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
5 juin 2009 à 11:05
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)
0
hellangel777 Messages postés 267 Date d'inscription jeudi 5 février 2009 Statut Membre Dernière intervention 26 novembre 2013 1
5 juin 2009 à 11:23
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
0
us_30 Messages postés 2065 Date d'inscription lundi 11 avril 2005 Statut Membre Dernière intervention 14 mars 2016 10
5 juin 2009 à 11:59
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.
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
5 juin 2009 à 12:12
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
0
us_30 Messages postés 2065 Date d'inscription lundi 11 avril 2005 Statut Membre Dernière intervention 14 mars 2016 10
5 juin 2009 à 12:20
"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.
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
5 juin 2009 à 12:24
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
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
5 juin 2009 à 13:09
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 !
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
5 juin 2009 à 13:18
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.
0
PCPT Messages postés 13272 Date d'inscription lundi 13 décembre 2004 Statut Membre Dernière intervention 3 février 2018 47
5 juin 2009 à 13:32
et avec un petit monDoc.Application.Selection.MoveEnd dans la fonction?
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
5 juin 2009 à 13:58
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)
0
r1r2 Messages postés 22 Date d'inscription mardi 23 janvier 2007 Statut Membre Dernière intervention 31 mars 2010
5 juin 2009 à 15:11
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...
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
5 juin 2009 à 16:45
Très astucieux ça, bigfish_le vrai
Je vais tester ça dans le week-end.
Merci
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
5 juin 2009 à 16:56
Oups, j'ai oublié r1r2
Hélas, Range n'a pas du tout les mêmes propriétés (j'y avais aussi pensé)
0
hellangel777 Messages postés 267 Date d'inscription jeudi 5 février 2009 Statut Membre Dernière intervention 26 novembre 2013 1
5 juin 2009 à 17:38
Bonjour ou rebonjour à tous

Merci de cet échange, riche et constructif.

Bon week end
0
bigfish_le vrai Messages postés 1835 Date d'inscription vendredi 13 mai 2005 Statut Membre Dernière intervention 20 novembre 2013 15
9 juin 2009 à 15:43
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+
0
cs_Jack Messages postés 14006 Date d'inscription samedi 29 décembre 2001 Statut Modérateur Dernière intervention 28 août 2015 79
9 juin 2009 à 16:13
Oups, pas essayé, désolé.
0
Rejoignez-nous