Link to home
Start Free TrialLog in
Avatar of rwheeler23
rwheeler23Flag for United States of America

asked on

C# application spawning phantom Excel sessions

I have a C# application that creates and populates an Excel spreadsheet.

1) Create spreadsheet
2) Populate spreadsheet
3) Save spreadsheet
4) Open spreadsheet

The problem I have is after the user closes the spreadsheet there is a phantom spreadsheet session open. Here is how I am saving the spreadsheet. Is there something I need to add here or perhaps in the code that opens the spreadsheet?

        public static Boolean SaveExcelSpreadsheet()
        {
            /* Save the excel file */
            Model.xlWorkBook.SaveAs(Model.excelFullOutputFile, Excel.XlFileFormat.xlOpenXMLWorkbook, Model.misValue, Model.misValue, Model.misValue, Model.misValue, Excel.XlSaveAsAccessMode.xlExclusive, Model.misValue, Model.misValue, Model.misValue, Model.misValue, Model.misValue);
            Model.xlWorkBook.Close(true, Model.misValue, Model.misValue);
            Model.xlApp.UserControl = true;
            Model.xlApp.Quit();

            Marshal.ReleaseComObject(Model.xlWorkSheetDetail);
            Marshal.ReleaseComObject(Model.xlWorkSheetDist);
            Marshal.ReleaseComObject(Model.xlWorkBook);
            Marshal.ReleaseComObject(Model.xlApp);

            MessageBox.Show("Excel file created , you can find the file " + Model.excelFullOutputFile);

            return (true);
        }
Avatar of David Johnson, CD
David Johnson, CD
Flag of Canada image

1) Create spreadsheet
2) Populate spreadsheet
3) Save spreadsheet
close excel
4) Open spreadsheet
1) Create spreadsheet
2) Populate spreadsheet
3) Save spreadsheet

Open in new window


Are these steps happening in memory or in a physical instance of an Excel spreadsheet?
Avatar of rwheeler23

ASKER

My code is doing it all. After the spreadsheet is opened and the user uses Excel to close it, the user can no longer open the spreadsheet. They will get a message about the spreadsheet already being in use. Everytime the execute the code an additional phantom session is created.  Do I need to do some garbage collecting?
You'd might have a handle to the spreadsheet open in the code which locks the file in the system from read/write access by others, close it after saving the spreadsheet (as David suggested) and then try opening the document.
This is .Net 4.5.1
I thought I was already closing Excel with my code. What do I need to add?
I cannot help you without seeing the rest of the steps snippet, this will allow us to further diagnose your bug. All we've seen is the Save routine, but it looks fine the way it is. I can see you're calling Close and then Quit on the Excel Application object, so It's hard to examine the problem by only reading this routine.
ASKER CERTIFIED SOLUTION
Avatar of ste5an
ste5an
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I did add garbage collection to the Save method.

        public static Boolean SaveExcelSpreadsheet()
        {
            /* Save the excel file */
            Model.xlWorkBook.SaveAs(Model.excelFullOutputFile, Excel.XlFileFormat.xlOpenXMLWorkbook, Model.misValue, Model.misValue, Model.misValue, Model.misValue, Excel.XlSaveAsAccessMode.xlExclusive, Model.misValue, Model.misValue, Model.misValue, Model.misValue, Model.misValue);
            Model.xlWorkBook.Close(true, Model.misValue, Model.misValue);
            Model.xlApp.UserControl = true;
            Model.xlApp.Quit();
            GC.Collect();

            /*
            Marshal.FinalReleaseComObject(Model.xlWorkSheetDetail);
            Marshal.FinalReleaseComObject(Model.xlWorkSheetDist);
            Marshal.FinalReleaseComObject(Model.xlWorkBook);
            Marshal.FinalReleaseComObject(Model.xlApp); */

            Marshal.ReleaseComObject(Model.xlWorkSheetDetail);
            Marshal.ReleaseComObject(Model.xlWorkSheetDist);
            Marshal.ReleaseComObject(Model.xlWorkBook);
            Marshal.ReleaseComObject(Model.xlApp);

            MessageBox.Show("Excel file created , you can find the file " + Model.excelFullOutputFile);

            return (true);
        }

----------------------------------------------------------------------------------------------------------------------------------------
This is how I open the spreadsheet. The open is at the bottom.
----------------------------------------------------------------------------------------------------------------------------------------
        private void btnExcel_Click(object sender, EventArgs e)
        {
            int row;
            /* Create the spreadsheet with column headings only in both worksheets */
            Utilities.CreateExcelSpreadsheet();

            a couple of sql statements that populate two worksheets with the workbook.
                    using (SqlDataReader sdr = cmd.ExecuteReader())
                    {
                        /* Create a new DataTable */
                        DataTable dtPayrollDetailTrx = new DataTable("dtPayrollDetailTrx");

                        /* Load DataReader into the DataTable */
                        dtPayrollDetailTrx.Load(sdr);

                        foreach (DataRow dtrow in dtPayrollDetailTrx.Rows)
                        {
                            row += 1;

                            Model.xlWorkSheetDetail.Cells[row, 1] = dtrow["Trx_Type"].ToString();
                            Model.xlWorkSheetDetail.Cells[row, 2] = dtrow["Trx_Date"].ToString();
                            Model.xlWorkSheetDetail.Cells[row, 3] = dtrow["ChkNbr"].ToString();
                            Model.xlWorkSheetDetail.Cells[row, 4] = dtrow["EENbr"].ToString();
                            Model.xlWorkSheetDetail.Cells[row, 5] = dtrow["RecordID_DistributionRef"].ToString();
                            Model.xlWorkSheetDetail.Cells[row, 6] = System.Math.Abs(Convert.ToDouble(string.IsNullOrWhiteSpace(dtrow["Doc_Amount"].ToString()) ? 0.00 : Convert.ToDouble(dtrow["Doc_Amount"].ToString())));
                        }
                    }
                    using (SqlDataReader sdr = cmd.ExecuteReader())
                    {
                        /* Create a new DataTable */
                        DataTable dtPayrollDistTrx = new DataTable("dtPayrollDistTrx");

                        /* Load DataReader into the DataTable */
                        dtPayrollDistTrx.Load(sdr);

                        foreach (DataRow dtrow in dtPayrollDistTrx.Rows)
                        {
                            row += 1;

                            Model.xlWorkSheetDist.Cells[row, 1] = dtrow["Trx_Type"].ToString();
                            Model.xlWorkSheetDist.Cells[row, 2] = dtrow["Trx_Date"].ToString();
                            Model.xlWorkSheetDist.Cells[row, 3] = dtrow["ChkNbr"].ToString();
                            Model.xlWorkSheetDist.Cells[row, 4] = dtrow["EENbr"].ToString();
                            Model.xlWorkSheetDist.Cells[row, 5] = dtrow["RecordID_DistributionRef"].ToString();
                            Model.xlWorkSheetDist.Cells[row, 6] = dtrow["ACTDESCR"].ToString();
                            Model.xlWorkSheetDist.Cells[row, 7] = dtrow["Full_GL_Account"].ToString();
                            Model.xlWorkSheetDist.Cells[row, 8] = System.Math.Abs(Convert.ToDouble(string.IsNullOrWhiteSpace(dtrow["Debit_Amount"].ToString()) ? 0.00 : Convert.ToDouble(dtrow["Debit_Amount"].ToString())));    
                            Model.xlWorkSheetDist.Cells[row, 9] = System.Math.Abs(Convert.ToDouble(string.IsNullOrWhiteSpace(dtrow["Credit_Amount"].ToString()) ? 0.00 : Convert.ToDouble(dtrow["Credit_Amount"].ToString())));
                        }
                    }

            Utilities.SaveExcelSpreadsheet();                                                   /* Save the spreadsheet */

            var excelApp = new Excel.Application();
            excelApp.Visible = true;
            MessageBox.Show("The filename is : " + Model.excelFullOutputFile);
            excelApp.Workbooks.Open(Model.excelFullOutputFile);
}
--------------------------------------------------------------------------------------------------------------------
The spreadsheet is created with this
--------------------------------------------------------------------------------------------------------------------
        public static Boolean CreateExcelSpreadsheet()
        {
            object misValue = System.Reflection.Missing.Value;

            /* Initialize the Excel application object */
            Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();

            /* Check whether Excel is installed */
            if (xlApp == null)
            {
                MessageBox.Show("Excel is not properly installed! Please install Excel or attempt a repair.");
                return (false);
            }

            xlApp.Visible = false;

            /* Create the new workbook */
            Excel.Workbook xlWorkBook = xlApp.Workbooks.Add(misValue);
            /* Create and populate columns headings for distribution worksheet */
            Excel.Worksheet xlWorkSheetDist = xlWorkBook.ActiveSheet  as Excel.Worksheet;
            xlWorkSheetDist.Name = "Distributions";
            xlWorkSheetDist.Cells[1, 1] = "Transaction Type";
            xlWorkSheetDist.Cells[1, 2] = "Transaction Date";
            xlWorkSheetDist.Cells[1, 3] = "Chk Nbr/Bldg";
            xlWorkSheetDist.Cells[1, 4] = "EE Nbr/Dept";
            xlWorkSheetDist.Cells[1, 5] = "Record ID";
            xlWorkSheetDist.Cells[1, 6] = "Acct Description";
            xlWorkSheetDist.Cells[1, 7] = "GL Account";
            xlWorkSheetDist.Cells[1, 8] = "Debit Amount";
            xlWorkSheetDist.Cells[1, 9] = "Credit Amount";

            /* Create and populate columns headings for detail worksheet */
            Excel.Worksheet xlWorkSheetDetail = xlWorkBook.Sheets.Add(misValue, misValue, 1, misValue) as Excel.Worksheet;
            xlWorkSheetDetail.Name = "Detail";
            xlWorkSheetDetail.Cells[1, 1] = "Transaction Type";
            xlWorkSheetDetail.Cells[1, 2] = "Transaction Date";
            xlWorkSheetDetail.Cells[1, 3] = "Chk Nbr/Bldg";
            xlWorkSheetDetail.Cells[1, 4] = "EE Nbr/Dept";
            xlWorkSheetDetail.Cells[1, 5] = "Record ID";
            xlWorkSheetDetail.Cells[1, 6] = "Doc Amount";

            Model.xlApp = xlApp;
            Model.xlWorkBook = xlWorkBook;
            Model.xlWorkSheetDetail = xlWorkSheetDetail;
            Model.xlWorkSheetDist = xlWorkSheetDist;
            Model.misValue = misValue;

            return (true);

        }
Your creating at least two instances, as far as I understand your code...