2017-07-11 4 views
-1

J'ai créé un complément Excel qui traite la feuille active et ouvre une autre application Excel et écrit dans une autre feuille. Je ne veux pas fermer Excel quand le programme est fait car ce serait à l'utilisateur. Quand mon programme s'exécute, je peux voir EXCEL.exe dans le gestionnaire de tâches et quand c'est fait, je le vois toujours, ce qui est ce que je m'attends et quand je ferme EXCEL, ça s'en va, mais je ne sais toujours pas si je devrait appeler ReleaseComObject et sur quelles variables l'appeler et quand. Voici mon code actuel:Comment nettoyer les objets COM pour un complément Excel qui crée un autre fichier Excel?

public class ProcessExcel { 
Worksheet activeSheet; 

ProcessExcel_Click(object sender, EventArgs e) 
{ 
    //Do I need to break these into variables and/or do I need to dispose of them? 
    var addIn = Globals.ThisAddIn; 
    var application = addIn.Application; 
    var workbook = application.ActiveWorkbook; 

activeSheet = workbook.ActiveSheet; 

    var processor= new Processor(activeSheet, _bank); 

      var processedCells = processor.Process(); 

      CreateExcelFile(); 

      GenerateOutput(processor, processedCells); 
} 

    private void CreateExcelFile() 
     { 

      var xlApp = new Microsoft.Office.Interop.Excel.Application(); 


      if (xlApp == null) 
      { 
       MessageBox.Show("EXCEL could not be started"); 
       return; 
      } 

      xlApp.Visible = true; 

      var workbooks = xlApp.Workbooks; 

      var wb = workbooks.Add(); 
      xlApp.DefaultSaveFormat = xlFileFormat; 

      var worksheets = wb.Worksheets; 

      activeSheet = worksheets.Add(); 
      activeSheet.Name = "Output"; 


      if (activeSheet == null) 
      { 
       MessageBox.Show("Worksheet could not be created"); 
       return; 
      } 

      var outputSheetColumns = activeSheet.Columns; 

      foreach (var item in data.Columns) 
      { 
       if (item.TargetDataType != null) 
       { 
        if (item.TargetDataType.ToLower() == DataType.Text.ToLower()) 
        { 
         outputSheetColumns[item.TargetColumnNumber].Numberformat = NumberFormat.Text; 
        } 
       } 

      } 


     } 

    private void GenerateOutput(Processor processor, ProcessedCells processedCells) 
    { 
     var cells = activeSheet.Cells; 

     if (data.IncludeHeader) 
     { 
      processor.SetHeaders(activeSheet); 
     } 

     foreach (var cell in processedCells.ValidCells) 
     { 
      var currentCell = cells[cell.RowNumber, cell.ColumnNumber]; 
      currentCell.Value2 = cell.Value; 
     } 
    } 
} 

Comme vous pouvez le voir ci-dessus, je suis en train du matin (je pense) en utilisant des variables pour tous les objets com et en évitant deux points. Je n'ai la méthode suivante pour le nettoyage, mais pas sûr sur les objets à utiliser et quand:

private void releaseObject(object obj) 
    { 
     try 
     { 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); 
      obj = null; 
     } 
     catch (Exception ex) 
     { 
      obj = null; 
      MessageBox.Show("Unable to release the Object " + ex.ToString()); 
     } 
     finally 
     { 
      GC.Collect(); 
     } 
    } 

j'ai vu que ReleaseComObject peut-être pas nécessaire et je peux appeler:

 GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 

Si la l'utilisateur est responsable de la fermeture de l'application Excel, est-ce nécessaire ci-dessus?

Répondre

0

Unfortunatly une mauvaise solution qui fonctionne est de tuer le processus

System.Diagnostics.Process pro = ExcelProcess.GetExcelProcess(ExcelApp); 
pro.Kill(); 

[DllImport("user32.dll")] 
static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); 

public static System.Diagnostics.Process GetExcelProcess(oExcel.Application excelApp) 
{ 
    int id; 
    GetWindowThreadProcessId(excelApp.Hwnd, out id); 
    return System.Diagnostics.Process.GetProcessById(id); 
} 
+0

Dans mon cas, quand mon application se termine, je veux exceller à courir parce que je veux que l'utilisateur pour la fermer. J'étais curieux de savoir si je dois encore gérer la libération de la mémoire si je garde Excel ouvert – xaisoft

+0

Ce code attrape l'ID de processus que votre processus C# code Excel utilise. Il tue ce processus. Vous pouvez appeler beaucoup de processus Excel pour faire n'importe quoi. Cela va seulement tuer le processus qui est attaché à l'objet ExcelApp. –

+0

Mais je veux l'application Excel que mon code C# utilise pour rester ouvert. – xaisoft

0

Utilisez les fonctions intégrées dans le Interop pour quitter l'objet Workbook.

using Excel = Microsoft.Office.Interop.Excel; // skip a lot of redundant typing 

// declare application/workbook/worksheet objects 
Excel.Application applicationObject = new Excel.Application(); 
Excel.Workbook workbookObject; 
Excel.Worksheet worksheetObject; 


workbookObject = applicationObject.Open(/* lot of parameters go here */); 
worksheetObject = workbookObject.Sheets["SheetName"]; 
DoThings(worksheetObject); 

// finished working with sheet, time to close it 
workbookObject.SaveAs(/* necessary parameters */); 
workbookObject.Close(/* necessary parameters */); 

Une fois que vous appelez la méthode Workbook.Close(), il mettra fin au processus que vous avez créé en ouvrant