使用C#格式化Excel文件

时间:2012-10-09 08:54:29

标签: c# excel interop

Bellow函数用于合成excel文件,但在运行该函数后,Application Excel没有从Try ..(无法杀死应用程序)中关闭请帮助我这个

private void FormateExcelFile()
{
    try
    {
        int nI = 0;//For Loop
        string nFieldName = string.Empty;
        nUserName=  WindowsIdentity.GetCurrent().Name; //Get Windows Login User
        string reportFilenPath = Application.StartupPath + "\\OutPutFiles\\" + "NewTempFile.xls";
        string connString = "provider=Microsoft.Jet.OLEDB.4.0;Data Source='" + reportFilenPath + "';Extended Properties=Excel 8.0;";
        DataTable parts = new DataTable();
        using (OleDbConnection conn = new OleDbConnection(connString))
        {
            string sqlParts = "Select * from [" + nSheetName + "]";
            OleDbDataAdapter adapter = new OleDbDataAdapter(sqlParts, conn);
            adapter.Fill(parts);
        }

        for (nI = 0; nI < parts.Columns.Count; nI++)
        {
            DataColumn column = parts.Columns[nI];
            if (nI == 0) { nFieldName = column.ColumnName; }
            else { nFieldName = nFieldName + "," + column.ColumnName; }
        }
        parts.Dispose(); parts = null;

        oExcel = new Excel.Application();
        oBook = oExcel.Workbooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
        oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oBook.Worksheets.get_Item(nSheetName.Replace("$", ""));
        oExcel.DisplayAlerts = false;
        oExcel.Visible = true;



        //Check the Field Is Avilable in the Sheet if not then Add
        if (nFieldName.Contains("Sub Device") == false)
        {
            nRng = oSheet.get_Range("A1", oMissing);
            nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
            oSheet.Cells[1, 1] = "Sub Device";
        }
        if (nFieldName.Contains("Brand") == false)
        {
            nRng = oSheet.get_Range("A1", oMissing);
            nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
            oSheet.Cells[1, 1] = "Brand";
        }
        if (nFieldName.Contains("Model") == false)
        {
            nRng = oSheet.get_Range("A1", oMissing);
            nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
            oSheet.Cells[1, 1] = "Model";
        }
        if (nFieldName.Contains("Product Details") == false)
        {
            nRng = oSheet.get_Range("A1", oMissing);
            nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
            oSheet.Cells[1, 1] = "Product Details";
        }
        if (nFieldName.Contains("Price") == false)
        {
            nRng = (Excel.Range)oSheet.Cells[1, 1];
            //nRng = oSheet.get_Range("A1", oMissing);
            nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
            oSheet.Cells[1, 1] = "Price";
        }

        oBook.Save();
        oBook.Close(false, oMissing, oMissing);
        oExcel.DisplayAlerts = true;
        releaseObject(oSheet);
        releaseObject(oBook);
        oExcel.Quit();
        releaseObject(oExcel);
        releaseObject(nRng);
        nRng = null;
        oExcel = null;
        oSheet = null;


    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
        releaseObject(oSheet);
        releaseObject(oBook);
        //oExcel.Quit();
        releaseObject(oExcel);
    }
}

private void releaseObject(object obj)
{
    try
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null;
    }
    catch (Exception ex)
    {
        obj = null;
        MessageBox.Show("Exception Occured while releasing object " + ex.ToString());
    }
    finally
    {
        GC.Collect();
    }
}

4 个答案:

答案 0 :(得分:1)

您需要发布所有您引用的Excel对象。例如:

if (nFieldName.Contains("Sub Device") == false)
{
    nRng = oSheet.get_Range("A1", oMissing);
    nRng.EntireColumn.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
    oSheet.Cells[1, 1] = "Sub Device";
}

应该是这样的(为了简单起见,省略了try / finally)

if (nFieldName.Contains("Sub Device") == false)
{
    nRng = oSheet.get_Range("A1", oMissing);
    var col = nRng.EntireColumn
    col.Insert(Microsoft.Office.Interop.Excel.XlInsertShiftDirection.xlShiftToRight, false);
    var cells = oSheet.Cells;
    var firstCell = cells[1,1];
    firstCell.Value = "Sub Device";

    Marshal.ReleaseComObject(nRng);
    Marshal.ReleaseComObject(col);
    Marshal.ReleaseComObject(cells);
    Marshal.ReleaseComObject(firstCell);

}

类似地:

oBook = oExcel.Workbooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false);
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oBook.Worksheets.get_Item(nSheetName.Replace("$", ""));

需要:

oBooks = oExcel.Workbooks
oBook = oBooks.Open(...);
oSheets = oBook.Worksheets
oSheet = oSHeets.get_Item(...);

你需要发布oBooks和oSheets。

答案 1 :(得分:0)

尝试使用以下命令结束您的Excel任务:

        Marshal.FinalReleaseComObject(sheet);
        app.DisplayAlerts = false; //Very important!
        range = null;
        sheet = null;
        // Garbage collecting
        GC.Collect();
        GC.WaitForPendingFinalizers();
        book.Close(false, Missing.Value, Missing.Value);
        Marshal.FinalReleaseComObject(book);
        book = null;
        app.Quit();
        Marshal.FinalReleaseComObject(app);
        app = null;

访问我的excel文件时遇到同样的问题,但是显示的代码会一直关闭。

当然,如果程序在到达代码之前崩溃,请使用调试器检查代码。

在您的情况下:书籍 - &gt; oBook,app - &gt; oExcel,sheet - &gt; oSheet。

答案 2 :(得分:0)

带走这些界限:

nRng = null;
oExcel = null;
oSheet = null;

我认为您正在发布您的Excel对象,然后通过使其等于null,之后您正在使用Excel在您的计算机上启动新实例。

释放对象后,您不需要将变量设置为null,或者运行GC.Collect();,垃圾收集器会为您处理这个问题,我想在这个例子中尝试清理托管对象本身(在正确清理非托管Excel对象之后)实际上是导致您的问题。

答案 3 :(得分:0)

我使用Excel互操作时遇到了同样的问题。问题应该来自这种界限(至少在我的情况下):

oBook = oExcel.Workbooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false); 

最后你会重新编写oBook,但这就是这里真正发生的事情:为了让oBook指向你打开的工作簿,你访问了一个Workbooks对象(使用oExcel.Workbooks)。这从未发布,并使Excel不会退出。

我通过将该行重写为:

解决了这个问题
Microsoft.Interop.Excel.Workbooks oBooks = oExcel.Workbooks;
oBook = oBooks.Open(reportFilenPath, 0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "", true, false, 0, true, false, false); 
releaseObject(oBooks);

当然,必须为此类的每一行(例如oBook.Worksheets.get_Item(...)nRng.EntireColumn.Insert(...)等)执行此操作。