Reputation: 23
I think I've read through every post on here and MSDN, but I think I'm a special case since most of the articles and posts don't seem to cover what I'm trying to do.
I'm going through an Excel sheet and pulling out records and passing them off so that they can be converted to different file types. I'm trying to use threads so I don't tie up the UI and everything is fine except for when it comes to updating the progress bar that I have in the form. Below is the class that needs to update the form:
public class ExcelItem : Form1
{
private string inFile { get; set; }
public ExcelItem(string file)
{
inFile = file;
}
public string getExcelData()
{
string result = "";
int numRec = 0;
int recCount = 0;
Excel.Application xlApplication;
Excel.Workbook xlWorkbook;
Excel.Worksheet xlWorksheet;
Excel.Range xlRange;
xlApplication = new Excel.Application();
xlWorkbook = xlApplication.Workbooks.Open(File, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorksheet = (Excel.Worksheet)xlWorkbook.Worksheets.get_Item(2);
xlRange = xlWorksheet.UsedRange;
int rCnt = xlRange.Rows.Count;
int cCnt = xlRange.Columns.Count;
//for (int k = 1; k <= xlWorkbook.Worksheets.Count; k++)
// MessageBox.Show("Found worksheet " + k);
// get the number of records in tne sheet and use numRec to set progress bar max
for (int i = 1; i <= xlRange.Rows.Count; i++)
{
for (int j = 1; j <= xlRange.Columns.Count; j++)
{
if ((((Excel.Range)xlWorksheet.Cells[i, j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() == "Date of Birth"))
{
numRec++;
//code for updating progress bar max would go here
}
}
}
// iterate through records in sheet, use recCount to set progress bar value and return records
for (int i = 1; i <= xlRange.Rows.Count; i++)
{
for (int j = 1; j <= xlRange.Columns.Count; j++)
{
if ((((Excel.Range)xlWorksheet.Cells[i, j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() == "Date of Birth"))
{
result += Environment.NewLine;
recCount++;
// code for updating progress bar value would go here
}
if ((((Excel.Range)xlWorksheet.Cells[i,j]).Value2 != null) && (((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() != ":"))
{
result += (string)((Excel.Range)xlWorksheet.Cells[i, j]).Value2.ToString() + Environment.NewLine;
}
}
}
return result;
}
}
}
Returning the records isn't a problem, just updating things like the progress bar is the headache right now. So far I've tried delegates, backgroundworker, BeginInvoker and threads but can't seem to get anything to work. Thanks in advance for any help.
Upvotes: 1
Views: 490
Reputation: 23
I found another way to approach this using AsyncCallBack located in System.Runtime.Remoting.Messaging which needs to be included. Below is actually what I ended up doing:
AsyncCallBack methods (pbvalue is a private global variable):
public void setPg1InAnotherThread(Int32 val)
{
new Func<Int32>(setPbValue).BeginInvoke(new AsyncCallback(setPbValueCallback), null);
}
private Int32 setPbValue()
{
Int32 result = recCount;
return result;
}
private void setPbValueCallback(IAsyncResult ar)
{
AsyncResult result = (AsyncResult)ar;
Func<Int32> del = (Func<Int32>)result.AsyncDelegate;
try
{
Int32 pbValue = del.EndInvoke(ar);
if (pbValue != 0)
{
Form1 frm1 = (Form1)findOpenForm(typeof(Form1));
if (frm1 != null)
{
frm1.setPbValue(pbValue);
}
}
}
catch { }
}
The only thing left is to get a reference to the main form which I wasn't able to do via file handlers or delegates since I'm a) in a separate thread and b) in a separate class.
private static Form findOpenForm(Type typ)
{
for (int i = 0; i < Application.OpenForms.Count; i++)
{
if (!Application.OpenForms[i].IsDisposed && (Application.OpenForms[i].GetType() == typ))
{
return Application.OpenForms[i];
}
}
return null;
}
With those methods in place, all that is needed is to call setPg1InAnotherThread() with whatever value you need. I'll also probably go back and refactor Int32 to Int16. This isn't the preferred way of doing it and BackGroundWorker or the usual delegate methods should be used when possible, but is working for my situation.
Upvotes: 0