excelcomobject

Disconnected Context Excel Com Object


I have an multi threaded Application. One of the property of application is reporting.

User can take one year data day by day

I fetch the database, get the results to the List. Then use Excel (as com object).

Excel is opened and cell values are started to be added from the list.

While these processes are going suddenly I get this message:

The Error

Here is my code for excel reporting:

private void RNReportDensityStatistics(List<object[]> _PlateBasedDensityStaticticsList)
        {
            try
            {
                RNTakeReportButton.Enabled = false;
                RNExcelApp = new RNExcel.Application();
                RNExcelApp.Visible = false;
                RNWorkBook = RNExcelApp.Workbooks.Add();
                RNWorkSheet = (RNExcel.Worksheet)RNExcelApp.ActiveSheet;
                RNExcelApp.DisplayAlerts = false;

                RNProgressBar.Visible = true;
                RNProgressBar.Minimum = 0;
                RNProgressBar.Maximum = _PlateBasedDensityStaticticsList.Count;
                RNProgressBar.Value = 0;
                RNProgressBar.Step = 1;

                RNExcelApp.Range["A2"].Value = GetGUIItemString(GUIItemIndex.RNReportDensityStatisticsAutoParkPlate);
                RNExcelApp.Range["B2"].Value = GetGUIItemString(GUIItemIndex.RNReportDensityStatisticsAutoParkEntryTime);
                RNExcelApp.Range["C2"].Value = GetGUIItemString(GUIItemIndex.RNReportDensityStatisticsAutoParkExitTime);
                RNExcelApp.Range["D2"].Value = GetGUIItemString(GUIItemIndex.RNReportDensityStatisticsAutoParkCameraIP);
                RNExcelApp.Range["E2"].Value = GetGUIItemString(GUIItemIndex.RNReportDensityStatisticsAutoParkSpaceNo);

                RNWorkSheet.Columns[1].AutoFit();
                RNWorkSheet.Columns[2].AutoFit();
                RNWorkSheet.Columns[3].AutoFit();
                RNWorkSheet.Columns[4].AutoFit();
                RNWorkSheet.Columns[5].AutoFit();

                var row = 2;
                foreach (var DensityStatistics in _PlateBasedDensityStaticticsList)
                {
                    row++;
                    RNWorkSheet.Cells[row, "A"] = DensityStatistics[4];
                    RNWorkSheet.Cells[row, "B"] = ConvertEpochToDateTime(Convert.ToUInt64(DensityStatistics[2]));
                    RNWorkSheet.Cells[row, "C"] = ConvertEpochToDateTime(Convert.ToUInt64(DensityStatistics[3]));
                    RNWorkSheet.Cells[row, "D"] = DensityStatistics[0];
                    RNWorkSheet.Cells[row, "E"] = DensityStatistics[1];                    
                    RNProgressBar.PerformStep();
                }

                RNWorkSheet.Columns[1].AutoFit();
                RNWorkSheet.Columns[2].AutoFit();
                RNWorkSheet.Columns[3].AutoFit();
                RNWorkSheet.Columns[4].AutoFit();
                RNWorkSheet.Columns[5].AutoFit();

                string RNExcelReportPath = RNExcelReportPathStartingAdress
                    + GetGUIItemString(GUIItemIndex.RNReportPathNameAsPlate)
                    + RNPlateSearchTextBox.Text + " "
                    + GetGUIItemString(GUIItemIndex.RNReportPathNameAsDensity)
                                      + ".xlsx";
                RNWorkBook.SaveAs(RNExcelReportPath, 
                                  misValue,
                                  RNExcelPassword, 
                                  misValue, 
                                  misValue,
                                  misValue, 
                                  RNExcel.XlSaveAsAccessMode.xlExclusive,
                                  misValue, 
                                  misValue, 
                                  misValue, 
                                  misValue, 
                                  misValue);

                RNWorkBook.Close(true, misValue, misValue);
                RNExcelApp.Application.Quit();
                RNExcelApp.Quit();

                RNReleaseObject(RNWorkSheet);
                RNReleaseObject(RNWorkBook);
                RNReleaseObject(RNExcelApp);

                RNTakeReportButton.Enabled = true;
                AddLog(LogIndex.RNReportDensityStatisticsSuc, RNExcelReportPath, string.Empty, string.Empty);

            }
            catch (Exception ex)
            {
                RNReleaseObject(RNWorkSheet);
                RNReleaseObject(RNWorkBook);
                RNReleaseObject(RNExcelApp);
                AddException(ex.ToString());
                RNTakeReportButton.Enabled = true;
                AddLog(LogIndex.RNReportDensityStatisticsFail, string.Empty, string.Empty, string.Empty);
            }
            finally
            {
                RNReleaseObject(RNWorkSheet);
                RNReleaseObject(RNWorkBook);
                RNReleaseObject(RNExcelApp);
                RNTakeReportButton.Enabled = true;

                RNProgressBar.Value = _PlateBasedDensityStaticticsList.Count;
                RNProgressBar.Update();
            }
        }

        private void RNReleaseObject(object obj)
        {
            try
            {
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj);

                if (System.Runtime.InteropServices.Marshal.AreComObjectsAvailableForCleanup())
                {
                    System.Runtime.InteropServices.Marshal.CleanupUnusedObjectsInCurrentContext();
                }

                obj = null;
            }
            catch (Exception ex)
            {
                obj = null;
                AddTrace("Unable to release the Object ");
                AddException(ex.ToString());
            }
            finally
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }
        }

Solution

  • There is no need to use COM object for reporting. I solved my problem by not using com object to use excel for reporting.

    There are different tools for reporting and using excel for it

    1. Open XML SDK : http://www.microsoft.com/en-us/download/details.aspx?id=5124

    Documentation http://msdn.microsoft.com/en-us/library/bb491088(v=office.14).aspx

    1. If Open XML SDK syntax is hard for you then you can use: http://spreadsheetlight.com/

    Documentation is very well and Vincent (http://spreadsheetlight.com/about/ ) is really helpful for your questions.

    1. If your application does not require some kind of charts then you can use: http://closedxml.codeplex.com/

    Both of spreadsheetlight and Closed XML are based on Open XML SDK and from my experience I do not any kind of disconnected contex problem.

    If you need to protect your excel files you can use: http://dotnetzip.codeplex.com/ You have a password protected zipped xlsx file.

    In consequence, you dont need to use COM object, interop services and Excel.Exe in your computer.

    I wish the suggestions are helpful and thank you for all who developed SpreadSheetLight and Closed XML and Open XML