teclado recorrer office nueva microsoft insertar hoja formato example escribir desde datos dar crear con archivo c# excel com interop pia

recorrer - microsoft.office.interop.excel c# example



Interoperabilidad de C#: el proceso de Excel no sale después de agregar una nueva hoja de trabajo al archivo existente (7)

Posible duplicado:
Cómo limpiar adecuadamente los objetos de interoperabilidad de Excel en C #

He leído muchos de los otros hilos aquí sobre la administración de referencias COM mientras uso la interoperabilidad .Net-Excel para asegurarme de que el proceso de Excel sale correctamente al salir, y hasta ahora las técnicas han estado funcionando muy bien, pero recientemente encontré una problema al agregar nuevas hojas de trabajo a un archivo de libro de trabajo existente.

El siguiente código deja un proceso zombie de Excel.

Si agrego una hoja de trabajo a un archivo de libro de trabajo recién creado, sale bien. Si ejecuto el código excluyendo la línea .Add() , sale bien. (El archivo existente del que estoy leyendo es un archivo vacío creado por el código comentado)

¿Algunas ideas?

//using Excel = Microsoft.Office.Interop.Excel; //using System.Runtime.InteropServices; public static void AddTest() { string filename = @"C:/addtest.xls"; object m = Type.Missing; Excel.Application excelapp = new Excel.Application(); if (excelapp == null) throw new Exception("Can''t start Excel"); Excel.Workbooks wbs = excelapp.Workbooks; //if I create a new file and then add a worksheet, //it will exit normally (i.e. if you uncomment the next two lines //and comment out the .Open() line below): //Excel.Workbook wb = wbs.Add(Excel.XlWBATemplate.xlWBATWorksheet); //wb.SaveAs(filename, m, m, m, m, m, // Excel.XlSaveAsAccessMode.xlExclusive, // m, m, m, m, m); //but if I open an existing file and add a worksheet, //it won''t exit (leaves zombie excel processes) Excel.Workbook wb = wbs.Open(filename, m, m, m, m, m, m, Excel.XlPlatform.xlWindows, m, m, m, m, m, m, m); Excel.Sheets sheets = wb.Worksheets; //This is the offending line: Excel.Worksheet wsnew = sheets.Add(m, m, m, m) as Excel.Worksheet; //N.B. it doesn''t help if I try specifying the parameters in Add() above wb.Save(); wb.Close(m, m, m); //overkill to do GC so many times, but shows that doesn''t fix it GC(); //cleanup COM references //changing these all to FinalReleaseComObject doesn''t help either while (Marshal.ReleaseComObject(wsnew) > 0) { } wsnew = null; while (Marshal.ReleaseComObject(sheets) > 0) { } sheets = null; while (Marshal.ReleaseComObject(wb) > 0) { } wb = null; while (Marshal.ReleaseComObject(wbs) > 0) { } wbs = null; GC(); excelapp.Quit(); while (Marshal.ReleaseComObject(excelapp) > 0) { } excelapp = null; GC(); } public static void GC() { System.GC.Collect(); System.GC.WaitForPendingFinalizers(); System.GC.Collect(); System.GC.WaitForPendingFinalizers(); }


No es muy constructivo, lo sé, pero probé el código exactamente como se muestra arriba y mi proceso de Excel sale como se esperaba, mi C: / addtest.xls está instalada con 8 hojas nuevas y no se está ejecutando ningún proceso de Excel.
¿Podría ser la causa de la versión de interoperabilidad? Probé con 11 y 12.


He hecho algo similar. Creo un archivo de Excel o abro un existente. Borro todas las hojas y agrego las mías. aquí está el código que uso para asegurar que todas las referencias estén cerradas:

workbook.Close(true, null, null); excelApp.Quit(); if (newSheet != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(newSheet); } if (rangeSelection != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(rangeSelection); } if (sheets != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets); } if (workbook != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook); } if (excelApp != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp); } newSheet = null; rangeSelection = null; sheets = null; workbook = null; excelApp = null; GC.Collect();

He probado esto con muchas opciones diferentes y aún no me ha fallado.


No tengo el código a mano, pero me encontré con un problema similar. Si recuerdo correctamente, terminé recuperando el id. De proceso de la instancia de excel y matándolo (después de un período de espera adecuado, y cuando el otro método falló).

Creo que utilicé:

GetWindowThreadProcessId (a través de P / Invoke) en la propiedad del objeto excel hwnd para obtener la identificación del proceso, y luego usó Process.GetProcessById para obtener un objeto de proceso. Una vez que hubiera hecho eso, llamaría a Kill en el proceso.

EDITAR: Tengo que admitir que esta no es la solución ideal, pero si no puedes encontrar la interfaz deshonesta que no se está lanzando, entonces esto lo arreglará con la verdadera moda de cáscara de huevo / almádena. ;)

EDIT2: No tiene que llamar a Kill en el objeto de proceso de inmediato ... Primero puede intentar llamar a Close antes de recurrir a Kill .


Estoy usando VB.NET 3.5 SP1 y el siguiente código STILL deja EXCEL.EXE abierto:

xlWorkbook.Close(SaveChanges:=False) xlApplication.Quit() System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorksheet) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbook) System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApplication) xlRange = Nothing xlWorksheet = Nothing xlSheets = Nothing xlWorkbook = Nothing xlApplication = Nothing GC.GetTotalMemory(False) GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() GC.GetTotalMemory(True)


Andrew, aquí está el código que encontré que funciona. Pensé en publicarlo aquí para otros que se encuentran:

namespace WindowHandler { using System; using System.Text; using System.Collections; using System.Runtime.InteropServices; /// <summary> /// Window class for handling window stuff. /// This is really a hack and taken from Code Project and mutilated to this small thing. /// </summary> public class Window { /// <summary> /// Win32 API import for getting the process Id. /// The out param is the param we are after. I have no idea what the return value is. /// </summary> [DllImport("user32.dll")] private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr ProcessId); /// <summary> /// Gets a Window''s process Id. /// </summary> /// <param name="hWnd">Handle Id.</param> /// <returns>ID of the process.</returns> public static IntPtr GetWindowThreadProcessId(IntPtr hWnd) { IntPtr processId; IntPtr returnResult = GetWindowThreadProcessId(hWnd, out processId); return processId; } } }


aquí está mi código completo para matar el Excel que creó con la biblioteca de interoperabilidad .Net de Office12: Enjoy, -Alan.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; using Microsoft.Office.Interop.Excel; class Program { /// <summary> /// Win32 API import for getting the process Id. /// The out param is the param we are after. I have no idea what the return value is. /// </summary> [DllImport("user32.dll")] private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr ProcessId); static void Main(string[] args) { var app = new Application(); IntPtr hwnd = new IntPtr(app.Hwnd); IntPtr processId; IntPtr foo = GetWindowThreadProcessId(hwnd, out processId); Process proc = Process.GetProcessById(processId.ToInt32()); proc.Kill(); // set breakpoint here and watch the Windows Task Manager kill this exact EXCEL.EXE app.Quit(); // should give you a "Sorry, I can''t find this Excel session since you killed it" Exception. } }


Esto funciona muy bien para mí, sin excepciones.

Public Class ExcelHlpr Declare Function EndTask Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal ShutDown As Boolean, ByVal Force As Boolean) As Integer Dim cXlApp As Microsoft.Office.Interop.Excel.Application Public Function GetExcel() As Microsoft.Office.Interop.Excel.Application cXlApp = New Microsoft.Office.Interop.Excel.Application Return cXlApp End Function Public Function EndExcel() As Integer Dim xlHwnd As New IntPtr(cXlApp.Hwnd) Return EndTask(xlHwnd, False, True) End Function End Class