Index out of range error; Here but not There? - c#

I have a winform app that fills a lot of its dropdomn fields fram a maintenance table at runtime. Each Form has a Private void FillMaintFields()
I have run into a strange error where setting the column visibility on 1 form works but on another gives me an index out of range error!
Here is the abriged method on the offending form -->
private void FillMaintFields()
{
var myMCPTableMaint = new TableMaint();
// Index 27 is Diabetic Teaching Topics
var myDataSet = myMCPTableMaint.GetMaintItem(27);
var myDataTable = myDataSet.Tables[0];
// Diabetic TeachingTopics dropdown
chkcboDiabeticTeachingTopics.Properties.DataSource = myDataTable;
chkcboDiabeticTeachingTopics.Properties.DisplayMember = "ItemDescription";
chkcboDiabeticTeachingTopics.Properties.ValueMember = "ItemID";
// Index 26 is Diabetic Teaching
myDataSet = myMCPTableMaint.GetMaintItem(26);
myDataTable = myDataSet.Tables[0];
lkuDiabeticTeaching.Properties.DataSource = myDataTable;
lkuDiabeticTeaching.Properties.PopulateColumns();
lkuDiabeticTeaching.Properties.DisplayMember = "ItemDescription";
lkuDiabeticTeaching.Properties.ValueMember = "ItemID";
lkuDiabeticTeaching.Properties.Columns[0].Visible = false;
lkuDiabeticTeaching.Properties.Columns[1].Visible = false;
lkuDiabeticTeaching.Properties.Columns[3].Visible = false;
lkuDiabeticTeaching.Properties.Columns[4].Visible = false;
}
Now here is the working function on a sister form -->
private void FillMaintFields()
{
var myMCPTableMaint = new TableMaint();
// Index 4 is Minimum Contact Schedule
var myDataSet = myMCPTableMaint.GetMaintItem(4);
var myDataTable = myDataSet.Tables[0];
lkuMinContactSchedule.Properties.DataSource = myDataTable;
lkuMinContactSchedule.Properties.PopulateColumns();
lkuMinContactSchedule.Properties.DisplayMember = "ItemDescription";
lkuMinContactSchedule.Properties.ValueMember = "ItemID";
lkuMinContactSchedule.Properties.Columns[0].Visible = false;
lkuMinContactSchedule.Properties.Columns[1].Visible = false;
lkuMinContactSchedule.Properties.Columns[3].Visible = false;
lkuMinContactSchedule.Properties.Columns[4].Visible = false;
// Index 5 is Release of Information Updated Annually
myDataSet = myMCPTableMaint.GetMaintItem(5);
myDataTable = myDataSet.Tables[0];
lkuReleaseInfoUpdateAnnually.Properties.DataSource = myDataTable;
lkuReleaseInfoUpdateAnnually.Properties.PopulateColumns();
lkuReleaseInfoUpdateAnnually.Properties.DisplayMember = "ItemDescription";
lkuReleaseInfoUpdateAnnually.Properties.ValueMember = "ItemID";
lkuReleaseInfoUpdateAnnually.Properties.Columns[0].Visible = false;
lkuReleaseInfoUpdateAnnually.Properties.Columns[1].Visible = false;
lkuReleaseInfoUpdateAnnually.Properties.Columns[3].Visible = false;
lkuReleaseInfoUpdateAnnually.Properties.Columns[4].Visible = false;}
They are all using the same method in the DAL and accessing the EXACT same table which has a structure of -->
|ItemID | CategoryID | ItemDescription | OrderID | Active|
I am at a loss here as to why it would work in 1 spot and not another. If I comment out the Columns[] portion in the offending Form it returns the correct data with NO errors but, of course ALL columns visible.
Ideas? Thanks!
EDIT 1
Based on some comments and concerns:
The error appears on the first line that tries to access the Columns[]. Wherever and whatever column that may be on the offending Form.
If I debug and look at myDataTable it shows the correct columnms and correct data.

Is the error happening on the "lkuReleaseInfoUpdateAnnually" or the "lkuMinContactSchedule"? Which control is that exactly? It seems the error is on the control side of things, seems like your control in the second form doesn't have all the columns you're expecting it to have.
EDIT: You seem to be confusing the Columns in the dataTable with the columns on your control(s). I'm not sure which control you're using, but doing:
lkuReleaseInfoUpdateAnnually.Properties.Columns[0]
does NOT mean you're indexing into the DataTable. You're indexing into the columns of your control, which may or may not be there.

Create a minimal code that still reproduces a problem. Debug that code; or, if that doesn't help, post it here. The above code doesn't really tell us anything: it's too large, too specific to your problem. We don't know how your data looks, we've got to take your word for the table structure – although C# seems to disagree.
All in all, any help anyone could offer is just fuzzy guesswork.

I have some ideas on how to better specify bugs and their origin. Something you should do, is to watch "lkuDiabeticTeaching.Properties.Columns.Count" value, if, it's less than 1 means, you do not have any columns, and probably because no population occurred.

The only thing I can see is that the first set of code is missing a call to PopulateForms() (it is included in the second set). Could that be it?

Well, I figured it out. Kinda. For some reason I need to call lkuDiabeticTeaching.Properties.ForceInitialize(); after setting the data source on the offending form.
I can only guess that because I have nested forms that somehow this was trying to fire before the control was initialized.
It now looks like this -->
// Index 26 is Diabetic Teaching
harDataSet = myHARTableMaint.GetMaintItem(26);
harDataTable = harDataSet.Tables[0];
lkuDiabeticTeaching.Properties.DataSource = harDataTable;
lkuDiabeticTeaching.Properties.ForceInitialize();
lkuDiabeticTeaching.Properties.PopulateColumns();
lkuDiabeticTeaching.Properties.DisplayMember = "ItemDescription";
lkuDiabeticTeaching.Properties.ValueMember = "ItemID";
if(lkuDiabeticTeaching.Properties.Columns.Count > 0)
{
lkuDiabeticTeaching.Properties.Columns[0].Visible = false;
lkuDiabeticTeaching.Properties.Columns[1].Visible = false;
lkuDiabeticTeaching.Properties.Columns[3].Visible = false;
lkuDiabeticTeaching.Properties.Columns[4].Visible = false;
}
Thanks to all who gave of there time.

Related

C# Nested Tables in Word

I'm trying to design a table that has 3 additional tables in the last cell. Like this.
I've managed to get the first nested table into row 4, but my second nested table is going into cell(1,1) of the first table.
var wordApplication = new Word.Application();
wordApplication.Visible = true;
var wordDocument = wordApplication.Documents.Add();
var docRange = wordDocument.Range();
docRange.Tables.Add(docRange, 4, 1);
var mainTable = wordDocument.Tables[1];
mainTable.set_Style("Table Grid");
mainTable.Borders.Enable = 0;
mainTable.PreferredWidthType = Word.WdPreferredWidthType.wdPreferredWidthPercent;
mainTable.PreferredWidth = 100;
docRange.Collapse(Word.WdCollapseDirection.wdCollapseStart);
var phoneRange = mainTable.Cell(4, 1).Range;
phoneRange.Collapse(Word.WdCollapseDirection.wdCollapseStart);
phoneRange.Tables.Add(phoneRange, 3, 2);
var phoneTable = mainTable.Cell(4, 1).Tables[1];
phoneTable.set_Style("Table Grid");
phoneTable.Borders.Enable = 0;
phoneTable.AutoFitBehavior(Word.WdAutoFitBehavior.wdAutoFitContent);
phoneTable.Rows.RelativeHorizontalPosition = Word.WdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin;
phoneRange.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
I've tried collapsing the range, adding in a paragraph then collapsing the range again. No luck. I found this post and many similar ones, but I must be missing something.
Thanks for your time.
It usually helps in situation like these to add a line in your code: phoneRange.Select(); and having code execution end with that. Take a look at where the Range actually is. Now you can test using the keyboard where the Range needs to be in order to insert the next table successfully.
Since you say phoneRange selects outside the third row, rather than working with phoneRange try setting a new Range object to phoneTable.Range then collapse it to its end-point.

Iterate through MySql database using C# displaying rows in textbox's foreach or while loop

I'm having a little trouble with my application, I have a Database connected and have already displays the values from the first row in the database, however I need to have the database iterate through each row and display them accordingly replacing what was previously there and ideally being delayed by a timer
I thought this was the correct way of going about it however it doesn't seem right as now it doesn't display anything and gives me a System.NullReferenceException. I have tried to solve the issue but seems to be having no luck. If you could recommend something to read, that would be greatly helpful just can't see a lot on the internet for my specific problem
Any help will be great first time posting on here so sorry if things are in the wrong format.
private void FillInTextFields(DataTable table, int ind)
{
foreach(DataRow dr in table.Rows)
{
foreach(var item in dataRow.ItemArray)
{
dataRow = table.Rows[ind];
txtNHSNumber.Text = dataRow.ItemArray.GetValue(0).ToString();
txtFirstName.Text = dataRow.ItemArray.GetValue(1).ToString();
txtLastName.Text = dataRow.ItemArray.GetValue(2).ToString();
txtTimeDate.Text = dataRow.ItemArray.GetValue(3).ToString();
txtHeartRate.Text = dataRow.ItemArray.GetValue(4).ToString();
txtTemp.Text = dataRow.ItemArray.GetValue(5).ToString();
txtReps.Text = dataRow.ItemArray.GetValue(6).ToString();
txtDia.Text = dataRow.ItemArray.GetValue(7).ToString();
txtSys.Text = dataRow.ItemArray.GetValue(8).ToString();
}
}
}
foreach(var item in dataRow.ItemArray)
should be:
foreach(var item in dr.ItemArray)
can put a sleep at the end of the loop to delay before going back to the top.
It seems you have a few issues. First, your inner loop doesn't seem to be necessary. Second, the outer loop is going through all the rows, even though you're specifically passing the row index into your method. Finally, it seems you're using your "dataRow" variable before it's assigned, although I'd have to see more code to be sure. Consider this:
private void FillInTextFields(DataTable table, int ind)
{
dataRow = table.Rows[ind];
txtNHSNumber.Text = dataRow.ItemArray.GetValue(0).ToString();
txtFirstName.Text = dataRow.ItemArray.GetValue(1).ToString();
txtLastName.Text = dataRow.ItemArray.GetValue(2).ToString();
txtTimeDate.Text = dataRow.ItemArray.GetValue(3).ToString();
txtHeartRate.Text = dataRow.ItemArray.GetValue(4).ToString();
txtTemp.Text = dataRow.ItemArray.GetValue(5).ToString();
txtReps.Text = dataRow.ItemArray.GetValue(6).ToString();
txtDia.Text = dataRow.ItemArray.GetValue(7).ToString();
txtSys.Text = dataRow.ItemArray.GetValue(8).ToString();
}
You'll just need to call this method with the particular index you want to display.
You can also remove the ItemArray.GetValue stuff, and just go with this:
private void FillInTextFields(DataTable table, int ind)
{
dataRow = table.Rows[ind];
txtNHSNumber.Text = dataRow[0].ToString();
txtFirstName.Text = dataRow[1].ToString();
txtLastName.Text = dataRow[2].ToString();
txtTimeDate.Text = dataRow[3].ToString();
txtHeartRate.Text = dataRow[4].ToString();
txtTemp.Text = dataRow[5].ToString();
txtReps.Text = dataRow[6].ToString();
txtDia.Text = dataRow[7].ToString();
txtSys.Text = dataRow[8].ToString();
}
Not sure why you are passing int ind in this method it's not needed.
private void FillInTextFields(DataTable table)
{
txtNHSNumber.Text = table.Rows[0].ItemArray[0];
txtFirstName.Text = table.Rows[0].ItemArray[1];
txtLastName.Text = table.Rows[0].ItemArray[2];
txtTimeDate.Text = table.Rows[0].ItemArray[3];
txtHeartRate.Text = table.Rows[0].ItemArray[4];
txtTemp.Text = table.Rows[0].ItemArray[5];
txtReps.Text = table.Rows[0].ItemArray[6];
txtDia.Text = table.Rows[0].ItemArray[7];
txtSys.Text = table.Rows[0].ItemArray[8];
}

DataView.Count() returns more than one value

I'm kinda new to all this so I'll try to be as specific as possible..
I'm trying to create a button that'll display two dates in another form. So I've written this:
DataView dv = new DataView(dataComercioDataSet.Comex);
dv.Sort = "Id";
int ixe = dv.Find(idTextBox.Text);
DateTime embarque = Convert.ToDateTime(dv[ixe]["FechaEmbarque"]);
otherForm.fechaEmbarqueDateTimePicker.Value = embarque;
DateTime vencimiento = Convert.ToDateTime(dv[ixe]["FechaVencimiento"]);
otherForm.fechaVencimientoDateTimePicker.Value = vencimiento;
otherForm.idBox1.Text = dv[ixe]["Id"].ToString();
this.comexTableAdapter.FillBy3(this.dataComercioDataSet.Comex, c41TextBox.Text);
Now, when I click the button it catches an exception showing that it's a DBNull object. So I decide to test it by adding this:
if (dv.Count == 1)
{
MessageBox.Show("1");
}
if (dv.Count == 0) ;
{
MessageBox.Show("0");
}
And it shows both! Since the exception states that it's DBNull I reckon dv.find must be returning 0, so I figure this:
if (ixe == 0)
{
ixe = 1;
DateTime embarque = Convert.ToDateTime(dv[ixe]["FechaEmbarque"]);
otherForm.fechaEmbarqueDateTimePicker.Value = embarque;
DateTime vencimiento = Convert.ToDateTime(dv[ixe]["FechaVencimiento"]);
otherForm.fechaVencimientoDateTimePicker.Value = vencimiento;
otherForm.idBox1.Text = dv[ixe]["Id"].ToString();
this.comexTableAdapter.FillBy3(this.dataComercioDataSet.Comex, c41TextBox.Text);
}
But when I do this, the exception is that index 1 is either negative or superior than row count (it's in spanish, I don't know if that's the actual translation)
Anyway, I think i'm not quite getting how DataView.Find() actually indexes the result, i mean, is row 1 = 1 or 0 ?
Thanks in advance!
Managed to work around this issue, somehow changing
DataView dv = new DataView(dataComercioDataSet.Comex);
to
DataView dv = new DataView();
dv = dataComercioDataSet.Comex.AsDataView();
solved the problem, not sure why though...

Hiding subtotals in pivot table in epplus

I'm using EPPLUS to generate my pivot table (see this SO post). I have the following code
//group by fields
foreach (string row in _GroupByColumns)
{
ExcelPivotTableField field = pivotTable.Fields[row];
//field formating
field.Sort = eSortType.Ascending;
field.Outline = false;
field.Compact = false;
field.ShowAll = false;
field.SubtotalTop = false; //doesn't work, subtotals still there when excel is opened
//doesn't work, will result in "unreadable content" error when Excel is opened
//field.SubTotalFunctions = eSubTotalFunctions.None;
//add it to the pivot
pivotTable.RowFields.Add(field);
}
_GroupByColumns is a List<string> that contains my group by columns.
I thought field.SubtotalTop = false; would hide subtotals. It doesn't. field.SubTotalFunctions = eSubTotalFunctions.None; results in "invalid data" error when I open my Excel. What else can I try?
I know this is an old question, but I'm adding this answer in case anybody Googles here.
You need to set the SubTotalFunctions property after adding the field to the RowFields collection. This is because adding it to the collection changes the XML node that SubTotalFunctions makes adjustments to. This will work...
ExcelPivotTableField field = pivotTable.Fields[row];
pivotTable.RowFields.Add(field);//<-- ADD IT FIRST
//field formating
field.Sort = eSortType.Ascending;
field.Outline = false;
field.Compact = false;
field.ShowAll = false;
field.SubtotalTop = false;
field.SubTotalFunctions = eSubTotalFunctions.None;//<-- THIS WILL WORK NOW

BindindSource Filter does not work

Please see the following code on a Winform Load method:
List<CustomersDTO> res = new List<CustomersDTO>();
res = _CustomerBO.GetCustomers();
customerBindingSource.DataSource = res;
customerDataGridView.DataSource = this.customerBindingSource;
customerBindingNavigator.BindingSource = this.customerBindingSource;
Now I want to filter on Searchbutton but I am not able to see filtered record on screen.
customerBindingSource.Filter = "Active = false";
I am missing something.. I did reasearch. Can anybody give me exact code example? I read about implementing IBindingList but not sure how to do that with my BindingSource..
Can anyone help?
You don't have to implement IBindingList. You can construct a BindingList as the DataSource of your customerBindingSource. Like This:
customerBindingSource.DataSource = new BindingList<CustomersDTO>(res);

Categories

Resources