C# Excel.Interop issues - c#

Brief details:
Running Office 360 with Excel 64bit installed.
Application is built on .NET 4.6 and CPU type is set to x64
The code that's not working - line marked where it fails
public bool CreateInvoice()
{
try
{
//Write file
var setting = new Classes.Settings();
string WritePath = setting.DefaultSavePath + "\\Invoices\\" + InvoiceDetails.CustomerID + "\\" + InvoiceDetails.InvoiceNumber + ".xlsx";
if (!System.IO.Directory.Exists(setting.DefaultSavePath + "\\Invoices\\" + InvoiceDetails.CustomerID))
System.IO.Directory.CreateDirectory(setting.DefaultSavePath + "\\Invoices\\" + InvoiceDetails.CustomerID);
if (System.IO.File.Exists(WritePath))
System.IO.File.Delete(WritePath);
System.IO.File.WriteAllBytes(WritePath, AccountManagement.Properties.Resources.Invoice);
//Prepare Excel
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbooks xlWorkBooks = null;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook = null;
Microsoft.Office.Interop.Excel.Sheets xlSheets = null;
Microsoft.Office.Interop.Excel.Worksheet xlExportSheet = null;
Classes.GetExcelProcessID getExcelProcessID = new GetExcelProcessID();
xlWorkBooks = xlApp.Workbooks; //***********FAILS HERE*************
xlWorkBook = xlWorkBooks.Add(WritePath);
xlSheets = xlApp.Worksheets;
xlExportSheet = (Microsoft.Office.Interop.Excel.Worksheet)(xlSheets[1]);
var cells = xlExportSheet.Cells;
var Process = Classes.GetExcelProcessID.ExcelProcesID(xlApp);
try
{
xlApp.Visible = false;
xlApp.DisplayAlerts = false;
//This is where I make my edits.
xlWorkBook.SaveAs(WritePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
xlWorkBook.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF, setting.DefaultSavePath + "\\Invoices\\" + InvoiceDetails.CustomerID + "\\" + InvoiceDetails.InvoiceNumber + ".pdf");
InvoiceSavePath = setting.DefaultSavePath + "\\Invoices\\" + InvoiceDetails.CustomerID + "\\" + InvoiceDetails.InvoiceNumber + ".pdf";
InvoiceDetails.InvoiceSavePath = InvoiceSavePath;
}
catch (Exception ex)
{
return false;
}
finally
{
//Ensue all COM objects are closed and realesed or EXCEl will remain open.
xlWorkBook.Close(0, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
xlWorkBooks.Close();
//xlApp.Application.Quit();
xlApp.Quit();
while (Marshal.FinalReleaseComObject(xlApp) != 0) { }
while (Marshal.FinalReleaseComObject(xlWorkBooks) != 0) { }
while (Marshal.FinalReleaseComObject(xlWorkBook) != 0) { }
while (Marshal.FinalReleaseComObject(xlSheets) != 0) { }
while (Marshal.FinalReleaseComObject(xlExportSheet) != 0) { }
while (Marshal.FinalReleaseComObject(cells) != 0) { }
xlApp = null;
xlWorkBooks = null;
xlWorkBook = null;
xlSheets = null;
xlExportSheet = null;
cells = null;
try
{
Process.Kill();
}
catch
{
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return false;
}
return true;
}
This is the exception I keep getting.
Unable to cast COM object of type 'Microsoft.Office.Interop.Excel.ApplicationClass' to interface type 'Microsoft.Office.Interop.Excel._Application'
I initially thought the issue was about my application possibly still being built at x86 but I have a interop function with Word that runs perfectly fine - and that's 64bit.
I've tried google but all the fixes are to do with 64bit office and a 32bit application.
Any tips?

Related

Get Excel Active Worksheet with C#

I am wondering why this code gets the open worksheet when I run it in debug, and catch an exception when I run it with no debug..
Excel.Application xlApp = null;
Excel.Workbook xlWBook = null;
Excel.Worksheet xlWSheet = null;
Excel.Range xlRange = null;
try {
xlApp = (Excel.Application) Marshal.GetActiveObject("Excel.Application");
xlApp.Visible = true;
xlWBook = xlApp.ActiveWorkbook;
xlWSheet = xlWBook.ActiveSheet;
xlRange = xlWSheet.UsedRange;
logResult = logResult + "Agganciato " + xlWBook.Name + " \r\n";
} catch {
logResult = logResult + "Nessun file aperto rilevato. \r\n";
}
Any suggestion?
The following shows how one can use Excel Interop to either interact with an open Excel workbook or create a new workbook if one isn't open.
Try the following:
Add Reference (Option 1)
Download / install NuGet package: Microsoft.Office.Interop.Excel
Add Reference (Option 2)
In VS menu, click Project
Select Add Reference...
Click COM
Check Microsoft Excel xx.x Object Library (ex: Microsoft Excel 16.0 Object Library)
Add the following using directives:
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.IO;
using System.Diagnostics;
CreateExcelWorkbook
public void CreateExcelWorkbook(string filename)
{
bool isExcelAlreadyRunning = false;
string logResult = string.Empty;
Excel.Application xlApp = null;
Excel.Workbook xlWBook = null;
Excel.Worksheet xlWSheet = null;
Excel.Range xlRange = null;
try
{
try
{
//if Excel isn't open, this will throw a COMException
xlApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
//set value
isExcelAlreadyRunning = true;
}
catch (System.Runtime.InteropServices.COMException ex)
{
//create new instance
xlApp = new Excel.Application();
}
//whether or not to make Excel visible
xlApp.Visible = true;
//prevent prompting to overwrite existing file
xlApp.DisplayAlerts = false;
//disable user control while modifying the Excel Workbook
//to prevent user interference
//only necessary if Excel application Visibility property = true
//need to re-enable before exitin this method
//xlApp.UserControl = false;
if (xlApp.Workbooks.Count > 0)
xlWBook = xlApp.ActiveWorkbook;
else
xlWBook = xlApp.Workbooks.Add();
if (xlWBook.Worksheets.Count > 0)
xlWSheet = xlWBook.ActiveSheet;
else
xlWSheet = xlWBook.Sheets.Add();
xlRange = xlWSheet.UsedRange;
//set value
xlWSheet.Cells[1, 1] = $"Test {DateTime.Now.ToString("HH:mm:ss.fff")}";
//save Workbook - if file exists, overwrite it
// xlWBook.SaveAs(filename, Excel.XlFileFormat.xlWorkbookDefault, System.Reflection.Missing.Value, System.Reflection.Missing.Value, true, false, Excel.XlSaveAsAccessMode.xlNoChange, Excel.XlSaveConflictResolution.xlLocalSessionChanges, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
xlWBook.SaveAs(filename, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
logResult = logResult + "Agganciato " + xlWBook.Name + " \r\n";
}
catch
{
logResult = logResult + "Nessun file aperto rilevato. \r\n";
}
finally
{
if (xlWBook != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWSheet);
xlWSheet = null;
xlRange = null;
if (!isExcelAlreadyRunning)
{
//close workbook
xlWBook.Close(false);
}
//release all resources
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWBook);
xlWBook = null;
}
System.Threading.Thread.Sleep(150);
if (xlApp != null)
{
if (!isExcelAlreadyRunning)
{
xlApp.Quit();
}
//release all resources
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp);
xlApp = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
System.Threading.Thread.Sleep(175);
}
}
}
Usage:
CreateExcelWorkbook(filename);
//the following is necessary otherwise the Excel process seems to persist in Task Manager
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Resources:
Microsoft.Office.Interop.Excel Namespace
Excel is still running though I quit and released the object
Cannot close Excel.exe after Interop process

Memory issues with excel interops , memory out exception

I have a code that converts bunch of csv files into excel and then highlights some rows.When I feed multiple files it throws memory out of exception . I believe there are memory leaks in code pertaining to com objects.Also, I am not sure how to correctly place garbage collectors.
Below is my do work method of background worker . It works fine if I put single file but for multiple file is throws exception. I just need help in assesing if i am correctly releasing memory ,or my logic is inefficient, or really i am using extra memory [I dont believe this might be case]
Giving below my code for expert analysis
try
{
Microsoft.Office.Interop.Excel.Application oXL;
Microsoft.Office.Interop.Excel.Workbook oWB;
Microsoft.Office.Interop.Excel.Worksheet oSheet;
Microsoft.Office.Interop.Excel.Range oRng;
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = false;
oWB = (Microsoft.Office.Interop.Excel.Workbook)(oXL.Workbooks.Add(""));
oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oWB.ActiveSheet;
oSheet.Name = "Summary Report";
object misvalue = System.Reflection.Missing.Value;
int file_progress_Delta = 72 / lstFileName.Count();
int droppedCount = 0;
int acceptedCount = 0;
int invalidMACCount = 0;
int ARCRepeatedCount = 0;
int tMAC1matchedCount = 0;
int tMACmatchedCount = 0;
int tMAC2matchedCount = 0;
int tMAC3matchedCount = 0;
int syncFrameARCUpdatedCount = 0;
int resyncFrameARCUpdatedCount = 0;
int syncFrameARCNotUpdatedCount = 0;
int resyncFrameARCNotUpdatedCount = 0;
int securedinvalidframeCount = 0;
int ARClessthanwindowCount = 0;
int tMACNotMatchedSyncFrame = 0;
int tMACNotMatchedReSyncFrame = 0;
int tMACMatched = 0;
int IPDUDLCZeroCount = 0;
int IPDUDLCEightCount = 0;
int invalidpaddingCount = 0;
int invalidContainerFrame = 0;
oSheet.Cells[2, 3] = "Log Analysis Report";
oSheet.Cells[4, 4] = "Category";
oSheet.Cells[4, 5] = "Count";
oSheet.Cells[6, 4] = "Result";
oSheet.Cells[7, 4] = "Accepted";
oSheet.Cells[8, 4] = "Dropped";
oSheet.Cells[10, 4] = "Remarks";
oSheet.Cells[11, 4] = "Invalid MAC";
oSheet.Cells[12, 4] = "ARC Repeated";
oSheet.Cells[13, 4] = "tMAC1 matched";
oSheet.Cells[14, 4] = "tMAC2 matched";
oSheet.Cells[15, 4] = "tMAC3 matched";
oSheet.Cells[16, 4] = "Sync Frame ARC Updated";
oSheet.Cells[17, 4] = "Resync Frame ARC Updated";
oSheet.Cells[18, 4] = "MAC matched. Sync frame ARC not updated";
oSheet.Cells[19, 4] = "MAC matched. Resync frame ARC not updated";
oSheet.Cells[20, 4] = "Secured invalid frame";
oSheet.Cells[21, 4] = "ARC less than window";
oSheet.Cells[22, 4] = "tMAC Not Matched Sync Frame";
oSheet.Cells[23, 4] = "tMAC Not Matched ReSync Frame";
oSheet.Cells[24, 4] = "tMAC Matched";
oSheet.Cells[25, 4] = "Secure container frame check";
oSheet.Cells[26, 4] = "IPDU DLC =0";
oSheet.Cells[27, 4] = "IPDU DLC >8";
oSheet.Cells[28, 4] = "Invalid padding";
oSheet.Cells[29, 4] = "Invalid Container Frame";
oSheet.Cells[30, 4] = "Sync ARC jumps greater than 1 million";
oSheet.get_Range("E7", "E30").HorizontalAlignment =
Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
oSheet.get_Range("C2", "F2").HorizontalAlignment =
Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
oSheet.get_Range("C2", "F2").Font.Bold = true;
oSheet.get_Range("C2", "F2").Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue);
oSheet.get_Range("D4", "E4").Font.Bold = true;
oSheet.get_Range("D4", "E4").Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue);
oSheet.get_Range("D4", "E4").VerticalAlignment =
Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
oSheet.get_Range("D6", "E6").Font.Bold = true;
oSheet.get_Range("D6", "E6").Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue);
oSheet.get_Range("D6", "E6").VerticalAlignment =
Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
oSheet.get_Range("D10", "E10").Font.Bold = true;
oSheet.get_Range("D10", "E10").Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue);
oSheet.get_Range("D10", "E10").VerticalAlignment =
Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
oSheet.get_Range("D25", "E25").Font.Bold = true;
oSheet.get_Range("D25", "E25").Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue);
oSheet.get_Range("D25", "E25").VerticalAlignment =
Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
oSheet.get_Range("D30", "E30").Font.Bold = true;
oSheet.get_Range("D30", "E30").Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightBlue);
oSheet.get_Range("D30", "E30").VerticalAlignment =
Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
oRng = oSheet.get_Range("C2", "F2");
oRng.Borders.Color = System.Drawing.Color.Black.ToArgb();
oRng = oSheet.get_Range("D4", "D30");
oRng.Borders.Color = System.Drawing.Color.Black.ToArgb();
oRng = oSheet.get_Range("E4", "E30");
oRng.Borders.Color = System.Drawing.Color.Black.ToArgb();
oSheet.Range[oSheet.Cells[2, 3], oSheet.Cells[2, 6]].Merge();
oRng = oSheet.get_Range("D4", "E4");
oRng.EntireColumn.AutoFit();
//backgroundWorker1.ReportProgress(3,0);
backgroundWorker1.ReportProgress(5);
percentageCounter = 5;
fileCount = 0;
foreach (String file in lstFileName)
{
//GC.Collect();
//GC.WaitForPendingFinalizers();
Thread.Sleep(1000);
Microsoft.Office.Interop.Excel.Application appCSVToExcel;
Excel.Application appHighlight;
string name = file.Split('.')[0].ToString().Split('\\').Last();
//Converting each file from .csv to excel
appCSVToExcel = new Microsoft.Office.Interop.Excel.Application();
appCSVToExcel.DisplayAlerts = false;
Microsoft.Office.Interop.Excel.Workbook wbCSVToExcel = appCSVToExcel.Workbooks.Open(file, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wbCSVToExcel.SaveAs(outputFolderPath + "\\" + name + ".xlsx", Excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wbCSVToExcel.Close();
appCSVToExcel.Quit();
//int generation_3 = System.GC.GetGeneration(appCSVToExcel);
//System.GC.Collect(generation_3);
Marshal.ReleaseComObject(wbCSVToExcel);
Marshal.ReleaseComObject(appCSVToExcel);
//appCSVToExcel =null;
//wbCSVToExcel = null;
//GC.Collect();
//GC.WaitForPendingFinalizers();
//Thread.Sleep(2);
//backgroundWorker1.ReportProgress(10);
//Highlighting the excel files
//Application.DoEvents();
//GC.Collect();
appHighlight = new Excel.Application();
var wbHighlight = appHighlight.Workbooks;
var workbook = wbHighlight.Open(outputFolderPath + "\\" + name + ".xlsx", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
Microsoft.Office.Interop.Excel.Worksheet worksheet = workbook.ActiveSheet;
Microsoft.Office.Interop.Excel.Range usedRange = worksheet.UsedRange;
Microsoft.Office.Interop.Excel.Range rows = usedRange.Rows;
Microsoft.Office.Interop.Excel.Range columns = usedRange.Columns;
appHighlight.DisplayAlerts = false;
r = rows.Count;
c = columns.Count;
var startCell = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[1, 1];
var endCell = (Microsoft.Office.Interop.Excel.Range)worksheet.Cells[r, 12];
object[,] RangeValues = worksheet.get_Range(startCell, endCell).Value2;
ArrayList higlight = new ArrayList();
for (int i = 1; i <= r; i++)
{
if (RangeValues[i, 8] != null)
{
//if (RangeValues[i, 9].ToString() == "Invalid MAC"
//|| RangeValues[i, 9].ToString() == "ARC Repeated"
//|| RangeValues[i, 9].ToString() == "Secured invalid frame"
//|| RangeValues[i, 9].ToString() == "ARC less than window")
if (RangeValues[i, 8].ToString() == "Dropped")
{
higlight.Add(i);
}
}
//Thread.Sleep(2);
//backgroundWorker1.ReportProgress(20);
string firstCellValue1 = "";
if (RangeValues[i, 8] != null)
{
firstCellValue1 = RangeValues[i, 8].ToString();
}
if (firstCellValue1 == "Accepted")
{
acceptedCount++;
}
if (firstCellValue1 == "Dropped")
{
droppedCount++;
}
string cell = "";
if (RangeValues[i, 9] != null)
{
cell = RangeValues[i, 9].ToString();
}
switch (cell)
{
case "Invalid MAC":
invalidMACCount++;
break;
case "ARC Repeated":
ARCRepeatedCount++;
break;
case "tMAC1 matched":
tMAC1matchedCount++;
break;
case "tMAC2 matched":
tMAC2matchedCount++;
break;
case "tMAC3 matched":
tMAC3matchedCount++;
break;
case "Sync Frame ARC Updated":
syncFrameARCUpdatedCount++;
break;
case "Resync Frame ARC Updated":
resyncFrameARCUpdatedCount++;
break;
case "MAC matched. Sync frame ARC not updated":
syncFrameARCNotUpdatedCount++;
break;
case "MAC matched. Resync frame ARC not updated":
resyncFrameARCNotUpdatedCount++;
break;
case "ARC less than window":
ARClessthanwindowCount++;
break;
case "tMAC Matched":
tMACmatchedCount++;
break;
case "tMAC Not Matched Sync Frame":
tMACNotMatchedSyncFrame++;
break;
case "tMAC Not Matched ReSync Frame":
tMACNotMatchedReSyncFrame++;
break;
default:
break;
}
string cellReceptionRemarks = "";
if (RangeValues[i, 12] != null)
{
cellReceptionRemarks = RangeValues[i, 12].ToString();
}
switch (cellReceptionRemarks)
{
case "Zero DLC of 'contained I-PDU' has been detected.":
IPDUDLCZeroCount++;
break;
case "DLC greater than 8 in 'contained I-PDU' has been detected.":
IPDUDLCEightCount++;
break;
case "Padding other than 0x00 or 0xFF is observed in frame":
invalidpaddingCount++;
break;
case "Invalid container frame structure.":
invalidContainerFrame++;
break;
}
//backgroundWorker1.ReportProgress(25,0);
//percentageCounterFile++;
//int countProcessFile = r;
//percentFile = 100 - (((countProcessFile - percentageCounterFile) * 100) / countProcessFile);
//backgroundWorker1.ReportProgress(percentFile);
}
for (int k = 0; k < higlight.Count; k++)
{
string exclcmnS1 = "A" + higlight[k];
string exclcmnL1 = "L" + higlight[k];
Excel.Range _range1;
_range1 = worksheet.get_Range(exclcmnS1, exclcmnL1);
_range1.Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Pink);
_range1.Font.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);
}
workbook.SaveAs(outputFolderPath + "\\" + name + ".xlsx", Excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
// GC.Collect();
//GC.WaitForPendingFinalizers();
//GC.Collect();
//GC.WaitForPendingFinalizers();
int generation = System.GC.GetGeneration(appHighlight);
System.GC.Collect(generation);
//int generation_4 = System.GC.GetGeneration(wbHighlight);
//System.GC.Collect(generation_4);
//int generation_5 = System.GC.GetGeneration(workbook);
//System.GC.Collect(generation_4);
//int generation_6 = System.GC.GetGeneration(worksheet);
//System.GC.Collect(generation_4);
//int generation_7 = System.GC.GetGeneration(usedRange);
//System.GC.Collect(generation_4);
//int generation_8 = System.GC.GetGeneration(rows);
//System.GC.Collect(generation_4);
//int generation_9 = System.GC.GetGeneration(columns);
//System.GC.Collect(generation_4);
wbHighlight.Close();
//workbook.Close(0);
appHighlight.Quit();
//usedRange.Clear();
//rows.Clear();
//columns.Clear();
while (Marshal.ReleaseComObject(appHighlight) != 0) { }
while (Marshal.ReleaseComObject(wbHighlight) != 0) { }
while (Marshal.ReleaseComObject(workbook) != 0) { }
while (Marshal.ReleaseComObject(worksheet) != 0) { }
while (Marshal.ReleaseComObject(usedRange) != 0) { }
while (Marshal.ReleaseComObject(rows) != 0) { }
while (Marshal.ReleaseComObject(columns) != 0) { }
//while (Marshal.ReleaseComObject(worksheet.get_Range(startCell, endCell)) != 0) { }
//while (Marshal.ReleaseComObject(RangeValues) != 0) { }
//while (Marshal.ReleaseComObject(_range1) != 0) { }
appHighlight = null;
wbHighlight = null;
workbook = null;
worksheet = null;
usedRange = null;
rows = null;
columns = null;
RangeValues = null;
//_range1 = null;
//startCell = null;
//endCell = null;
//higlight = null;
//KillSpecificExcelFileProcess(name + ".xlsx");
//Thread.Sleep(2);
//backgroundWorker1.ReportProgress(60,0);
//GC.Collect();
//GC.WaitForPendingFinalizers();
//var processes = from p in Process.GetProcessesByName("EXCEL") select p;
//foreach (var process in processes)
//{
// process.Kill();
//}
//For Abnormal ARC
//rch_updates.AppendText(DateTime.Now.ToString("t") + " " + "Analyzing file : "+file +" for Abnormal ARC Increments.\n");
// Application.DoEvents();
var excel_Report = new excel.Application();
var excelWB = excel_Report.Workbooks.Add();
var workSheet = excelWB.ActiveSheet;
dict_ADAS = new Dictionary<Int64, Int64>();
dict_BCM = new Dictionary<Int64, Int64>();
dict_CDM = new Dictionary<Int64, Int64>();
dict_AVM = new Dictionary<Int64, Int64>();
dict_SONAR = new Dictionary<Int64, Int64>();
dict_PWT = new Dictionary<Int64, Int64>();
dict_ATCU = new Dictionary<Int64, Int64>();
// List of class Logdata
data = new List<LogData>();
dict_LogData = new Dictionary<Int64, LogData>();
List<string> lines = new List<string>();
workSheet.Name = "Abnormal ARC Observations";
excel_Report.Visible = false;
workSheet.Cells[1, "A"] = "Time Stamp";
workSheet.Cells[1, "B"] = "CAN ID";
workSheet.Cells[1, "C"] = "DLC";
workSheet.Cells[1, "D"] = "CAN PAYLOAD";
workSheet.Cells[1, "E"] = "RESULT";
workSheet.Cells[1, "F"] = "REMARK";
workSheet.Cells[1, "G"] = "ARC Difference";
//Thread.Sleep(2);
//backgroundWorker1.ReportProgress(65,0);
readCSV(file, lines);
//backgroundWorker1.ReportProgress(70,0);
categorizeSyncFrames();
//backgroundWorker1.ReportProgress(75,0);
identifyAbnormalIndices();
//backgroundWorker1.ReportProgress(80);
writeToReport(workSheet);
//Thread.Sleep(2);
//backgroundWorker1.ReportProgress(85);
dict_LogData.Clear();
dict_ATCU.Clear();
dict_ADAS.Clear();
dict_AVM.Clear();
dict_CDM.Clear();
dict_PWT.Clear();
dict_SONAR.Clear();
dict_BCM.Clear();
ADAS_Indices_List.Clear();
BCM_Indices_List.Clear();
CDM_Indices_List.Clear();
AVM_Indices_List.Clear();
SONAR_Indices_List.Clear();
PWT_Indices_List.Clear();
ATCU_Indices_List.Clear();
data.Clear();
dict_LogData.Clear();
excel_Report.DisplayAlerts = false;
excelWB.SaveAs(outputFolderPath + "\\" + "Abnormal_ARC_Increment" + DateTime.Now.ToLongDateString() + ".xlsx", excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
//GC.Collect();
//GC.WaitForPendingFinalizers();
int generation_2 = System.GC.GetGeneration(excel_Report);
System.GC.Collect(generation_2);
excelWB.Close(0);
excel_Report.Quit();
//rch_updates.AppendText(DateTime.Now.ToString("t") + " " + "File Analysis complete for : " + file + " for Abnormal ARC Increments.\n");
while (Marshal.ReleaseComObject(excel_Report) != 0) { }
while (Marshal.ReleaseComObject(excelWB) != 0) { }
while (Marshal.ReleaseComObject(workSheet) != 0) { }
excel_Report = null;
excelWB = null;
workSheet = null;
fileCount++;
percentageCounter += file_progress_Delta;
backgroundWorker1.ReportProgress(percentageCounter);
}
oSheet.Cells[7, 5] = acceptedCount;
oSheet.Cells[8, 5] = droppedCount;
oSheet.Cells[11, 5] = invalidMACCount;
oSheet.Cells[12, 5] = ARCRepeatedCount;
oSheet.Cells[13, 5] = tMAC1matchedCount;
oSheet.Cells[14, 5] = tMAC2matchedCount;
oSheet.Cells[15, 5] = tMAC3matchedCount;
oSheet.Cells[16, 5] = syncFrameARCUpdatedCount;
oSheet.Cells[17, 5] = resyncFrameARCUpdatedCount;
oSheet.Cells[18, 5] = syncFrameARCNotUpdatedCount;
oSheet.Cells[19, 5] = resyncFrameARCNotUpdatedCount;
oSheet.Cells[20, 5] = securedinvalidframeCount;
oSheet.Cells[21, 5] = ARClessthanwindowCount;
oSheet.Cells[22, 5] = tMACNotMatchedSyncFrame;
oSheet.Cells[23, 5] = tMACNotMatchedReSyncFrame;
oSheet.Cells[24, 5] = tMACMatched;
oSheet.Cells[26, 5] = IPDUDLCZeroCount;
oSheet.Cells[27, 5] = IPDUDLCEightCount;
oSheet.Cells[28, 5] = invalidpaddingCount;
oSheet.Cells[29, 5] = invalidContainerFrame;
//Abnromal ARC observations count
oSheet.Cells[30, 5] = (i - 1) / 2;
backgroundWorker1.ReportProgress(85);
oXL.Visible = false;
oXL.UserControl = false;
oXL.ActiveWindow.DisplayGridlines = false;
oXL.DisplayAlerts = false;
oWB.SaveAs(outputFolderPath + "\\" + DateTime.Now.ToLongDateString() + "Report.xlsx", Excel.XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
oWB.Close(0);
oXL.Quit();
backgroundWorker1.ReportProgress(90);
//Marshal.FinalReleaseComObject(oSheet);
//Marshal.FinalReleaseComObject(oWB);
//Marshal.FinalReleaseComObject(oXL);
//Marshal.FinalReleaseComObject(oRng);
while (Marshal.ReleaseComObject(oXL) != 0) { }
while (Marshal.ReleaseComObject(oWB) != 0) { }
while (Marshal.ReleaseComObject(oSheet) != 0) { }
while (Marshal.ReleaseComObject(oRng) != 0) { }
oXL = null;
oWB = null;
oSheet = null;
oRng = null;
//KillSpecificExcelFileProcess(DateTime.Now.ToLongDateString() + "Report.xlsx");
//Thread.Sleep(2);
backgroundWorker1.ReportProgress(100);
//progressBar3.Value = 100;
e.Result = true;
}
catch (Exception ex)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
MessageBox.Show(ex.ToString());
//wbHighlight.Close();
//appHighlight.Quit();
//int generation = System.GC.GetGeneration(appHighlight);
//System.GC.Collect(generation);
var processes = from p in Process.GetProcessesByName("EXCEL") select p;
foreach (var process in processes)
{
process.Kill();
}
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
//wbHighlight.Close();
//appHighlight.Quit();
//int generation = System.GC.GetGeneration(appHighlight);
//System.GC.Collect(generation);
var processes = from p in Process.GetProcessesByName("EXCEL") select p;
foreach (var process in processes)
{
process.Kill();
}
}
Why do you create new Excel instance for each file ? Try to create one excel instance and just close the workbook and open a new one for each file.
It is bad practice to call GC.Collect manually (GC is quite smart to collect object instances if there is no alive dependencies).
You do not have to copy the same code from finally to catch - finally is executed always.
Why do you think that Excel causes out of memory? What about identifyAbnormalIndices, writeToReport, writeToReport methods? Seems that there are a lot of global variables, like dictionaries you are creating.
Are you using using when working with file/stream in the readCSV method?
Is there really need to store int64 in the Dictionary btw? Can you use int32 ?
Try to use VS memory dumps and check what kind of objects are being kept in the memory. Just run the program under debug and take memory dump after one file was processed. Then you can compare the dumps, check the diff and you will get some imagine what objects are not collected by the GC.
UPD link provided by #bradbury9 should be taken into account as well.

C# Excel PivotItem Visibility

I want to use C# to get the values of the checkboxes from the Excel Filter.
so ...
Proj_1 should be true
Proj_2 should be true
Proj_3 should be false
Proj_4 should be false
Below is the code I am currently using but item.Visible is ALWAYS false no matter if the UI has a check by it or not (unless I uncheck Select Multiple Items) but I need that checked
foreach (PivotField fld in pivotFields)
{
Console.WriteLine(fld.Name + " -- " + fld.Orientation + " -- " + fld.EnableItemSelection + " -- " + fld.EnableMultiplePageItems + " -- ");
foreach (PivotItem item in fld.PivotItems(Type.Missing))
{
if (item.Visible == true)
{
Console.WriteLine("Item" + item.Name + " in field " + fld.Name + "is Visible (Selected)");
}
else
{
Console.WriteLine("Item" + item.Name + " in field " + fld.Name + "is Hidden (Not Selected)");
}
}
}
This is something that works, if the Microsoft.Office.Interop.Excel library is added:
namespace ExcelAtSomething
{
using System;
using Excel = Microsoft.Office.Interop.Excel;
class Startup
{
static void Main()
{
string filePath = #"C:\Users\stackoverflow\Desktop\Sample.xlsx";
Excel.Application excel = new Excel.Application();
excel.Visible = true;
excel.EnableAnimations = true;
Excel.Workbook wkb = Open(excel, filePath);
foreach (Excel.Worksheet xlWorksheet in wkb.Worksheets)
{
Excel.PivotTables pivotTablesCollection = xlWorksheet.PivotTables();
if (pivotTablesCollection.Count > 0)
{
for (int i = 1; i <= pivotTablesCollection.Count; i++)
{
Excel.PivotTable currentPivotTable = pivotTablesCollection.Item(i);
Console.WriteLine($"Table is named -> {currentPivotTable.Name}");
foreach (Excel.PivotField pivotField in currentPivotTable.PivotFields())
{
Console.WriteLine($"\nField is named -> {pivotField.Name}");
foreach (Excel.PivotItem visibleItems in pivotField.VisibleItems)
{
Console.WriteLine($"Visible item name -> {visibleItems.Name}");
}
foreach (Excel.PivotItem PivotItem in pivotField.PivotItems())
{
Console.WriteLine($"Item is named -> {PivotItem.Name}");
Console.WriteLine(PivotItem.Visible);
}
}
}
}
}
excel.EnableAnimations = true;
wkb.Close(true);
excel.Quit();
Console.WriteLine("Finished!");
}
private static Excel.Workbook Open(Excel.Application excelInstance,
string fileName, bool readOnly = false,
bool editable = true, bool updateLinks = true)
{
Excel.Workbook book = excelInstance.Workbooks.Open(
fileName, updateLinks, readOnly,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, editable, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
return book;
}
}
}
The trick is that except for PivotItem, there is a PivotField, which has a list of its visible items. If you display these, then only the visible ones are displayed:
Playing a bit and probably making custom a function, that returns the non-visible items, which are not in that list is a good option for the Excel.

C# Interop print and close Excel file

have problem with interop and editing existing excel file. Excel app doesn't want to close. If I set code, when I edit cells, as comment, rest of code work as I need - Excel open and after print dialog close.
Excel.Application excelApp = null;
Excel.Workbook excelWorkbook = null;
Excel.Worksheet excelWorksheet = null;
string workbookPath = "";
if (RBType1.Checked == true) { workbookPath = Path.GetFullPath("Excel/Mesto.xls"); }
else if (RBType2.Checked == true) { workbookPath = Path.GetFullPath("Excel/Ulehly.xls"); }
else if (RBType3.Checked == true) { workbookPath = Path.GetFullPath("Excel/Spolecenstvi.xls"); }
else if (RBType4.Checked == true) { workbookPath = Path.GetFullPath("Excel/Vlastnici.xls"); }
excelApp = new Excel.Application();
excelApp.Visible = true;
excelWorkbook = excelApp.Workbooks.Open(workbookPath, 0, false, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
excelWorksheet = (Excel.Worksheet)excelWorkbook.Worksheets.get_Item(1);
excelWorksheet.Cells[4, "J"] = RequisitionNumberBox.Text;
excelWorksheet.Cells[9, "C"] = ApplicantBox.Text;
excelWorksheet.Cells[9, "G"] = StreetBox.Text;
excelWorksheet.Cells[9, "J"] = CPBoxC.Text;
excelWorksheet.Cells[10, "J"] = CBBox.Text;
excelWorksheet.Cells[11, "D"] = CTBox.Text;
excelWorksheet.Cells[11, "G"] = ContactPersonBox.Text;
excelWorksheet.Cells[14, "B"] = RepairBox.Text;
excelWorksheet.Cells[20, "B"] = ItemBox.Text;
if (PMOption1.Checked == true) { excelWorksheet.Cells[23, "D"] = "X"; }
if (PMOption2.Checked == true) { excelWorksheet.Cells[24, "D"] = "X"; }
excelWorksheet.Cells[23, "F"] = IssueDate.Text;
excelApp.Dialogs[Excel.XlBuiltInDialog.xlDialogPrint].Show();
excelWorkbook.Close(false, Type.Missing, Type.Missing);
excelApp.Quit();
releaseObject(excelWorksheet);
releaseObject(excelWorkbook);
releaseObject(excelApp);
releaseObject code (found this on internet)
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();
}
How I should edit this code, that it close Excel when program edits cells?

Generic Parser Design

I have this function implemented for parsing employee details, similarly i will have to parse for sales, customer etc for that i need to create 2 more functions. The code will be repeated in all the functions only difference being
the return type of the function
instantiating appropriate object
cells to read
is there any way to move the repeating code to a class and configure it so that i an reuse it?
public List<Employee> ParseEmployee(string filePath)
{
Application _excelApp = null;
Workbooks workBooks = null;
Workbook workBook = null;
Sheets wSheets = null;
Worksheet wSheet = null;
Range xlRange = null;
Range xlRowRange = null;
Range xlcolRange = null;
List<Employee> empLst= new List<Employee>();
try
{
_excelApp = new Application();
workBooks = _excelApp.Workbooks;
workBook = workBooks.Open(filePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
wSheets = (Sheets)workBook.Sheets;
wSheet = (Worksheet)wSheets.get_Item(1);
xlRange = wSheet.UsedRange;
xlRowRange = xlRange.Rows;
xlcolRange = xlRange.Columns;
int rowCount = xlRowRange.Count;
int colCount = xlcolRange.Count;
for (int i = 2; i <= rowCount; i++)
{
Range cell1 = xlRange.Cells[i, 1] as Range;
Range cell2 = xlRange.Cells[i, 2] as Range;
Range cell3 = xlRange.Cells[i, 3] as Range;
object val1 = cell1.Value2;
object val2 = cell2.Value2;
object val3 = cell3.Value2;
Employee emp = new Employee();
emp.FirstName = val1.ToString();
emp.LastName = val2.ToString();
emp.EmpID = val3.ToString();
empLst.Add(emp);
Marshal.ReleaseComObject(cell1);
Marshal.ReleaseComObject(cell2);
Marshal.ReleaseComObject(cell3);
}
}
catch (Exception exp)
{
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
workBook.Close(false, Type.Missing, Type.Missing);
_excelApp.Quit();
Marshal.ReleaseComObject(xlRowRange);
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlcolRange);
Marshal.ReleaseComObject(wSheet);
Marshal.ReleaseComObject(wSheets);
Marshal.ReleaseComObject(workBook);
Marshal.ReleaseComObject(workBooks);
Marshal.ReleaseComObject(_excelApp);
}
return empLst;
}
I think the visitor pattern might be a good fit here. You modify the function you have above to include a parameter called visitor. Then you modify your for loop to pass relevant data to the visitor object:
for (int i = 2; i <= rowCount; i++)
{
visitor.VisitRow(xlRange.Cells, i);
}
The visitor.VisitRow() function will extract the data it needs and keeps internally a reference to the extracted objects. You will have different visitors, one for employers, one for sales, customers, etc.
In the end, you will write something like this:
Visitor employerVisitor = new EmployerVisitor();
Visitor salesVisitor = new SalesVisitor();
Parse("workbook-employers.xls", employerVisitor);
Parse("workbook-sales.xls", salesVisitor);
List<Employee> employers = employerVisitor.GetData();
List<Sale> sales = salesVisitor.GetData();
You could expose this from a generic class, along the lines of:
public class ObjectParser<T>
{
public List<T> ParseObject(string filePath, Func<Range, T> f)
{
Application _excelApp = null;
Workbooks workBooks = null;
Workbook workBook = null;
Sheets wSheets = null;
Worksheet wSheet = null;
Range xlRange = null;
Range xlRowRange = null;
Range xlcolRange = null;
List<T> lst= new List<T>();
try
{
_excelApp = new Application();
workBooks = _excelApp.Workbooks;
workBook = workBooks.Open(filePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
wSheets = (Sheets)workBook.Sheets;
wSheet = (Worksheet)wSheets.get_Item(1);
xlRange = wSheet.UsedRange;
xlRowRange = xlRange.Rows;
xlcolRange = xlRange.Columns;
int rowCount = xlRowRange.Count;
int colCount = xlcolRange.Count;
for (int i = 2; i <= rowCount; i++)
{
lst.Add(f(xlRange));
}
}
catch (Exception exp)
{
}
finally
{
GC.Collect();
GC.WaitForPendingFinalizers();
workBook.Close(false, Type.Missing, Type.Missing);
_excelApp.Quit();
Marshal.ReleaseComObject(xlRowRange);
Marshal.ReleaseComObject(xlRange);
Marshal.ReleaseComObject(xlcolRange);
Marshal.ReleaseComObject(wSheet);
Marshal.ReleaseComObject(wSheets);
Marshal.ReleaseComObject(workBook);
Marshal.ReleaseComObject(workBooks);
Marshal.ReleaseComObject(_excelApp);
}
return lst;
}
}
To use this:
ObjectParser<Employee> op = new ObjectParser<Employee>()
op.Parse(filepath, r => /* insert code to handle Employee here */)
My concern here is that some of the Marshall.ReleaseComObject() calls are pushed onto the lambda that is passed in, which makes that a little heavy-weight. Can you tell us more about the differences in what cells are used between Employee and the other types?
I have re-factored my code to something like this
class ExcelParser : IDisposable
{
bool disposed = false;
Application _excelApp = null;
Workbooks workBooks = null;
Workbook workBook = null;
Sheets wSheets = null;
Worksheet wSheet = null;
Range xlRange = null;
Range xlRowRange = null;
Range xlcolRange = null;
public bool Load(string filePath)
{
bool bFlag = true;
try
{
_excelApp = new Application();
workBooks = _excelApp.Workbooks;
workBook = workBooks.Open(filePath, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
wSheets = (Sheets)workBook.Sheets;
wSheet = (Worksheet)wSheets.get_Item(1);
xlRange = wSheet.UsedRange;
xlRowRange = xlRange.Rows;
xlcolRange = xlRange.Columns;
}
catch (Exception exp)
{
throw;
}
return bFlag;
}
public int GetRowCount()
{
int rowCount = 0;
if(xlRowRange != null)
rowCount = xlRowRange.Count;
return rowCount;
}
public string GetValue(int rowIndex, int colIndex)
{
string value = "";
Range cell = null;
try
{
cell = xlRange.Cells[rowIndex, colIndex] as Range;
object val = cell.Value2;
value = val.ToString();
}
catch (Exception exp)
{
}
finally
{
Marshal.ReleaseComObject(cell);
}
return value;
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{ // don't dispose more than once
if (disposing)
{
// disposing==true means you're not in the finalizer, so
// you can reference other objects here
GC.Collect();
GC.WaitForPendingFinalizers();
if (workBook != null)
workBook.Close(false, Type.Missing, Type.Missing);
if (_excelApp != null)
_excelApp.Quit();
if (xlRowRange != null)
Marshal.ReleaseComObject(xlRowRange);
if (xlRange != null)
Marshal.ReleaseComObject(xlRange);
if (xlcolRange != null)
Marshal.ReleaseComObject(xlcolRange);
if (wSheet != null)
Marshal.ReleaseComObject(wSheet);
if (wSheets != null)
Marshal.ReleaseComObject(wSheets);
if (workBook != null)
Marshal.ReleaseComObject(workBook);
if (workBooks != null)
Marshal.ReleaseComObject(workBooks);
if (_excelApp != null)
Marshal.ReleaseComObject(_excelApp);
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~ExcelParser()
{
Dispose(false);
}
}
and the calling code looks like this
public List<Employee> Handle(string filePath)
{
List<Employee> empLst = new List<Employee>();
ExcelParser exlParser = new ExcelParser();
try
{
if (exlParser.Load(filePath))
{
int rowCount = exlParser.GetRowCount();
for (int i = 2; i <= rowCount; i++)
{
Employee emp = new Employee();
emp.FirstName = exlParser.GetValue(i, 1);
emp.LastName = exlParser.GetValue(i, 2);
emp.EmpID = exlParser.GetValue(i, 3);
empLst.Add(emp);
}
}
}
catch (Exception exp)
{
}
finally
{
exlParser.Dispose();
}
return empLst;
}
so now i can reuse the parser in whatever places i wish to use. please comment whether this is correct

Categories

Resources