IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Bookmarks détruits avec Interop Word


Sujet :

C#

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Expert Maritime
    Inscrit en
    Février 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert Maritime
    Secteur : Transports

    Informations forums :
    Inscription : Février 2019
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Bookmarks détruits avec Interop Word
    Bonjour à tous,
    Bien que débutant je me suis lancé dans l'écriture, en C#, d'une application "Form" pour bureau Windows.
    Son objet est, entre autre, de créer des documents Word à partir de modèles existants.
    Grace à la fréquentation assidue du forum, j'ai réussi à faire ce que je souhaitais pour la création et l'enregistrement.
    En revanche, je butte sur l'insertion des informations des TextBoxes du formulaire dans les signets Word préexistants ( qui sont au nombre de vingt à soixante selon les documents).
    J'utilise une boucle "foreach" qui passe en revue les signets vierges du document et lit dans des listes les adresses des textes correspondant à y insérer.
    Tout se passe bien mais les signets sont détruits ce qui ruine l'usage des champs REF qui est pourtant l'essentiel de l'automatisation du process.
    J'ai bien essayé de les recréer dans la foulée mais là, le "forech" reboucle indéfiniment sur le même signet (le premier par ordre alphabétique)
    J'ai beaucoup cherché sur le web et essayé de nombreuses combinaisons malheureusement sans succès.
    Voici la partie du code défectueux, je l'ai commenté pour une lecture plus directe du problème.
    Pouvez-vous m'aider ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    	....
     
               foreach (string mod in modeles)// BOUCLE d'appel DE CREATION DES DOCUMENTS à partir des modèles Word sélectionnés au " void ChoixDoc()"
                {
                    modelDoc = mod;  
                    CreateDocFile();
                }  // fin de BOUCLE d'appel DE CREATION DES DOCUMENTS Word
     
                void CreateDocFile() // _____CREATION DE DOCUMENT Word .docx 
                {               
                    Word.Application objWord = new Word.Application {Visible = false}; // connexion à Word           
                    object TemplateName = Path.Combine(ModelPath, modelDoc); // Chemin du fichier modèle choisi
                    Word.Document newDoc = objWord.Documents.Add(ref TemplateName); //création d'un nouveau document d'après le modèle                           
     
                    //remplissage des signets selon les listes préétablies
                    foreach (Word.Bookmark signet in newDoc.Bookmarks)
                    {
                        string nomSignet = signet.Name;
                        int indexB = Array.IndexOf(liste_Signet, nomSignet); // On récupére l'index du signet (liste de corrélation préétablie [])
                        string textSignet = liste_Signet_Texte[indexB, 1];   //on récupère le texte de la textBox du formulaire correspondant au nom du signet (liste de corrélation 2D préétablie[,])
                        if (textSignet != "")   
                        {                                             
                            //object name = nomSignet;  // -> //première méthode  
                            //Word.Range range = newDoc.Bookmarks.get_Item(ref name).Range;
     
                            Word.Range range = newDoc.Bookmarks.get_Item(nomSignet).Range;   // -> autre méthode sans passer par la ref name                               
                           //Pas mieux pour la boucle
                            range.Text = textSignet;
                            //object newRange = range; // -> essai sans la ref newRange : même pb de foreach !
     
                            newDoc.Bookmarks.Add(nomSignet, range);
                            /*  Cette dernière instruction bloque la boucle foreach qui fonctionne sur le premier signet
                                puis reboucle indéfiniement sur ce même signet sans passer au suivant.
                                En revanche le texte premier signet est bien inséré et le signet recréé comme on l'attend.
                                Si on commente cette instruction pour la sauter, la boucle fonctionne et tous les textes des signets sont insérés.
                                Mais, les signets eux-mêmes disparaissent ce qui ruine le document 
                                qui en fait grand usage par l'intermédiaire de champs "REF".
                            */
                        }
                    //pour visualisation de déboguage
                       MessageBox.Show("Avant rebouclage \nLe signet  = " + nomSignet + " = ?signet.Name = " +signet.Name + "\n son texte est : " + textSignet);                 
                    }
     
                    //Attribution du nom de fichier à partir des listes de noms des modèles[] et des noms à attribuer[,]
                    int indexF = Array.IndexOf(liste_modelDoc, modelDoc);
                    string nomFichier = liste_Attribution_Nom [indexF,1];
                    string recapPath = Path.Combine(RepPath, nomFichier);      
                    object fileName = recapPath;              
                    newDoc.SaveAs2(ref fileName); // Enregistrement du document avec son nouveau nom
                    newDoc.Close();
     
                    objWord.Quit();               
                }  //______ fin de CREATION DE DOCUMENT Word .docx

  2. #2
    Nouveau Candidat au Club
    Homme Profil pro
    Expert Maritime
    Inscrit en
    Février 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert Maritime
    Secteur : Transports

    Informations forums :
    Inscription : Février 2019
    Messages : 3
    Points : 1
    Points
    1
    Par défaut EDIT
    Re-bonjour à tous,
    J'ai finalement résolu le problème en créant une "liste intermédiaire" sur laquelle j'applique une boucle "for". (pas sur que la méthode soit conforme aux canons de la programmation mais ça marche).
    Pour ceux que cela pourrait intéresser voici le code modifié :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
                void CreateDocFile() // _____CREATION DE DOCUMENT Word .docx 
                {             
                    Word.Application objWord = new Word.Application {Visible = false}; // connexion à Word           
                    object TemplateName = Path.Combine(ModelPath, modelDoc); // Chemin du fichier modèle choisi
                    Word.Document newDoc = objWord.Documents.Add(ref TemplateName); //création d'un nouveau document d'après le modèle                           
     
                    //remplissage des signets selon les listes préétablies
                    foreach (Word.Bookmark signet in newDoc.Bookmarks)
                    {
                        bmkList.Add(signet.Name);
                    }
                    for(int i=0 ;i<bmkList.Count ; i++)
                    {
                        string nomSignet = bmkList[i];
                        int indexBm = Array.IndexOf(liste_Signet, nomSignet);// On récupére l'index du signet (liste de corrélation préétablie [])
                        string textSignet = liste_Signet_Texte[indexBm, 1];//on récupère le texte de la textBox du formulaire correspondant au nom du signet (liste de corrélation 2D préétablie[,])
                        if (textSignet != "")
                        {
                            Word.Range range = newDoc.Bookmarks.get_Item(nomSignet).Range;
                            range.Text = textSignet;
                            newDoc.Bookmarks.Add(nomSignet, range);
                        }
                    }
                    //Attribution du nom de fichier à partir des listes de noms des modèles[] et des noms à attribuer[,]
                    int indexF = Array.IndexOf(liste_modelDoc, modelDoc); 
                    string nomFichier = liste_Attribution_Nom [indexF,1];
                    string recapPath = Path.Combine(RepPath, nomFichier);      
                    object fileName = recapPath;              
                    newDoc.SaveAs2(ref fileName); // Enregistrement du document avec son nouveau nom
                    newDoc.Close();
     
                    objWord.Quit();               
                }  //______ fin de CREATION DE DOCUMENT Word .docx
    Autre question :
    Parmi les modèles que j'utilise, certains (.dotm) ont une macro VBA.
    Elle récupère les résultats d'un fichier Excel qui est créé en même temps et dans le même répertoire que les fichiers Word .docm.
    Cette macro utilise le nom générique du fichier Excel, en l’occurrence : "Détail des montants.xlsx".
    Je sais enregistrer le fichier Excel sous un autre nom au moment de sa création, par exemple "Détail des montants + référence du dossier + .xlsx".
    Serait-il possible à l'exécution de l'application C# de modifier la macro VBA Word pour y passer le nouveau nom de fichier Excel ?
    Cordialement
    PMV

  3. #3
    Inactif  

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2012
    Messages
    4 904
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2012
    Messages : 4 904
    Points : 10 168
    Points
    10 168
    Billets dans le blog
    36
    Par défaut
    Bonjour,

    Navré pour toi, mais je connais plus VB.net que C# et là je réponds de mémoire pour Word.


    Tout se passe bien mais les signets sont détruits ce qui ruine l'usage des champs REF qui est pourtant l'essentiel de l'automatisation du process.
    Ça c'est typique de Word. Dès que l'on place quelque chose directement sur le signet; il est détruit. En gros, je vois deux façons de t'en (s'en) sortir.

    1) Travailler avec un modèle dotm(avec macros) ou dotx (sans macros). et enregistrer obligatoirement le document final sous un autre nom et ne pas enregistrer le modèle en quittant. Comme le modèle N'est pas modifié, les signets restent en place.

    2) tu peux également déplacer le point d'insertion vers la droite ou vers la gauche (moveright, ou moveleft) avec un objet Selection de Word. Exemple C# avec Microsoft.interop.word En principe, si tu places tes infos à côté du signet; le signet devrait être préservé.

    Je sais enregistrer le fichier Excel sous un autre nom au moment de sa création, par exemple "Détail des montants + référence du dossier + .xlsx".
    Serait-il possible à l'exécution de l'application C# de modifier la macro VBA Word pour y passer le nouveau nom de fichier Excel ?
    Je dirais théoriquement oui, mais c'est plus difficile qu'il n'y parait et il faut modifier la configuration de Word dans Word avant de pouvoir procéder. (Parce que c'était une façon commode d'introduire des virus, Microsoft a renforcé les procédures de sécurité dans Office.) Mais, comme tu peux piloter Excel directement à partir de C#, tu peux enregistrement directement ton nouveau classeur à partir de ton programme; sans toucher à la macro. Ou bien tu renommes immédiatement le fichier Excel, une fois qu'il a été crée. (Le problème, c'est d'être sûr que le fichier Excel est bien fermé et libéré par la macro VBA.) En plus compliqué, tu peux passer par le registre mais VBA doit utiliser une section pré-définie du registre. (Une clef commune pour toutes les applications VB6-VBA, avec une sous-clef pour chaque application.) Pour déroger à cel en VBA, il faut passer par l'API Windows.
    À ma connaissance, le seul personnage qui a été diagnostiqué comme étant allergique au mot effort. c'est Gaston Lagaffe.

    Ô Saint Excel, Grand Dieu de l'Inutile.

    Excel n'a jamais été, n'est pas et ne sera jamais un SGBD, c'est pour cela que Excel s'appelle Excel et ne s'appelle pas Access junior.

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Expert Maritime
    Inscrit en
    Février 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert Maritime
    Secteur : Transports

    Informations forums :
    Inscription : Février 2019
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    @clementmarcotte

    Bonjour,
    Merci de vous être intéressé à mes questions de débutant.
    Le problème des signets Word est résolu comme je l'indiquais dans mon second message.
    Pour ce qui est du pilotage des macros VBA je crains que cela ne dépasse largement mes capacités, d'autant plus que l'application a vocation à être installée sur plusieurs postes dont les utilisateurs n'auront pas forcément la patience pour gérer un dysfonctionnement que j'imagine quasi certain.
    Je vais donc m'en tenir à ce qui fonctionne pour le moment.
    Cordialement
    PMV

Discussions similaires

  1. Travailler sur Word avec Microsoft.Office.Interop.Word
    Par Claude_Azoulai dans le forum VB.NET
    Réponses: 0
    Dernier message: 30/08/2017, 16h15
  2. Probleme avec interop word pour office 2013
    Par 44ced dans le forum VB.NET
    Réponses: 11
    Dernier message: 23/09/2014, 16h56
  3. [Débutant] Probleme avec Silverlight et Microsoft.Office.Interop.Word.dll
    Par manal00 dans le forum Silverlight
    Réponses: 0
    Dernier message: 20/06/2012, 13h42
  4. lire un fichier.doc avec la classe interop.word
    Par calvi2002 dans le forum VB.NET
    Réponses: 6
    Dernier message: 03/12/2010, 23h32
  5. Pilotage de WORD avec Office.Interop.Word
    Par lead8209 dans le forum C#
    Réponses: 2
    Dernier message: 27/08/2010, 14h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo