Loop operation is not stopping C# - c#

When I try to find a value that is not saved in excel I can't stop loops and get a message from the MessageBox
killExcel();
OpenFileDialog file = new OpenFileDialog();
string filename = Path.GetFileName(file.FileName);
if (file.ShowDialog() == DialogResult.OK) //if there is a file chosen by the user
{
Boolean chc = false;
var Excel = new Microsoft.Office.Interop.Excel.Application();
//var xlWB = Excel.Workbooks.Open("C:/Users/User/Desktop/ttt.xlsx");
var xlWB = Excel.Workbooks.Open(Path.GetFullPath(file.FileName));
var xlSht = xlWB.Worksheets[1];
Microsoft.Office.Interop.Excel.Range range = xlSht.Columns[1];
Microsoft.Office.Interop.Excel.Range findRange;
object missing = System.Reflection.Missing.Value;
findRange = range.Find(id_v.Text, missing,
Microsoft.Office.Interop.Excel.XlFindLookIn.xlValues,
Microsoft.Office.Interop.Excel.XlLookAt.xlPart,
Microsoft.Office.Interop.Excel.XlSearchOrder.xlByRows,
Microsoft.Office.Interop.Excel.XlSearchDirection.xlNext, false, missing, missing);
string result = "";
int a = range.Rows.Count;
if (findRange != null)
{
while (chc==false)
{
for (int i = 1; i <= a; i++)
{
result = Convert.ToString(xlSht.Cells[i, findRange.Column].Value);
if (result == id_v.Text && result != null)
{
id.Text = result;
chc = true;
break;
}
}
if (chc==false) {
MessageBox.Show("Not found!");
break;
}
}
}
}
Sorry I'm just a beginner in programming and I can't understand why the loop is not stopping when the value is not founded

Your while (chc==false) will always return false if the value is not found keeping it in the infinite loop.

Remove the while(csc=false) loop. The for loop accomplishes what you are trying to do and will exit if it finds the entry without the outer while loop. When the for loop exits, either csc will be true because you set it when the entry was found or csc will be false because you initialized it to false before entering the for loop.

Related

C#, Winforms automation app throwing 0x800AC472 error when saving excel file

I am writing a winform app that reads data from an sql database, paste it into excel and then saves the file in a given location.
My current issue is i'm encountering system error : 0x800AC472 when saving down the excel file.
So far I have tried adding
GC.Collect();
GC.WaitForPendingFinalizers();
to the on click method, after calling the excel save function.
From my googling it seems as though it may be due to the COM object not being removed after usage? these GC methods were meant to clear this, but it doesn't seem to be working properly. The reason I think it's not working properly is that there is still a microsoftoffice.exe process running in task manager after executing the code and receiving the error.
Something else worthy of mention is that if i wrap the code in a try-catch, the error is pasted to the console and the excel file is saved without issue, the only issue being that the process is still running in the task manager.
Is anyone here able to help me isolate the issue in my code causing this error? Thank you.
Here is the code that is called upon button press;
else if (((DataGridView)sender).Columns[e.ColumnIndex].DataPropertyName == "Run")
{
// return SQL into datatable
var returnedDT = SQLAcess.SQLtoDataTable(dataGridView1[0, e.RowIndex].Value.ToString()!);
//find item to open
string loadstring = DataGridClass.CellColumn(dataGridView1, "Load_Location", e.RowIndex);
//finds workbook to paste into.
var SettingsDataset = XMLData.ReturnXMLDataset(2);
var workbookstring = XMLData.returnXMLcellwithcolumnname(SettingsDataset, "Data_Dump_Worksheet_name", e.RowIndex);
//find location to save it
string savestring = DataGridClass.CellColumn(dataGridView1, "Save_location", e.RowIndex);
//execute export to excel, with the locations saved from above.
GXOMIClassLibrary.My_DataTable_Extensions.ExportToExcelDetailed(returnedDT, loadstring, workbookstring, savestring);
GC.Collect();
GC.WaitForPendingFinalizers();
}
The
GXOMIClassLibrary.My_DataTable_Extensions.ExportToExcelDetailed(returnedDT, loadstring, workbookstring, savestring);
method refers to a class library I have created with this method below;
public static void ExportToExcelDetailed(this System.Data.DataTable DataTable, string ExcelLoadPath, string WorksheetName, string ExcelSavePath)
{
try
{
int ColumnsCount;
//if datatable is empty throw an exception.
if (DataTable == null || (ColumnsCount = DataTable.Columns.Count) == 0)
throw new Exception("ExportToExcel: Null or empty input table!\n");
// load excel, and create a new workbook
//Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
//Excel.Workbooks.Add();
var excelApp = new Excel.Application();
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(ExcelLoadPath);
//TELL THE PROGRAM WHAT WORKBOOK TO OPEN
// select the right worksheet.
var Worksheet = excelWorkbook.Sheets[WorksheetName];
// DataCells
int RowsCount = DataTable.Rows.Count;
object[,] Cells = new object[RowsCount, ColumnsCount];
for (int j = 0; j < RowsCount; j++)
for (int i = 0; i < ColumnsCount; i++)
Cells[j, i] = DataTable.Rows[j][i];
//find last row
var xlRange = (Excel.Range)Worksheet.Cells[Worksheet.Rows.Count, 1];
long lastRow = (long)xlRange.get_End(Excel.XlDirection.xlUp).Row;
long newRow = lastRow + 1;
///cells[2,1] needs to become cell below last paste
Worksheet.Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[newRow, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[newRow + RowsCount -1, ColumnsCount])).Value = Cells;
// check fielpath
if (ExcelSavePath != null && ExcelSavePath != "")
{
try
{
Worksheet.SaveAs(ExcelSavePath);
excelApp.Quit();
// Worksheet.Close(0);
//richTextBox1("Excel file saved!");
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
+ ex.Message);
excelApp.Quit();
}
}
else // no filepath is given
{
excelApp.Visible = true;
}
excelApp.Quit();
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: \n" + ex.Message);
}
}
changing this part of the ExportToExcelDetailed seems to have corrected the issue;
if (ExcelSavePath != null && ExcelSavePath != "")
{
try
{
Worksheet.SaveAs(ExcelSavePath);
excelApp.Quit();
Marshal.ReleaseComObject(Worksheet);
GC.Collect();
GC.WaitForPendingFinalizers();
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
+ ex.Message);
excelApp.Quit();
}
}
else // no filepath is given
{
excelApp.Visible = true;
}

I'm trying to read a Regex from an xml file but when i pass on the Regex to the C# code but I'm getting false matches

When i give my Regex by Xml I'm getting False matches but when I hardcode the Regex in the C# code I'm getting the right Matches , please help me out.
The code was working fine when I directly put the Regex in the Code. The problem started when I began to use XMl file
public static List<string> RegxFind(string path, string XmlPath)
{
string Patterns = "";
XmlReader reader = XmlReader.Create(XmlPath);
while (reader.Read())
{
if (reader.IsStartElement())
{
switch (reader.Name.ToString())
{
case "reg1":
Console.WriteLine(reader.Value);
Console.ReadKey();
Patterns = reader.Value;
break;
}
}
}
List<string> Results = new List<string>();
Excel.Application xlapp = new Excel.Application();
Excel.Workbooks xlworkbooks = xlapp.Workbooks;
//string Pattern = #"\b[0-9DEF]{2}[A-z]{ 2}[0-9]{6}[0-9]{3}|[0-9DEF]{2}[A-z]{2}[0-9]{6}[\S\s][0-9]{3}|[0-9DEF]{2}[A-z]{2}[0-9]{6}[\S\s][\s][0-9]{3}|[0-9DEF]{2}[A-z]{2}[\s\W\d]{8,12}\b";
try
{
xlapp = new Excel.Application();
xlapp.Visible = true;
xlworkbooks = xlapp.Workbooks;
Excel.Workbook xlworkbook = xlworkbooks.Open(path);
Excel.Sheets xlsheets = xlworkbook.Worksheets;
Excel._Worksheet xlsheet = xlworkbook.Sheets[1];
Excel.Range xlRange = xlsheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
if (xlRange.Cells[i, j].value != null)
{
//Console.WriteLine("vlues" + xlRange.Cells[i, j].Value);
//Console.ReadKey();
string tempstr = Convert.ToString((xlRange.Cells[i, j].Value));
Match m = Regex.Match(tempstr, Patterns);
if (m.Success)
{
Results.Add((xlRange.Cells[i, j].Value) + "<>");
tempstr = "";
}
else
{
tempstr = "";
m.NextMatch();
}
}
else
{
continue;
}
}
}
xlworkbook.Close();
xlapp.Quit();
return Results;
}
catch (Exception es)
{
Console.WriteLine("error:" + es);
Console.ReadKey();
return Results;
}
}
The problem is , when I'm reading from the xml file I'm unable to get proper match as the Pattern variable is not receiving any value at line Regx.match(tempstr,patterns)
I want The code to give me correct pattern Matches
here the xml for reference :
<?xml version="1.0" encoding="UTF-8"?>
<pattern>
<reg1>#"\b[0-9DEF]{2}[A-z]{ 2}[0-9]{6}[0-9]{3}|[0-9DEF]{2}[A-z]{2}[0-9]{6}[\S\s][0-9]{3}|[0-9DEF]{2}[A-z]{2}[0-9]{6}[\S\s][\s][0-9]{3}|[0-9DEF]{2}[A-z]{2}[\s\W\d]{8,12}\b"</reg1>
</pattern>
First, fix your pattern a bit: 1) group the alternatives so that word boundaries could be applied to all the alternatives, 2) replace [A-z] with [A-Za-z] to match just ASCII letters and 3) remove spaces inside limiting quantifiers.
So, it should at least look like
\b(?:[0-9DEF]{2}[A-Za-z]{2}[0-9]{6}[0-9]{3}|[0-9DEF]{2}[A-Za-z]{2}[0-9]{6}[\S\s][0-9]{3}|[0-9DEF]{2}[A-Za-z]{2}[0-9]{6}[\S\s][\s][0-9]{3}|[0-9DEF]{2}[A-Za-z]{2}[\s\W\d]{8,12})\b
You may further contract it by grouping it further as the [0-9DEF]{2}[A-Za-z]{2} starts all the alternatives:
\b[0-9DEF]{2}[A-Za-z]{2}(?:[0-9]{6}(?:[0-9]{3}|[\S\s]\s?[0-9]{3})|[\s\W\d]{8,12})\b
See the regex demo.
Put it into a Patterns.xml file as a string inside a CDATA block to avoid having to escape chars:
<?xml version="1.0" encoding="UTF-8"?>
<pattern>
<reg1><![CDATA[\b[0-9DEF]{2}[A-Za-z]{2}(?:[0-9]{6}(?:[0-9]{3}|[\S\s]\s?[0-9]{3})|[\s\W\d]{8,12})\b]]></reg1>
</pattern>
Read it:
public static string RegxFind(string XmlPath)
{
var xml = XDocument.Load(XmlPath);
return xml.Root.Descendants("reg1").FirstOrDefault()?.Value;
}
Then, read it into any variable, static or not:
var pattern = RegxFind(path_to_xml);
and use the pattern.

Release Interop Excel object

I'm currently writting a C#.NET application who use a VBA macro in an Excel file.
I run the macro from the c# application when the user click on a button. I have to wait all data are downloaded that's why this is the VBA code who execute "Application.Quit".
There is my code :
private void toolStripButton5_Click(object sender, EventArgs e)
{
int lastUsedRowFund, lastUsedRowEquity, lastUsedRowBond, lastUsedRowAccount = 0;
Excel.Application oXL = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbook oWB = null;
Excel.Worksheet oSheetFund = null;
Excel.Worksheet oSheetEquity = null;
Excel.Worksheet oSheetBond = null;
Excel.Worksheet oSheetAccount = null;
oXL.Visible = false;
oWB = oXL.Workbooks.Open("C:\\extract.xlsm");
oSheetFund = oWB.Sheets["Fund"];
oSheetEquity = oWB.Sheets["Equity"];
oSheetBond = oWB.Sheets["Bond"];
oSheetAccount = oWB.Sheets["Account"];
string[] valuesHeaderFund = {"field1", "field2" };
string[] valuesHeaderEquity = {"field1", "field2"};
string[] valuesHeaderBond = {"field1", "field2"};
string[] valuesHeaderAccount = {"field1", "field2"};
Excel.Range headerFund = oSheetFund.get_Range("A1", "AA1");
Excel.Range headerEquity = oSheetEquity.get_Range("A1", "AE1");
Excel.Range headerBond = oSheetBond.get_Range("A1", "AE1");
Excel.Range headerAccount = oSheetAccount.get_Range("A1", "AE1");
headerFund.Value2 = valuesHeaderFund;
headerEquity.Value2 = valuesHeaderEquity;
headerBond.Value2 = valuesHeaderBond;
headerAccount.Value2 = valuesHeaderAccount;
Excel.Range lastRowFund = oSheetFund.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range lastRowEquity = oSheetEquity.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range lastRowBond = oSheetBond.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Excel.Range lastRowAccount = oSheetAccount.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
lastUsedRowFund = lastRowFund.Row;
lastUsedRowEquity = lastRowEquity.Row;
lastUsedRowBond = lastRowBond.Row;
lastUsedRowAccount = lastRowAccount.Row;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
string[] data = { row.Cells[0].Value.ToString(), row.Cells[1].Value.ToString()};
if (row.Cells[5].Value.ToString() == "FON")
{
lastUsedRowFund += 1;
oSheetFund.get_Range("A" + lastUsedRowFund, "K" + lastUsedRowFund).Value2 = data;
}
else if (row.Cells[5].Value.ToString() == "ACT")
{
lastUsedRowEquity += 1;
oSheetEquity.get_Range("A" + lastUsedRowEquity, "K" + lastUsedRowEquity).Value2 = data;
}
else if (row.Cells[5].Value.ToString() == "OBL")
{
lastUsedRowBond += 1;
oSheetBond.get_Range("A" + lastUsedRowBond, "K" + lastUsedRowBond).Value2 = data;
}
else if (row.Cells[5].Value.ToString() == "ACCOUNT")
{
lastUsedRowAccount += 1;
oSheetAccount.get_Range("A" + lastUsedRowAccount, "K" + lastUsedRowAccount).Value2 = data;
}
}
RunMacro(oXL, new Object[] { "Main" });
oXL.UserControl = false;
//oWB.Close();
//oXL.Quit();
releaseObject(lastRowFund);
releaseObject(lastRowEquity);
releaseObject(lastRowBond);
releaseObject(lastRowAccount);
releaseObject(headerFund);
releaseObject(headerEquity);
releaseObject(headerBond);
releaseObject(headerAccount);
releaseObject(oSheetFund);
releaseObject(oSheetEquity);
releaseObject(oSheetBond);
releaseObject(oSheetAccount);
releaseObject(oWB);
releaseObject(oXL);
private void RunMacro(object oApp, object[] oRunArgs)
{
oApp.GetType().InvokeMember("Run",
System.Reflection.BindingFlags.Default |
System.Reflection.BindingFlags.InvokeMethod,
null, oApp, oRunArgs);
}
private void releaseObject(object obj)
{
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();
}
}
When i click on the toolStripButton5, everything is working. But at the end an "EXCEL.EXE" processus still alive in task manager. When i click again on the button, a new "EXCEL.EXE" is create but when the task is finish, the processus is correctly release.
When i quit my application, the first processus is release.
Can you help me to correctly release the object at the first click.
Regards,
Danny.
Unfortunatelly this is not so simple to quit Excel app, because COM objects of Interoop services still exists in memory. That's why Excel.exe process is still running. Every object can be released using Marshal class. Sample codes:
Marshal.ReleaseComObject(excelSheets); //Worksheet
Marshal.ReleaseComObject(excelSheet); //Sheet
...and so on.
Hope this helps.
Now, it works greatly. When i execute a second extraction with Excel, the first process is correctly release when the new one is created.
I just replace in "releaseObject" System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); by
Marshal.ReleaseComObject(obj);
Maybe because i use "using System.Runtime.InteropServices;" in the header.
Thanks a lot.
Regards

System.Runtime.InteropServices.COMException when I use Microsoft.interop.Excel.dll

I use Microsoft.interop.Excel.dll to convert Excel to .pdf. The core code:
using Microsoft.Office.Interop.Excel;
using ExcelApplicationClass = Microsoft.Office.Interop.Excel.ApplicationClass;
public static bool ExcelToPdf(string sourcePath, string targetPath, out string exmsg)
{
exmsg = string.Empty;
bool result = false;
object missing = Type.Missing;
ExcelApplicationClass applicationClass = null;
Workbook workBook = null;
try
{
applicationClass = new ExcelApplicationClass();
applicationClass.Visible = false;
/* applicationClas*/
workBook = applicationClass.Workbooks.Open(sourcePath);
if (workBook != null)
{
Microsoft.Office.Interop.Excel.Worksheet worksheet = workBook.ActiveSheet as Microsoft.Office.Interop.Excel.Worksheet;
//*** if I annotation the block in this if. the code no error occured.
if (worksheet != null)
{
worksheet.PageSetup.Zoom = false;
worksheet.PageSetup.FitToPagesWide = 1;
}
workBook.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, targetPath, XlFixedFormatQuality.xlQualityMinimum, false, true);
}
result = true;
}
catch (Exception ex)
{
exmsg = ex.Message;
result = false;
}
finally
{
if (workBook != null)
{
workBook.Close(true,missing, missing);
workBook = null;
}
if (applicationClass != null)
{
applicationClass.Quit();
applicationClass = null;
}
}
return result;
}
If I don't set worksheet.PageSetup's property like zoom etc. the program runs well but if I set the property System.Runtime.InteropServices.COMException will occur nine times out of ten. Sometime there is no error.
The error info
The environment information
Microsoft Excel 2013
Windows 10
Every time it has killed the Microsoft Excel progress.

C# not creating the excel file and cannot write in different excel sheets

First of all in my code im opening an excel sheet and reading it into a list. Second of all im closing this excel sheet and creating a new excel sheet:
excel_init("C:\\Users\\oma\\Desktop\\excel2.xlsx"); // this path does NOT exist yet
Next its going to this method:
static void excel_init(String path)
{
appExcel = new Microsoft.Office.Interop.Excel.ApplicationClass();
if (System.IO.File.Exists(path))
{
// then go and load this into excel
newWorkbook_First = appExcel.Workbooks.Open(path, true, true);
objsheet = (_Worksheet)appExcel.ActiveWorkbook.ActiveSheet;
}
else
{
try
{
appExcel = new Microsoft.Office.Interop.Excel.ApplicationClass();
appExcel.Visible = true;
newWorkbook_First = appExcel.Workbooks.Add(1);
objsheet = (Microsoft.Office.Interop.Excel.Worksheet)newWorkbook_First.Sheets[1];
objsheet.Name = ("test");
var newSheet3 = (Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1, XlSheetType.xlWorksheet);
newSheet3.Name = "test2";
var newSheet2 = (Microsoft.Office.Interop.Excel.Worksheet)appExcel.Worksheets.Add(Type.Missing, appExcel.Worksheets[appExcel.Worksheets.Count], 1, XlSheetType.xlWorksheet);
newSheet2.Name = "test3";
}
catch (Exception e)
{
Console.Write("Error");
}
finally
{
}
}
}
It wont create excel2.xlsx on my desktop, why not?
Next in my main I am shouting excel_setValue this way:
excel_setValue("C", "hello", "");
This is the excel_setValue function:
static void excel_setValue(string cellname, string value, string color)
{
objsheet.get_Range(cellname).set_Value(Type.Missing, value);
if (kleur == "red")
{
objsheet.get_Range(cellname).Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.Red);
}
}
How do I add the sheet to this? For exmaple: excel_setValue(cellname, value, color, sheetname)
Finally I do excel_close();
the excel_close function:
static void excel_close()
{
if (appExcel != null)
{
try
{
newWorkbook_First.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(appExcel.ActiveWorkbook.ActiveSheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(appExcel.ActiveWorkbook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(appExcel);
appExcel = null;
objsheet = null;
}
catch (Exception ex)
{
appExcel = null;
Console.WriteLine("Unable to release the Object " + ex.ToString());
}
finally
{
GC.Collect();
}
}
}
It closes and ask me if I wanna save/not-save or cancel it. And it will save # documents with no errors given
I create my Excel like this worked fine for me!
You need to do the folowing in you code before the newWorkbook_First.close(); part:
newWorkbook_First.SaveAs(totalPath);
I hope this will help you solve the problems..
using Excel = Microsoft.Office.Interop.Excel;
internal static bool ExportDGV(DataGridView DGV, List<string> selectedCustomerList, string path, string fileName, string exportName, int exportType, string mailSubject)
{
string totalPath;
//Create an Excel application instance
Excel.Application excelApp = new Excel.Application();
Excel.Workbook excelWorkBook = excelApp.Application.Workbooks.Add();
Excel._Worksheet worksheet = null;
excelApp.Visible = false;
worksheet = excelWorkBook.ActiveSheet;
//set headers
for (int i = 1; i < DataGridView.Columns.Count + 1; i++)
{
worksheet.Cells[1, i] = DGV.Columns[i - 1].HeaderText;
}
createList(worksheet, DGV);
//Create excel with the choosen name
Worksheet sheet1 = excelWorkBook.Worksheets[1];
worksheet.Name = fileName;
totalPath = path + "/" + fileName + ".xlsx";
//if path exist add a number
totalPath = directoryExist(totalPath, path, fileName);
//Save exel and Quit exelApp
excelWorkBook.SaveAs(totalPath);
excelWorkBook.Close();
excelApp.Quit();
}
You can use EpPlus library for excel. It is very easy to use and well documented. You don't need to use COM classes anymore

Categories