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

Windows Forms Discussion :

[VB.NET]Processus Excel persistant


Sujet :

Windows Forms

  1. #1
    Membre actif Avatar de Yolak
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Vosges (Lorraine)

    Informations forums :
    Inscription : Mars 2007
    Messages : 341
    Points : 206
    Points
    206
    Par défaut [VB.NET]Processus Excel persistant
    Bonjour à tous,
    Je sais que le sujet à été discuté dans tout les sens sur le forum, mais je n'ai jamais trouvé une explication complète sur le phénomène:

    Mon appli doit ouvrir un fichier Excel, faire deux ou trois manip dedans (genre supprimer des colonnes, des lignes,...) , sauvegarder le fichier en csv (séparateur point virgule) puis le fermer.
    Cette procédure se trouve dans une boucle qui permet d'exécuter ce traitement sur tout les fichiers Excel qui se trouvent dans un dossier.
    Voici le code:

    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
    Private Sub Button_Executer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button_Executer.Click
            Dim appExcel As Excel.Application 'Application Excel
            Dim wbExcel As Excel.Workbook 'Classeur Excel
            Dim wsExcel As Excel.Worksheet  'Feuille Excel
     
            Dim TheFile As String 'Variable pour le nom du fichier
            Dim NewFile As String 'Variable pour le nom du fichier transformé
            Dim Rep As String
     
     
            appExcel = CreateObject("Excel.Application")
            Rep = Me.Tb_Path_Source.Text
            TheFile = Dir(Rep & "\*.xlsx")   'Listing des fichier Excel...
            While TheFile <> "" 'Tant que non vide
                'Ouverture d'un fichier Excel
                wbExcel = appExcel.Workbooks.Open(Rep & "\" & TheFile)
                'wsExcel correspond à la première feuille du fichier
                wsExcel = wbExcel.Worksheets(1)
     
                '#####################################################################################################################
                'Mon code de traitement sur wsExcel
                '#####################################################################################################################
     
                'Ce if permet de tronquer le nom du fichier pour eviter qu'il soit trop long
                If Len(TheFile) > 50 Then
                    TheFile = Strings.Left(TheFile, 40)
                    NewFile = TheFile & "~"
                Else
                    NewFile = Microsoft.VisualBasic.Left(TheFile, InStrRev(TheFile, ".") - 1)
                End If
     
                ChDir(Me.Tb_Path_Compil.Text)
                wbExcel.SaveAs(Filename:= _
                    Me.Tb_Path_Compil.Text & "\" & NewFile & ".csv", FileFormat:=Excel.XlFileFormat.xlCSVWindows)
                wsExcel.Delete()
                wbExcel.Close(SaveChanges:=False)
                appExcel.Quit()
                wsExcel = Nothing
                wbExcel = Nothing
                appExcel = Nothing
                TheFile = Dir() 'Fichier suivant
            End While
        End Sub
    J'ai essayé des tas de choses mais rien y fait, j'ai toujours ce fichu processus Excel qui reste dans le gestionnaire des tâches.
    Je me demande si ça vient du fait que je fait un SaveAs et que j'enregistre non pas en xls (ou xlsx) mais en csv...

    Est-ce que quelqu'un pourrait me conseiller?

    Merci d'avance !
    Épargnez votre cerveau : éteignez votre télé !

  2. #2
    Membre habitué Avatar de M.Max
    Homme Profil pro
    Inscrit en
    Décembre 2009
    Messages
    90
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2009
    Messages : 90
    Points : 127
    Points
    127
    Par défaut
    Dans un programme en VB j'avais besoin d'enregistrer des infos dans un fichier csv.
    De mémoire j'utilisais Close() et non pas Quit() pour l'objet Excel.Application et ça marchait parfaitement.

    Enfin je pense que tu as déja du essayer.

    Mes 2 cts.

    Cdt

  3. #3
    Membre actif Avatar de Yolak
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Vosges (Lorraine)

    Informations forums :
    Inscription : Mars 2007
    Messages : 341
    Points : 206
    Points
    206
    Par défaut
    Bonjour et merci pour la réponse.

    Close n'est pas un membre de Excel.Application.

    Je ne pense pas que ce soit la solution.

    Je cherche toujours!
    Épargnez votre cerveau : éteignez votre télé !

  4. #4
    Membre émérite

    Homme Profil pro
    Software Developer
    Inscrit en
    Mars 2008
    Messages
    1 470
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Software Developer

    Informations forums :
    Inscription : Mars 2008
    Messages : 1 470
    Points : 2 368
    Points
    2 368
    Par défaut
    Au pire tu peux faire avec Moi je fait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    myWb.Close(False)
                myApp.Quit()
                myWb = Nothing
                myApp = Nothing
    et ça fonctionne très bien

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Août 2008
    Messages
    310
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 310
    Points : 347
    Points
    347
    Par défaut
    Petit question : Quand tu retrouves le processus Excel activé, as-tu exécuté ton appli en mode debug, mis un point d'arrêt dans ton while et stoppé le debug en cours d'éxecution ? Si c'est ce cas de figure, c'est normal que le processus ne se ferme pas, Visual Studio ne ferme pas automatiquement tous les processus à l'arrêt d'un debug et donc tu dois les fermer via le gestionnaire de processus.

    Sinon arrange ton code de tel façon dans le while pour voir :

    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
     While TheFile <>
              Try
                  '......
                  '......
                  'Le code de traitement
                  '......
                  '......
                  wbExcel.SaveAs(Filename:= _Me.Tb_Path_Compil.Text & "\" & NewFile & ".csv", FileFormat:=Excel.XlFileFormat.xlCSVWindows)
     
                  ws.Delete()
     
               Catch ex As COMException
                   MessageBox.Show(ex.ToString())
               Finally
                   wbExcel.Close(SaveChanges:=False)
                   wbExcel = Nothing
               end Try
               TheFile = Dir() 
            End While
     
            'Place le quit après le while
            appExcel.Quit()
            appExcel = Nothing
    Le quit après le while, tu te sers tout le temps de l'objet, ça ne sert à rien de le fermer après chaque passage.

  6. #6
    Rédacteur/Modérateur
    Avatar de Skalp
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2006
    Messages
    1 694
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 694
    Points : 2 927
    Points
    2 927
    Par défaut
    Citation Envoyé par Yolak Voir le message
    Je sais que le sujet à été discuté dans tout les sens sur le forum, mais je n'ai jamais trouvé une explication complète sur le phénomène
    J'avais fait un message à ce sujet sur le forum Contribuer, mais il n'est plus visible car il va passer en FAQ très prochainement.
    Voilà tout de même le contenu qui devrait te permettre de résoudre ton problème :
    Nombreux sont ceux qui rencontrent ce problème : lorsque vous quittez une automation, vous utilisez (à quelques détails près) cette portion de code :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    monAppli.Quit();
    monAppli = null;
    Le plus souvent, ceci ne suffit pas à fermer le processus office : vous pouvez toujours le voir dans le gestionnaire des tâches. Ainsi, lorsque vous ouvrez le document, avec lequel vous avez travaillé par automation, depuis Windows, il refuse de l’ouvrir au titre qu’il est en cours d’utilisation par… vous-même !
    Voilà donc quelques astuces pour libérer les ressources automation efficacement :
    1. Déclarer les objets avec des variables indépendantes :
    Par exemple, ne faites pas :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    Workbook monClasseur = monAppli.Workbooks.Add();
    Mais plutôt :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Workbooks mesClasseurs = monappli.Workbooks;
    Workbook monClasseur = mesClasseurs.Add();
    Pour une automation simple, cela peut passer ; mais pour une automation complexe, cela peut s’avérer extrêmement fastidieux !
    2. Libérer les références aux objets COM :
    Utilisez la méthode suivante pour libérer les références à vos objets COM :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    System.Runtime.InteropServices.Marshal.ReleaseComObject(monAppli);
    3. Utiliser le Garbage Collector (GC) :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    GC.Collect();
    GC.WaitForPendingFinalizers();
    Il peut être utile de doubler cette portion, dans le cas où la référence mémoire du process est conservée après le premier appel.
    4. Récupérer l’identifiant du processus office :
    La méthode la plus définitive est de tuer le processus à la fin de l’automation.
    Il faut pour cela, dans un premier temps, récupérer l’identifiant du processus, et le stocker pendant tout le temps que doit durer l’automation. Exemple pour une automation Word :
    Code C# : 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
    int processId = 0;
    // 1. Additionner les identifiants des processus winword avant l’ouverture de l’automation :
    foreach (Process item in Process.GetProcessesByName("winword"))
        processId -= item.Id;
     
    // 2. Ouvrir l’automation :
    ApplicationClass monAppli = new ApplicationClass();
     
    // 3. Ajouter les identifiants des processus winword après l’ouverture de l’automation,
    // la différence (après - avant) donnera l’identifiant du processus ouvert :
    foreach (Process item in Process.GetProcessesByName("winword"))
        processId += item.Id;
     
    // Automation...
     
    // Enfin, lorsque l’automation est terminée, il suffit de tuer le processus à partir de son identifiant :
    Process.GetProcessById(processId).Kill();
    Ceci dit, tu peux déjà optimiser ton code en n'ouvrant Excel qu'une seule fois avant ta boucle (c'est ce que tu fais déjà) et fermant Excel qu'une seule fois après ta boucle. Ainsi, tu n'utilises qu'une seule instance de l'application, en ouvrant et fermant des classeurs.

  7. #7
    Membre actif Avatar de Yolak
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    341
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Vosges (Lorraine)

    Informations forums :
    Inscription : Mars 2007
    Messages : 341
    Points : 206
    Points
    206
    Par défaut
    Bonjour et merci pour toutes ces réponses.
    J'étais en train de tester la proposition de sebnantes mais j'éprouve encore quelques difficultés.
    Je regarde activement ça et je vous tiens au courant des avancements.
    En tout cas, merci pour votre aide!!!
    Épargnez votre cerveau : éteignez votre télé !

  8. #8
    Candidat au Club
    Inscrit en
    Octobre 2010
    Messages
    2
    Détails du profil
    Informations forums :
    Inscription : Octobre 2010
    Messages : 2
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Skalp Voir le message
    J'avais fait un message à ce sujet sur le forum Contribuer, mais il n'est plus visible car il va passer en FAQ très prochainement.
    Voilà tout de même le contenu qui devrait te permettre de résoudre ton problème :


    Ceci dit, tu peux déjà optimiser ton code en n'ouvrant Excel qu'une seule fois avant ta boucle (c'est ce que tu fais déjà) et fermant Excel qu'une seule fois après ta boucle. Ainsi, tu n'utilises qu'une seule instance de l'application, en ouvrant et fermant des classeurs.
    ------------

    En voyant cette partie de code je veux savoir si quelqu'un est capable d'aller lire en mémoire les données auxquelles sont ratachées au process ID ou je ne sait trop... Voici un exemple de code reflétant cela avec le process WINWORD:

    J'aimerais afficher le contenu de ce fichier dans un textbox mais je ne trouve pas la bonne syntaxe a utilser après une ébauche de toutes les propriétés disponibles du process.

    code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    Private Sub btnImporte_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnImporte.Click 
    Dim pro As Process = Process.GetCurrentProcess 
     
    Dim wordProes As Process() = Process.GetProcessesByName("WINWORD") 
     
    For Each pro In wordProes 
     
    txtImporte.Text = (pro.ProcessName & vbTab & pro.MainWindowTitle) 
    ''''Ici je voudrais trouver les données ratachés a ce process...
    Next 
     
    MessageBox.Show("Total Word document " & wordProes.Length) 
     
    End Sub
    Auriez-vous une suggestion ou un commentaire SVP?

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 058
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 058
    Points : 12 093
    Points
    12 093
    Par défaut
    Si c'est pour des documents Offices2007 et supérieurs, il y a beaucoup plus simple.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2007] Processus Excel persistant
    Par Beren69 dans le forum Excel
    Réponses: 1
    Dernier message: 10/03/2014, 18h02
  2. VBSCRIPT : Processus EXCEL persistant
    Par datastep dans le forum VBScript
    Réponses: 6
    Dernier message: 27/08/2010, 14h39
  3. Processus Excel persistant
    Par Mike619 dans le forum VBA Access
    Réponses: 8
    Dernier message: 12/03/2008, 10h15
  4. Réponses: 2
    Dernier message: 14/01/2008, 15h17

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