Dynamically create table in C# - c#

I have created a table in code behind file dynamically:
The code for creating this table is like this:
protected void BindGridviewNew(Guid SubscriptionID)
{
pnlreapeter.Visible = true;
gridviewnew.Visible = true;
List<string> plannig = new List<string>();
var s = m.bussinesCollection.BussinesPlanning.GetSingleSubVersionTrueFalse(SubscriptionID);
if (s != null)
{
if (s.T1.Value)
{
plannig.Add("T1");
}
if (s.T2.Value)
{
plannig.Add("T2");
}
if (s.T3.Value)
{
plannig.Add("T3");
}
if (s.T4.Value)
{
plannig.Add("T4");
}
if (s.T5.Value)
{
plannig.Add("T5");
}
if (s.T6.Value)
{
plannig.Add("T6");
}
if (s.T7.Value)
{
plannig.Add("T7");
}
if (s.T8.Value)
{
plannig.Add("T8");
}
if (s.T9.Value)
{
plannig.Add("T9");
}
if (s.T10.Value)
{
plannig.Add("T10");
}
}
DataTable PlanningDate = m.bussinesCollection.BussinesPlanning.GetRowOfPlanningDate(SubscriptionID);
DataTable Percentage = m.bussinesCollection.BussinesPlanning.GetAllStudentsForProgressForDocentNew(SubscriptionID);
DataTable dt = new DataTable();
DataRow newrow;
newrow = dt.NewRow();
DataRow Hiddenfield;
Hiddenfield = dt.NewRow();
DataRow percentage;
percentage = dt.NewRow();
int count = plannig.Count;
for (int j = 0; j < count; j++)
{
dt.Columns.Add(plannig[j], typeof(string));
string pl = plannig[j];
string c = pl.Substring(pl.Length - 1, 1);
int x = Convert.ToInt32(c);
DataRow dr = PlanningDate.Rows[0];
DateTime date = DateTime.Parse(dr[x-1].ToString());
newrow[plannig[j]] = date.ToShortDateString();
HiddenField hf = new HiddenField();
Hiddenfield[plannig[j]] = x;
DataRow dr1 = Percentage.Rows[0];
LinkButton link = new LinkButton();
link.Text = dr1[x].ToString();
percentage[plannig[j]] = (System.Web.UI.WebControls.LinkButton) link;
}
dt.Rows.Add(newrow);
dt.Rows.Add(percentage);
// dt.Rows.Add(Hiddenfield);
gridviewnew.DataSource = dt;
gridviewnew.DataBind();
}
The problem here is,as in screen shot I am trying to get link-buttond but the column type is string so that it shows "System.Web.UI.WebControls.LinkButton"
The table I want is like:
T1 | T2 | T3
3/01/2012| 3/03/2012| 3/05/2012
100 | 50 | -
where on clicking on 100 or 50 a new popup should be displayed.
Can any one help me to create this row..?

You can not add a LinkButton to a DataTable. What you should do is bind the DataTable to the GridView, and then manually add a new row to the grid view with the link buttons, I guess in the RowDataBound event, or if there is going to be just one row with link buttons, you can add a footer to the grid view.
Check this link How to programmatically insert a row in a GridView?

Related

Row already belongs to another table error when trying to add rows?

I tried this solution below:
This Row already belongs to another table error when trying to add rows?
I have a Datatable that contains 597 Columns and 20 Rows and are trying to export the data to excel. However, Excel has a maximum column count 256 and so I need to divide the source data into 3 datatables to make the export work.
Below is the code I have written.
var dtmasterdata = data.Tables[name];
for (int j = 1; j < datatableNumberCount; j++)
{
DataTable dt2 = new DataTable();
dt2.TableName = "Master_" + j;
dt2 = dtmasterdata.Copy();
foreach (DataColumn col in dtmasterdata.Columns)
{
DataColumn dtcol = new DataColumn();
dtcol = col;
dt2.Columns.Add(dtcol.ColumnName, dtcol.DataType);
}
for (int k = 0; k < dtmasterdata.Rows.Count; k++)
{
DataRow dr = dt2.NewRow();
dr = dtmasterdata.Rows[k];
dt2.ImportRow(dtmasterdata.Rows[k]);
//dt2.Rows.Add(dr.ItemArray);
}
After that I need to delete few columns like below and I want to create 3 datatables
foreach (DataColumn col in dtmasterdata.Columns)
{
if (j == 1)
{
// condition 1
if (col.Ordinal >= 255)
{
dt2.Columns.RemoveAt(col.Ordinal);
}
}
if (j == 2)
{
// condition 2.
if (col.Ordinal < 255 || col.Ordinal >= 510)
{
dt2.Columns.RemoveAt(col.Ordinal);
}
}
if (j == 3)
{
// condition 3.
if (col.Ordinal <= 510 || col.Ordinal >= 765)
{
dt2.Columns.Add(col);
}
}
}
int worksheetNumber = 1;
string worksheetNameWithNumber = "Master Data";
if (worksheetNumber > 1)
worksheetNameWithNumber = String.Format("{0}_{1}", ws1, worksheetNumber.ToString());
Infragistics.Excel.Worksheet worksheet = wb.Worksheets.Add(worksheetNameWithNumber);
Infragistics.WebUI.UltraWebGrid.UltraWebGrid masterData1 = new Infragistics.WebUI.UltraWebGrid.UltraWebGrid("masterDataGrid");
masterData1.Browser = Infragistics.WebUI.UltraWebGrid.BrowserLevel.UpLevel;
masterData1.DataSource = dt2;
masterData1.DataMember = "Master_" + j;
masterData1.DisplayLayout.HeaderStyleDefault.Font.Bold = true;
masterData1.DisplayLayout.HeaderStyleDefault.Font.Name = "Arial";
masterData1.DisplayLayout.HeaderStyleDefault.Font.Size = FontUnit.Parse("10px");
masterData1.DisplayLayout.HeaderStyleDefault.BackColor = System.Drawing.Color.LightGray;
masterData1.DisplayLayout.RowStyleDefault.Font.Name = "Arial";
masterData1.DisplayLayout.RowStyleDefault.Font.Size = FontUnit.Parse("10px");
Infragistics.WebUI.UltraWebGrid.UltraGridBand masterBand1 = new Infragistics.WebUI.UltraWebGrid.UltraGridBand();
masterData1.Bands.Add(masterBand1);
dgResults.Controls.Add(masterData1);
masterData1.DataBind();
wb.ActiveWorksheet = worksheet;
this.ugWebGridExporter.Export(masterData1, worksheet);
worksheetNumber++;
Your error is because you are trying to add a column to a datatable that already belongs to your source datatable.
dt2.Columns.Add(col);
You can't just iterate through the columns of a datatable and add them to another.
I've a solution to this, which involves cloning the source data and removing what you don't need.
1st, make 3 clones of the datatables you need. Below is an example with me creating my own source table with 596 columns. Notice that clone only takes the data table structure, no data!
var source597ColsTable = new DataTable("Source");
for (var i = 0; i <= 596; i++)
{
source597ColsTable.Columns.Add(new DataColumn("Column" + i , typeof(string)));
}
DataRow newRow = source597ColsTable.NewRow();
source597ColsTable.Rows.Add(newRow);
var cols0To199Table = source597ColsTable.Clone();
var cols200To399Table = source597ColsTable.Clone();
var cols400To596Table = source597ColsTable.Clone();
Next copy all the rows from the source table into the clones. The below is a simple function to do so.
private DataTable CopyRowsFromSource(DataTable sourceTable, DataTable destinationTable)
{
foreach (DataRow row in sourceTable.Rows)
{
destinationTable.Rows.Add(row.ItemArray);
}
return destinationTable;
}
Then call this function for each of your tables.
cols0To199Table = CopyRowsFromSource(source597ColsTable, cols0To199Table);
cols200To399Table = CopyRowsFromSource(source597ColsTable, cols200To399Table);
cols400To596Table = CopyRowsFromSource(source597ColsTable, cols400To596Table);
Finally, remove all the columns from the datatables to give you your split.
private DataTable RemoveColumns(DataTable table, int startCol, int endCol)
{
var colsToRemove = new List<DataColumn>();
for (var colCount = startCol; colCount <= endCol; colCount++)
{
colsToRemove.Add(table.Columns[colCount]);
}
foreach (DataColumn col in colsToRemove)
{
table.Columns.Remove(col);
}
return table;
}
Then call.. again for each cloned table.
cols0To199Table = RemoveColumns(cols0To199Table, 200, 596);
cols200To399Table = RemoveColumns(cols200To399Table, 0, 199);
cols200To399Table = RemoveColumns(cols200To399Table, 200, 396);
cols400To596Table = RemoveColumns(cols400To596Table, 0, 399);
After running this, you will have 3 datatables, columns 0-199, 200-399 and 400-596.
Hope that helps.
I am not sure to have really understood all of your code, but to copy a subset of columns to another datatable there is a very simple method in the DataView class named ToTable where you can list the columns you want in the new table. As added bonus, this method copies also the data in the 20 rows of your original table.
So the only difficult is to list these columns to the method.
You can proceed in this way using linq over the DataColumn collection
string[] firstCols = dtmasterdata.Columns
.Cast<DataColumn>()
.Take(255)
.Select(x => x.ColumnName).ToArray();
string[] secondCols = dtmasterdata.Columns
.Cast<DataColumn>()
.Skip(255)
.Take(255)
.Select(x => x.ColumnName).ToArray();
string[] thirdCols = dtmasterdata.Columns
.Cast<DataColumn>()
.Skip(510)
.Select(x => x.ColumnName).ToArray();
DataTable t1 = dtmasterdata.DefaultView.ToTable("Master_1", false, firstCols);
DataTable t2 = dtmasterdata.DefaultView.ToTable("Master_2", false, secondCols);
DataTable t3 = dtmasterdata.DefaultView.ToTable("Master_3", false, thirdCols);

How to move GridView multiple rows up and down?

I have a devexpress gridview bound to a datatable, right now I move one row up and down, by following some topic post on this blog.
What I need is to move multiple rows up and down.
for example on the button click event I have this
private void btnMoveMotor_Up_Click(object sender, EventArgs e)
{
GridView view = gridView_Motores;
view.GridControl.Focus();
int index = view.FocusedRowHandle;
if (index <= 0) return;
DataRow row1 = view.GetDataRow(index);
DataRow row2 = view.GetDataRow(index - 1);
object idcentg = row1[Codigo];
object idbatg = row1[batg];
object idunig = row1[unig];
object pot_cal = row1[potCalculada];
object pot_trab = row1[potTrabajo];
object idcentg1 = row2[Codigo];
object idbatg1 = row2[batg];
object idunig1 = row2[unig];
object pot_cal1 = row2[potCalculada];
object pot_trab1 = row2[potTrabajo];
row1[Codigo] = idcentg1;
row1[batg] = idbatg1;
row1[unig] = idunig1;
row1[potCalculada] = pot_cal1;
row1[potTrabajo] = pot_trab1;
row2[Codigo] = idcentg;
row2[batg] = idbatg;
row2[unig] = idunig;
row2[potCalculada] = pot_cal;
row2[potTrabajo] = pot_trab;
view.FocusedRowHandle = index - 1;
btnAplicar.Enabled = true;
btnAplicarOrdenMotores.Enabled = true;
}
Thanks!!!
I don't know how you actually move your row since you didn't post this solution, but maybe you just looking for following options to set
gridView1.OptionsSelection.MultiSelect = true;
gridView1.OptionsSelection.MultiSelectMode = DevExpress.XtraGrid.Views.Grid.GridMultiSelectMode.RowSelect;
and your code will work with multiple rows just like for one row.
if (view.SelectedRowsCount == 1)
{
// I do what I post in my question
}
if(view.SelectedRowsCount > 1)
{
int[] pos = new int[view.SelectedRowsCount];
pos = view.GetSelectedRows();//save into an array the selected rows handle
int lastHandle = pos.Last();
DataTable tableAux = new DataTable();
tableAux.Columns.Add("idcentg", typeof(string));
tableAux.Columns.Add("idbatg", typeof(int));
tableAux.Columns.Add("idunig", typeof(int));
tableAux.Columns.Add("potCalculada", typeof(decimal));
tableAux.Columns.Add("potTrabajo", typeof(decimal));
tableAux.Columns.Add("orden", typeof(int));
tableAux.Columns.Add("capinsg", typeof(decimal));
for (int i = 0; i < gridView_Motores.DataRowCount; i++)
{
tableAux.Rows.Add(gridView_Motores.GetRowCellValue(i,"idcentg"), gridView_Motores.GetRowCellValue(i, "idbatg"),
gridView_Motores.GetRowCellValue(i, "idunig"), gridView_Motores.GetRowCellValue(i, "potCalculada"),
gridView_Motores.GetRowCellValue(i, "potTrabajo"), gridView_Motores.GetRowCellValue(i, "orden"),
gridView_Motores.GetRowCellValue(i, "capinsg"));
}
int tag = 1;
int cont = 1;
for (int i = 0; i < pos.Length; i++)
{
if (tag == 1)
{
DataRow selectedRow = tableAux.Rows[pos[i]];
DataRow newRow = tableAux.NewRow();
newRow.ItemArray = selectedRow.ItemArray;
tableAux.Rows.Remove(selectedRow);
tableAux.Rows.InsertAt(newRow, lastHandle + 1);
}
else
{
DataRow selectedRow = tableAux.Rows[pos[i] - cont];
DataRow newRow = tableAux.NewRow();
newRow.ItemArray = selectedRow.ItemArray;
tableAux.Rows.Remove(selectedRow);
tableAux.Rows.InsertAt(newRow, lastHandle + 1);
cont++;
}
tag++;
}
int orden = 1;
foreach (DataRow row in tableAux.Rows)
{
row["orden"] = orden;
orden++;
}
grid_OrdenMotores.DataSource = null;
grid_OrdenMotores.DataSource = tableAux;
}

Reset column increment datagridview

I am trying to update the row increment number in a DataGridView in my WinForms application after deleting a row or rows. I have looked at sources and the all point on how to add the incrementing to a column in DataTable. My DataGridView is bound to my DataTable, and that is bound to a DataSet.
How I created by datatable:
DataColumn itemNumber = new DataColumn();
itemNumber.ColumnName = "ItemNumber";
itemNumber.AutoIncrement = true;
itemNumber.AutoIncrementSeed = 1;
itemNumber.AutoIncrementStep = 1;
DataColumn article = new DataColumn();
article.ColumnName = "Article";
article.ReadOnly = true;
DataColumn description = new DataColumn();
description.ColumnName = "Description";
description.ReadOnly = true;
DataColumn type = new DataColumn();
type.ColumnName = "Type";
type.ReadOnly = true;
//add to datatable
dt.Columns.Add(itemNumber);
dt.Columns.Add(article);
dt.Columns.Add(description);
dt.Columns.Add(type);
Removing a row from the DataGridView
foreach (DataGridViewRow row in dgvView.SelectedRows)
{
dgvView.Rows.RemoveAt(row.Index);
}
If I have 5 rows, and delete one. I would like the increment values to start from the 1,2,3,4 etc...
Can someone point me on how to achieve this?
I can't think of an efficient way to do this, but here are some ideas that may work with small data sets.
Keep up with the values yourself
1) Don't define the column as an AutoIncrement column):
DataColumn itemNumber = new DataColumn();
itemNumber.ColumnName = "ItemNumber";
//itemNumber.AutoIncrement = true;
//itemNumber.AutoIncrementSeed = 1;
//itemNumber.AutoIncrementStep = 1;
2) Handle the DataGridView.RowsAdded and DataGridView.RowsRemoved events and "reset" the values:
private void dgvView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
if (dgvView.Columns.Contains("ItemNumber"))
{
foreach (DataGridViewRow r in dgvView.Rows)
{
r.Cells["ItemNumber"].Value = r.Index + 1;
}
}
}
private void dgvView_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
{
if (dgvView.Columns.Contains("ItemNumber"))
{
foreach (DataGridViewRow r in dgvView.Rows)
{
r.Cells["ItemNumber"].Value = r.Index + 1;
}
}
}
Regenerate the values by rebuilding the DataTable and rebinding to it
1) Define the helper method below:
private DataTable ResetAutoIncrementColumn(DataTable dt, string autoIncrementColumnName)
{
DataTable result = new DataTable();
DataColumn itemNumber = new DataColumn(autoIncrementColumnName);
itemNumber.AutoIncrement = true;
itemNumber.AutoIncrementSeed = 1;
itemNumber.AutoIncrementStep = 1;
result.Columns.Add(itemNumber);
dt.Columns.Remove(autoIncrementColumnName);
result.Merge(dt, true);
return result;
}
2) Call it at the appropriate time (e.g. after a series of deletes as in the original question):
dt = ResetAutoIncrementColumn(dt, "ItemNumber");
dt.Columns["ItemNumber"].SetOrdinal(0);
dgvView.DataSource = dt;
dgvView.Columns["ItemNumber"].DisplayIndex = 0;
If you are just looking for a visual row number
Also, if you are just looking to have a visual row number on the DataGridView (and you don't care about the value being present in the underlying DataTable), you can handle the DataGridView.RowPostPaint event as follows (pulled from https://stackoverflow.com/a/12840794/3085273):
private void dgGrid_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
var grid = sender as DataGridView;
var rowIdx = (e.RowIndex + 1).ToString();
var centerFormat = new StringFormat()
{
// right alignment might actually make more sense for numbers
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
var headerBounds = new Rectangle(e.RowBounds.Left, e.RowBounds.Top, grid.RowHeadersWidth, e.RowBounds.Height);
e.Graphics.DrawString(rowIdx, this.Font, SystemBrushes.ControlText, headerBounds, centerFormat);
}

A data item was not found in the container. The container must either implement IDataItemContainer, or have a property named DataItem

I am trying to bind string array to grid view. While using the given below code showing the error "A data item was not found in the container. The container must either implement IDataItemContainer, or have a property named DataItem." Please help me to find a proper solution. Thank you.
Code:
protected void ddlCircle_SelectedIndexChanged(object sender, EventArgs e)
{
ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter cd;
cd = new ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter();
DataTable dt = new DataTable();
dt = cd.GetAvailableData(ddlCircle.SelectedValue); // Getting details of unassigned site
int x, y; //z;
DataTable dt3 = new DataTable();
dt3 = cd.GetTeam();
y = dt3.Rows.Count;
x = dt.Rows.Count; // counting the unassinged sites
DataTable dt2 = new DataTable();
dt2 = cd.GetAssignTeam(x); //Getting team based on count
string[] arr = new string[dt2.Rows.Count];
int i = 0;
foreach (DataRow r in dt2.Rows)
{
arr[i] = r["Team"].ToString(); // assigning available team to array
i++;
}
string[] strArr = new string[100]; // another array to copy arr values.
i = 0; int j = 0;
while (j <= x)
{
strArr[j]= arr[i] ; // copying the arr[] values into strArr[] based on count.
i++;
j++;
if (i == 3)
{
i = 0;
}
}
GridView2.DataSource = strArr;
GridView2.DataBind(); // error popup here
}
Define a GridView's column such that it binds to the Team column of your DataTable and assign the DataTable directly to the GridView as DataSource. Then DataBind to the DataTable.
Binding Array to DataGrid is just like putting bananas in egg tray. Please you have to bind a source having structure according to datagrid. As suggested by #Konstantin D - Infragistics
Now the gridview showing strArr[j] array values
protected void ddlCircle_SelectedIndexChanged(object sender, EventArgs e)
{
ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter cd;
cd = new ShadingAnalysisDataSetTableAdapters.tbl_CadEngineersTeamTableAdapter();
DataTable dt = new DataTable();
dt = cd.GetAvailableData(ddlCircle.SelectedValue); // Getting details of unassigned site
int x, y; //z;
DataTable dt3 = new DataTable();
dt3 = cd.GetTeam();
y = dt3.Rows.Count;
x = dt.Rows.Count; // counting the unassinged sites
DataTable dt2 = new DataTable();
dt2 = cd.GetAssignTeam(x); //Getting team based on count
string[] arr = new string[dt2.Rows.Count];
int i = 0;
foreach (DataRow r in dt2.Rows)
{
arr[i] = r["Team"].ToString(); // assigning available team to array
i++;
}
string[] strArr = new string[x+1]; // another array to copy arr values.
i = 0; int j = 0;
while (j <= x)
{
strArr[j]= arr[i] ; // copying the arr[] values into strArr[] based on count.
i++;
j++;
if (i == 3)
{
i = 0;
}
}
GridView2.DataSource = strArr;
GridView2.DataBind();
}

Dynamic CheckBoxes in GridView Rows are not showing properly in ASP.NET

I have a gridview in which i am showing values to be checked or unchecked in gridview rows checkboxes..Now i want to these values dynamically in gridview rows but its not going to happen ..All of the checkboxes are coming checked whereas result should be different ..
here is my hardcoded code condition to show the result which is coming fine...
string[] rolesarr = Roles.GetAllRoles();
DataTable dTable = new DataTable();
dTable.Columns.Add("Select", typeof(bool));
dTable.Columns.Add("Username", typeof(string));
Array.ForEach(rolesarr, r => dTable.Columns.Add(r, typeof(bool)));
foreach (MembershipUser u in Membership.GetAllUsers())
{
DataRow dRow = dTable.NewRow();
dRow[0] = false;
dRow[1] = u.UserName;
string[] roles = Roles.GetRolesForUser(u.UserName);
dRow[2] = roles.Contains("Admin") ? true : false;
dRow[3] = roles.Contains("DPAO User") ? true : false;
dRow[4] = roles.Contains("GeneralUser") ? true : false;
dTable.Rows.Add(dRow);
}
GridView1.DataSource = dTable;
GridView1.DataBind();
Now i want to make this condition dynamic for which i have written code..
string[] rolesarr = Roles.GetAllRoles();
DataTable dTable = new DataTable();
dTable.Columns.Add("Select", typeof(bool));
dTable.Columns.Add("Username", typeof(string));
Array.ForEach(rolesarr, r => dTable.Columns.Add(r, typeof(bool)));
foreach (MembershipUser u in Membership.GetAllUsers())
{
DataRow dRow = dTable.NewRow();
dRow[0] = false;
dRow[1] = u.UserName;
string[] roles = Roles.GetRolesForUser(u.UserName);
for (int i = 0; i < roles.Length; i++)
{
string rol = roles[i];
for (int j = 2; j < dTable.Columns.Count; j++)
{
dRow[j] = roles.Contains(rol) ? true : false;
}
}
dTable.Rows.Add(dRow);
}
GridView1.DataSource = dTable;
GridView1.DataBind();
And Here is my RowDatabound event for checkboxes ..
protected void GridView1_RowDataBound1(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
CheckBox c0 = (CheckBox)e.Row.Cells[0].Controls[0];
CheckBox c2 = (CheckBox)e.Row.Cells[2].Controls[0];
CheckBox c3 = (CheckBox)e.Row.Cells[3].Controls[0];
CheckBox c4 = (CheckBox)e.Row.Cells[4].Controls[0];
c0.Enabled = c2.Enabled = c3.Enabled = c4.Enabled = true;
}
}
Please guys help me ..Thanks in advance...
the problem should be the double loops you provided.
According to your hardcoded code, you want to map between roles in the array rolesarr and roles of users, to show which roles is checked for each user.
To set values for data row at indext 2 - 4, you will have two loops, first loop to repeat rolesarr array and second loop to repeat roles array and compare them in the second loop
This is the code I mean:
string[] rolesarr = Roles.GetAllRoles();
DataTable dTable = new DataTable();
dTable.Columns.Add("Select", typeof(bool));
dTable.Columns.Add("Username", typeof(string));
Array.ForEach(rolesarr, r => dTable.Columns.Add(r, typeof(bool)));
foreach (MembershipUser u in Membership.GetAllUsers())
{
DataRow dRow = dTable.NewRow();
dRow[0] = false;
dRow[1] = u.UserName;
string[] roles = Roles.GetRolesForUser(u.UserName);
for (int i = 0; i < rolesarr.Length; i++)
{
for (int j = 0; j < roles.Length; j++)
{
if (rolesarr[i] == roles[j])
{
dRow[i + 2] = true;
break;
}
}
}
dTable.Rows.Add(dRow);
}
GridView1.DataSource = dTable;
GridView1.DataBind();
Please notice that I use data row index as i + 2 (dRow[i + 2]) in the second loop, because your role columns start at index=2, not 0, and the length must equal rolesarr.Length which you use them as role colums.

Categories