简体   繁体   English

C#-如何终止以编程方式在后台运行的Excel进程

[英]C# - how to kill excel process running in the background programmatically

I have a created a program to auto fill a invoice excel file so that it can be later printed. 我创建了一个程序来自动填充发票excel文件,以便以后可以打印。 I am able to fill the cells and format them. 我能够填充单元格并对其进行格式化。 But the excel process is still running in the background. 但是excel进程仍在后台运行。

public void Write(tbl_Sale sale,List<SalesModel> saleCollection)
{  
    Mouse.SetCursor(Cursors.Wait);
    Excel.Application application = null;
    Workbook workbook = null;
    Worksheet inputSheet = null;
    Range range = null;

    try
    {
        if (sale != null)
        {
            if (saleCollection.Count != 0)
            {
                application = new Excel.Application();
                FileInfo fileInfo = new FileInfo("Sample.xlsx");
                var sheet = "Invoice";
                workbook = application.Workbooks.Open(fileInfo.FullName);
                inputSheet = workbook.Worksheets.Cast<Worksheet>().Where(w => w.Name == sheet).FirstOrDefault(); 

                range = inputSheet.Cells;
                range.SetValue("G4", sale.Sale_ID);
                range.SetValue("G5", sale.Sale_Date);

                Range row = inputSheet.get_Range("A22", Missing.Value).EntireRow;

                for (int i = 0; i < saleCollection.Count; i++)
                {
                    row.Insert(XlInsertShiftDirection.xlShiftDown, row);
                    range = inputSheet.Cells;
                    range.SetValue("A" + (22 + i), i + 1);

                    range = inputSheet.Cells;
                    range.SetValue("B" + (22 + i), saleCollection[i].Product.Prod_Code);
                    range = inputSheet.Range["B" + (22 + i) + ":" + "D" + (22 + i)];
                    range.Merge();

                    range = inputSheet.Cells;
                    range.SetValue("E" + (22 + i), saleCollection[i].Product.Prod_Name);
                    range = inputSheet.Range["E" + (22 + i) + ":" + "K" + (22 + i)];
                    range.Merge();
                    range.HorizontalAlignment = 1;

                    range = inputSheet.Cells;
                    range.SetValue("X" + (22 + i), saleCollection[i].SalesDetail.SaleD_Quantity);
                    range = inputSheet.Range["X" + (22 + i) + ":" + "Y" + (22 + i)];                          
                    range.Merge();
                    range.HorizontalAlignment = 1;
                    range.NumberFormat = "0.00";

                    range = inputSheet.Cells;
                    range.SetValue("Z" + (22 + i), saleCollection[i].SalesDetail.SaleD_Rate);
                    range = inputSheet.Range["Z" + (22 + i) + ":" + "AA" + (22 + i)];
                    range.Merge();
                    range.HorizontalAlignment = 1;
                    range.NumberFormat = "0.00";

                    range = inputSheet.Cells;
                    range.SetValue("AB" + (22 + i), saleCollection[i].SalesDetail.SaleD_Amount);
                    range = inputSheet.Range["AB" + (22 + i) + ":" + "AD" + (22 + i)];
                    range.Merge();
                    range.HorizontalAlignment = 1; ;
                    range.NumberFormat = "0.00";
                }
                range = inputSheet.Cells;
                range.SetValue("X" + (22 + saleCollection.Count + 2), saleCollection.Sum(s => s.SalesDetail.SaleD_Quantity));
                range.SetValue("AB" + (22 + saleCollection.Count + 2), sale.Sale_Total);
                fileInfo = new FileInfo("Invoices\\" + sale.Sale_ID + ".xlsx");

                workbook.Application.DisplayAlerts = false;
                workbook.SaveAs(fileInfo.FullName, XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing, false, false, XlSaveAsAccessMode.xlNoChange, XlSaveConflictResolution.xlLocalSessionChanges ,Type.Missing, Type.Missing, Type.Missing, Type.Missing);

                releaseObject(row);
                MessageBox.Show("Invoice exported successfully", "Invoice Export", MessageBoxButton.OK, MessageBoxImage.Information);                      
               // Process.Start(fileInfo.FullName);
            }
        }
    }
    catch (Exception)
    {
        MessageBox.Show("Error while generating Excel report");
    }
    finally
    {
        workbook.Close(0);
        application.Quit();
        releaseObject(application);
        releaseObject(workbook);
        releaseObject(inputSheet);
        releaseObject(range);
        GC.Collect();
        Mouse.SetCursor(Cursors.Arrow);
    }
}

I am not able to kill the excel process from the background.I m not sure what I am doing wrong.The code above is the whole stuff I am doing for automating excel. 我无法从后台终止excel进程。我不确定自己在做什么错。上面的代码是我为使excel自动化所做的全部工作。 Kindly please help me. 请帮助我。

What I do is use an Initializer and a Deinitializer for the Excel objects, like so: 我要做的是为Excel对象使用初始化器和反初始化器,如下所示:

private void InitializeExcelObjects()
{
    _xlApp = new Excel.Application
    {
        SheetsInNewWorkbook = 2,
        StandardFont = "Tahoma",
        StandardFontSize = 11
    };

    _xlBook = _xlApp.Workbooks.Add(Type.Missing);
    _xlApp.Windows.Application.ActiveWindow.DisplayGridlines = false;

    _xlSheets = _xlBook.Worksheets;
    _xlSheet = (Excel.Worksheet)_xlSheets.Item[1];
    _xlSheetDelPerf = (Excel.Worksheet)_xlSheets.Item[2];
}

private void DeinitializeExcelObjects()
{
    Marshal.ReleaseComObject(_xlSheet);
    Marshal.ReleaseComObject(_xlSheetDelPerf);

    Marshal.ReleaseComObject(_xlSheets);

    _xlBook.Close(false, null, null); 
    Marshal.ReleaseComObject(_xlBook);

    _xlApp.DisplayAlerts = false;
    _xlApp.Quit();
    Marshal.ReleaseComObject(_xlApp);
    _xlApp = null;
}

They are called like this: 他们这样称呼:

public void GenerateDuckbilledPlatypusRpt()
{
    try
    {
        InitializeExcelObjects();
        . . . // all the Excel generation code goes here
    }
    finally
    {
        DeinitializeExcelObjects();
    }
}

IOW, I think you could change your code to something like this: IOW,我认为您可以将代码更改为以下形式:

public void Write(tbl_Sale sale,List<SalesModel> saleCollection)
{  
    Mouse.SetCursor(Cursors.Wait);
    Excel.Application application = null;
    Workbook workbook = null;
    Worksheet inputSheet = null;
    Range range = null;

    try
    {
        . . .
        InitializeExcelObjects();
        . . .
    }
    finally
    {
       DeinitializeExcelObjects();
       Mouse.SetCursor(Cursors.Arrow);
    }
}

private void InitializeExcelObjects()
{    
    application = new Excel.Application();

    workbook = application.Workbooks.Add(Type.Missing);

    sheets = workbook.Worksheets;
    inputSheet = (Excel.Worksheet)sheets.Item[1];
}

private void DeinitializeExcelObjects()
{
    Marshal.ReleaseComObject(inputSheet);

    Marshal.ReleaseComObject(sheets);

    workbook.Close(false, null, null); 
    Marshal.ReleaseComObject(workbook);

    application.DisplayAlerts = false;
    application.Quit();
    Marshal.ReleaseComObject(application);
    application = null;
}

It works for me; 这个对我有用; YMMV 因人而异

See this answer: How do I properly clean up Excel interop objects? 看到这个答案: 如何正确清理Excel互操作对象?

You are using releaseObject(application) , but that seems to refer to some method you have that is not shown. 您正在使用releaseObject(application) ,但这似乎是指您未显示的某些方法。 Not sure what code is doing there. 不知道在那里做什么代码。

Try using Marshal.ReleaseComObject(application) in addition to heeding the cautions in the linked question. 除了注意链接问题中的注意事项外,请尝试使用Marshal.ReleaseComObject(application)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM