Excel Processus de clôture en VB.net
Je suis entrain de créer un fichier excel à l'aide de l'interopérabilité.excel et le processus n'est pas de clôture.
C'est le code que j'suis en train d'utiliser.
Private Sub converToExcel(fileLoc As String, ds As DataSet)
Dim xlApp As Excel.Application
Dim xlWorkBook As Excel.Workbook
Dim xlWorkBooks As Excel.Workbooks
Dim xlWorkSheet As Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
Dim i As Integer
Dim j As Integer
xlApp = New Excel.Application
xlWorkBooks = xlApp.Workbooks
xlWorkBook = xlWorkBooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
For i = 0 To ds.Tables(0).Rows.Count - 1
For j = 0 To ds.Tables(0).Columns.Count - 1
xlWorkSheet.Columns.NumberFormat = "@"
xlWorkSheet.Cells(i + 1, j + 1) = String.Format("{0}", ds.Tables(0).Rows(i).Item(j).ToString())
Next
Next
xlWorkSheet.SaveAs(fileLoc)
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlWorkSheet)
releaseObject(xlWorkBook)
releaseObject(xlWorkBooks)
releaseObject(xlApp)
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
Je pense que je vais rater un objet COM, mais ne peux pas l'air de trouver une solution.
Également comme une note, c'est en cours d'exécution sur une version 64 bits de Windows 8.
Toute aide serait super!
Grâce
Et vous êtes sûr que ce n'est pas une instance de gauche de précédents tests?
oui, j'ai vérifier le Gestionnaire des Tâches après chaque test et supprimer toutes les instances d'excel.
Je ne pense pas que ce soit la cause de votre problème, mais
Changé releaseObject à byref au lieu de byval, même résultat.
L'ajout de xlWorkbooks.Fermer supprimer le processus? Si non, je dirais pas à pas dans le code, de voir lorsque les processus sont en cours de création, puis la détermination de ce qui est retiré vers la fin de votre Sous.
oui, j'ai vérifier le Gestionnaire des Tâches après chaque test et supprimer toutes les instances d'excel.
Je ne pense pas que ce soit la cause de votre problème, mais
releaseObject
ne peut pas faire tout ce que vous pensez que cela fonctionne. Puisque vous êtes de passage obj
ByVal
, le obj = Nothing
n'a aucun effet sur la xlWorkSheet
, xlWorkBook
etc. les variables.Changé releaseObject à byref au lieu de byval, même résultat.
L'ajout de xlWorkbooks.Fermer supprimer le processus? Si non, je dirais pas à pas dans le code, de voir lorsque les processus sont en cours de création, puis la détermination de ce qui est retiré vers la fin de votre Sous.
OriginalL'auteur jmcsmith | 2013-01-08
Vous devez vous connecter pour publier un commentaire.
Manuel de gestion de la mémoire comme cela juste ne fonctionne jamais. C'est un problème qui est connu depuis très longtemps et le coeur, et la raison que les ramasseurs d'ordures ont été inventés. Les programmeurs juste jamais oublier de libérer la mémoire.
Il devient très difficile lorsque vous ne pouvez pas voir la mémoire utilisée. Ce qui est certainement le cas dans votre code, le
xlWorkSheet.Cells(i + 1, j + 1)
expression utilise pas moins de trois références. L'un pour la gamme de l'objet retourné par la propriété Cellules, une pour un sous-objet de la plage sélectionnée pari+1
et un autre pour le sous-objet de la plage sélectionnée parj+1
. Très belle syntaxe de sucre fourni par le VB.NET la langue, l'écriture de code COM sans elle, c'est joli nom de dieu douloureux. Mais pas utile pour vous permettre de voir les références. Non seulement pouvez-vous pas voir dans votre code source, il n'y a absolument rien, le débogueur peut faire pour vous aider à les voir.C'est bien un problème résolu .NET, il a un garbage collector et il peut voir tout. Le problème principal, c'est que vous ne lui donnez pas une chance de résoudre votre problème. L'erreur que vous faites, c'est que vous arrêté. Probablement en définissant un point d'arrêt sur la dernière déclaration, et puis en regardant dans le Gestionnaire des Tâches et de voir Excel.exe toujours en cours d'exécution. Oui, c'est normal. La collecte des ordures n'est pas instant.
L'appel de GC.Collect() est censé rendre instantané, mais qui ne fonctionne pas dans le cas précis de l'exécution de la version de Débogage de votre projet. La durée de vie des variables locales obtient ensuite étendu à la fin de la méthode, vous aider à les voir dans les Autos/Habitants/Watch fenêtre. En d'autres termes, GC.Collect() ne fait pas de recueillir tout de l'interface de références. Plus sur que le comportement dans ce post.
La solution simple est de pas arrêter. Continuer à faire des choses utiles pour donner le garbage collector une raison de courir. Ou de laisser votre programme de résilier puisqu'il est fait, Excel se termine lorsque le finaliseur thread s'exécute pour la dernière fois. Qui fonctionne parce que les variables locales qui avaient les références ne sont pas dans le champ d'application est plus.
Mais tout le monde veut la correction instantanée de toute façon. Vous l'obtenez par la suppression de tous les releaseObject() appelle. Et de le faire comme ceci à la place:
Ou en d'autres termes, la force d'une collection après la méthode est de retour. Les variables locales ne sont plus dans le champ d'application de sorte qu'ils ne peuvent pas tenir sur une feuille de référence. Il sera désormais également le travail quand vous le débogage, comme il l'a déjà fait lors de l'exécution de la Libération construire sans un débogueur.
C'est assez répandue illusions. Commune lors de l'arbitraire d'un petit changement a de gros effets secondaires, ce qui rend d'autant ressembler à de la magie noire. Ces "nombreux cas documentés" bien sûr besoin d'une citation. Voici la mienne: blogs.msdn.com/b/visualstudio/archive/2010/03/01/...
Désolé, ne peut pas trouver de rapide recherche sur google, mais quand j'ai fait des recherches à ce sujet il y a quelques années il y avait beaucoup de l'utilisateur de rapports de l'office de clôture avec la gestion des modules complémentaires (cause la plus courante était de s'abonner à des événements), ou même de quelques (très rares) se bloque à cause d'GC libérant les références à la fois office ne pouvait pas traiter avec. Tous probablement corrigé dans les versions d'office (et .NET 4 aide à l'événement de l'abonnement), de sorte que si vous devez être rétro-compatible. Il y avait aussi quelques articles de base de connaissances Microsoft à ce sujet, mais ils sont très difficiles à trouver.
Vous êtes à la droite (avec votre posté le lien) que ReleaseComObject cause des problèmes une fois que l'office commence à mettre en œuvre leurs interfaces .NET, mais le lien est faux dans cet “objet COM qui a été séparé de son RCW sous-jacent ne peut pas être utilisé” est un problème. Si vous obtenez ce que vous n'avez votre comptage de référence de mal (n'a pas augmenté le BRF refcount lorsque vous divisez la propriété de la référence à plusieurs propriétaires). Si vous n'manuel de comptage de référence, alors vous devez aller tout le chemin et de le faire correctement.
Et ne vous méprenez pas, vous avez absolument raison, être compatible GC est l'avenir. Devrait ne vous embêtez pas avec ReleaseComObject quand ils sont forcés à être compatible avec les anciens trucs comme Bureau 2000-2003 et/ou .NET 2 - et comme je l'ai dit dans ma réponse, je pense que ce n'est pas le cas pour cette question, il ne serait pas dans les problèmes de nécessitant ReleaseComObject
OriginalL'auteur Hans Passant
Essayez Système.Moment de l'exécution.InteropServices.Maréchal.FinalReleaseComObject, qui devrait l'aider à... en outre, vous devriez appeler xlWorkBook.Close() et xlapp.cesser de fumer, si je me souviens bien. D'abord les appeler et de les définir à rien.
Je pense que vous commandez est le problème avec les quitter: je pense que vous devez définir la seehts à rien, puis quittez le classeur puis définissez-la sur rien, alors " l'application et de le quitter. Mais à la poursuite de l'Investigatio j'ai vu que vous appelez gc recueillir une seule fois - de l'appeler deux fois. Si non, les objets sont marqués pour la libération, mais ne sont pas libérés.
OriginalL'auteur Christian Sauer
La GC.Recueillir fait pas beaucoup de sens où vous l'avez placé, si quelque chose vous devriez l'appeler après le retour à la de
converToExcel
. Aussi, vous pouvez avoir besoin d'attendre pour les finaliseurs à exécuter. Personnellement, je pense que Hans réponse est le chemin à parcourir, mais je sais par expérience personnelle, l'écriture office addins en C# qu'il est parfois nécessaire de le faire en manuel de comptage de référence, en particulier lorsque vous avez besoin pour être compatible avec les anciennes versions d'office. (Il y a beaucoup de problèmes documentés, en particulier lors de la manipulation des événements à partir d'office, qui ne peut être résolu de manière fiable par le manuel de comptage de référence. Aussi certaines bibliothèques COM n'aime pas du tout lorsqu'il est libéré dans le mauvais ordre par GC, mais ce n'est pas le cas avec le bureau.)Donc le problème dans ton code: il y a trois intermédiaires objets COM pas publié ici:
xlWorkBook.Sheets
retourne une collection de typeExcel.Sheets
xlWorkSheet.Columns
retourne un objet COM de typeExcel.Range
xlWorkSheet.Cells
renvoie aussi unExcel.Range
objetEn outre, si le Maréchal.ReleaseComObject déclenche une exception que vous avez fait quelque chose de mal dans votre manuel de comptage de référence, donc je ne serait pas l'envelopper dans un gestionnaire d'exception. Quand manuel de comptage de référence, vous devez relâcher chaque objet COM une fois pour chaque fois qu'il traverse la COM->NET frontière, ce qui signifie la
Excel.Range
objets doivent être libérés à chaque itération de la boucle.Voici le code qui se termine Excel pour moi:
Si vous voulez être très prudent que vous souhaitez pour gérer les exceptions de l'office de l'API et de l'appel ReleaseComObject à l'intérieur, enfin,-les clauses. Il peut être utile de définir un wrapper générique et écrire à l'aide de clauses relatives au lieu d'essayer, enfin, de faire le wrapper une structure de classe afin de ne pas affecter les wrappers sur le tas).
OriginalL'auteur Zarat
Enfin résolu 🙂
utiliser cette méthode
Cette méthode ferme spécifiquement processus ouvert.
OriginalL'auteur Xtian11
OriginalL'auteur Gretchen
Je n'ai vu personne de traiter correctement ce qui était produisent et au lieu de cela, essayé de créer des solutions pour les.
Ce qui se passe ici est que le classeur est invitant, dans le fond, pour être sauvés. Dans votre code, vous enregistrez la feuille de calcul et non le classeur. Vous pouvez soit le tromper et de définir l'état enregistré le classeur à true ou à enregistrer le classeur avant de sortir de l'application excel.
J'ai été aussi avoir ce problème. Le processus Excel irait à l'ensemble de fois que l'application est ouverte. En ajoutant le xlWorkBook.Saved = True ligne, le processus prendrait fin après l'appel à xlApp.Quit(). Dans mon cas, je n'ai pas besoin d'enregistrer le fichier excel, la seule référence pour les valeurs.
Option #1 - Ne pas enregistrer le classeur:
Option #2 - Enregistrez le classeur dans un nouveau fichier:
Option #3 - Enregistrer le classeur dans un fichier existant:
.Quit() Méthode:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel._application.quit?view=excel-pia#Microsoft_Office_Interop_Excel__Application_Quit
.Enregistré() Méthode:
https://docs.microsoft.com/en-us/dotnet/api/microsoft.office.interop.excel._workbook.saved?view=excel-pia#Microsoft_Office_Interop_Excel__Workbook_Saved
OriginalL'auteur TinMan464
Parfois, il ne nettoie pas le processus Excel et pendant que la génération d'excel à plusieurs reprises,il crée plus de 1 excel processus qui devait ralentir le processus ainsi que le système.Tel est le problème que j'utilisais et cette solution a bien fonctionné dans mon cas 🙂
Il peut avoir travaillé dans votre propre cas, mais il n'est pas utile à la proposer comme solution sans en expliquer les conséquences. Par exemple, il tuerait aucun Excel processus, y compris ceux dont l'utilisateur a ouvert. La plupart des gens ne veulent pas installer un programme juste pour savoir, il va tuer leurs instances d'Excel tout simplement parce que le programmeur ne pouvais pas penser à un moyen propre à interagir avec Excel.
Merci @Zarat pour les précieuses informations,en Fait nous n'avons jamais pensé à un tel scénario,alors maintenant nous avons besoin de changer ces ligne de nouveau.Merci
OriginalL'auteur Shivachandra