I have a DataTable like this:
And I want to write a for loop that shows debit and credit line on its own separate line like this:
Here is my unfinished code:
DataTable dt = new DataTable();
dt.Columns.Add("DEBIT", typeof(string));
dt.Columns.Add("CREDIT", typeof(string));
dt.Columns.Add("AMOUNT", typeof(double));
dt.Rows.Add("Debit1", "Credit1", 10);
dt.Rows.Add("Debit2", "Credit2", 8);
dt.Rows.Add("Debit3", "Credit3", 12);
for (int i=1; i <= dt.Rows.Count; i++)
{
//The first image (datatable) has three debit and credit lines are showing on the same line. Normally the debit line and credit line are showing on its own separate lines.
//With above given datatable I want to construct for loop that shows three debit lines and three credit lines as demonstrated in the second image. In this case it shows 6 lines
}
I would much appreciate it if you could help me with this.
Steps:
Start the loop in reverse (so you can easily insert rows).
Create a new row for the credit and fill it with the relevant data.
Remove the credit data from the original row.
Insert the new column in the position following the original row.
Something like this should do the trick:
for (int i = dt.Rows.Count - 1; i >= 0; i--)
{
var row = dt.Rows[i];
if (!string.IsNullOrEmpty(row["CREDIT"].ToString()))
{
var creditRow = dt.NewRow();
creditRow["CREDIT"] = row["CREDIT"];
creditRow["AMOUNT"] = row["AMOUNT"];
row["CREDIT"] = string.Empty;
dt.Rows.InsertAt(creditRow, i + 1);
}
}
Try it online.
Related
I have the code, that randomly select row from datagrid. But I need to select not randomly, but step by step in the loop.
For example:
Row1
Row2 <- Selected
Row3
It must go in loop Row3 - Row1 - Row2 - Row3 - Row1 ...
If some one can help me with that, I will be very grateful to you.
Here is my code with random:
Random rnd = new Random();
int rowMax = dataSender.Rows.Count;
int row = rnd.Next(0, rowMax);
var arg = new DataGridViewCellEventArgs(0, row);
dataSender_CellClick(dataSender, arg);
dataSender.CurrentCell = dataSender.Rows[row].Cells[0];
All what I want every time I use this code it got to move selected row to next row.
From Row2 to Row3. If there are only 3 rows, then from Row3 return to Row1
Your question is a little unclear, but if you're at say row 2, you then want to move to row 3?
If so, you could do something like this maybe:
Random rnd = new Random();
int rowMax = dataSender.Rows.Count;
int row = rnd.Next(0, rowMax);
for (int i = 0; i < rowMax; i++)
{
var arg = new DataGridViewCellEventArgs(0, row);
dataSender_CellClick(dataSender, arg);
dataSender.CurrentCell = dataSender.Rows[row].Cells[0];
row++;
if (row == rowMax)
{
row = 0;
}
}
So after your code finishes the dealing with the current row, you could increment the row integer by 1 and then check to see if it is equal to the maximum. If it is, then you can set row = 1.
Again, if I've mis-interpreted I'm sorry, but in that case please could you make your question a little clearer
I'm using the following code to parse the XLS file using ExcelDataReader. I would like to exclude the first three rows, first two columns followed by any columns that are after 9.
//create the reader
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
//remove the first 3 rows
DataRowCollection dt = result.Tables[0].Rows;
dt.RemoveAt(0);
dt.RemoveAt(1);
dt.RemoveAt(2);
//exclude the column 1 and2 and any columns after 9
for (int columnNumber = 2; columnNumber < 8; columnNumber++)
{
foreach (DataRow dr in dt)
{
Debug.Log(dr[columnNumber].ToString());
msg += dr[columnNumber].ToString();
}
}
Unfortunately, it does not skip the rows and columns as expected. How do I skip specific columns and rows using excelDataReader?
You are doing the following
dt.RemoveAt(0);
dt.RemoveAt(1);
dt.RemoveAt(2);
When the first line executes, the rows are reindexed with the 1 becoming 0, 2 becoming 1 and so on.
When the second line executes you have now removed the line that was position 2 originally. The rows are again reindexed.
When the third line executes you are then again removing an incorrect row.
As a result, when this process completes, it will have removed the lines that were originally positioned at 0, 2, and 4.
Change the code to remove the correct lines, or skip three lines with linq or a for loop.
Sample using for loop (not tested).
//create the reader
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
DataRowCollection dt = result.Tables[0].Rows;
//ignore the first 3 rows
for(int dataRowCount = 3; dataRowCount < dt.Count; dataRowCount++)
{
//exclude the column 1 and 2 and any columns after 9
for (int columnNumber = 2; columnNumber < 8; columnNumber++)
{
Debug.Log(dr[dataRowCount][columnNumber].ToString());
msg += dr[dataRowCount][columnNumber].ToString();
}
}
I am making a program in Visual Studio where you can read in an excel file in a specific format and where my program converts the data from the excel file in a different format and stores it in a database table.
Below you can find a part of my code where something strange happens
//copy schema into new datatable
DataTable _longDataTable = _library.Clone();
foreach (DataRow drlibrary in _library.Rows)
{
//count number of variables in a row
string check = drlibrary["Check"].ToString();
int varCount = check.Length - check.Replace("{", "").Length;
int count_and = 0;
if (check.Contains("and") || check.Contains("or"))
{
count_and = Regex.Matches(check, "and").Count;
varCount = varCount - count_and;
}
//loop through number of counted variables in order to add rows to long datatable (one row per variable)
for (int i = 1; i <= varCount; i++)
{
var newRow = _longDataTable.NewRow();
newRow.ItemArray = drlibrary.ItemArray;
string j = i.ToString();
//fill variablename with variable number
if (i < 10)
{
newRow["VariableName"] = "Variable0" + j;
}
else
{
newRow["VariableName"] = "Variable" + j;
}
}
}
When varCount equals 1, I get the following error message when running the program after inserting an excel file
The source contains no DataRows.
I don't know why I can't run the for loop with just one iteration. Anyone who can help me?
I'm trying to create an application which import an excel file and read the data from it and it returns n records randomly as winners according to how many winners the user want from that list. so i read the data from excel file and assign it to a datatable called dt. here is a small overview
thats the first 30 records in the excel which will be imported to dt. now if user key in 10(thats the total number of winners), i need to pick 10 winners "RANDOMLY" from this dt, but as you can see some of them are duplicated for example: in column D, the entry named "H" has 6 rows. now if the application chose 1 of them, the others "H" have to be removed but that is after it has been chosen. removing the duplicates before choosing any of them, will lower the chance for them to win better prizes.
Could you try something like,
dt2 = dt.Clone();
dt.AsEnumerable().Select(x => x["IC_NUMBER"].ToString()).Distinct().ToList().ForEach(x =>
{
DataRow[] dr = dt.Select("IC_NUMBER = '" + x + "'");
dt2.ImportRow(dr[0]);
dr.ToList().ForEach(y => dt.Rows.Remove(y));
dt.AcceptChanges();
});
EDIT:
int totalWinners = 10;
Random rnd = new Random();
dt2 = dt.Clone();
for (int i = 1; i <= totalWinners; i++)
{
//Pick random datarow
DataRow selectedWinner = dt.Rows[rnd.Next(0, dt.Rows.Count - 1)];
//Insert it in the second table
dt2.ImportRow(selectedWinner);
//Retrieve other datarows that have same 'IC NUMBER'
var rows = dt.AsEnumerable().Where(x => x["IC NUMBER"].ToString() ==
selectedWinner["IC NUMBER"].ToString());
//Delete all the rows with the selected IC NUMBER in the first table
rows.ToList().ForEach(y => dt.Rows.Remove(y));
dt.AcceptChanges();
}
Hope this helps...
How can I merge DataTable objects ignoring the first row?
The datatable I need to merge with the one I've got comes from a parsed CSV file and its first row (sometimes) still contains headers, which are obviously not supposed to end up in the resulting table...
DataTable.Merge method does not seem to offer such an option. What's the best way to do that? Just removing the first row beforehand? But that affects (alters) the "original", and what if I wanted it to stay as it was. Removing and reinserting after the merge? Smells like "clever coding". Is there really no better way?
Editing my previous
I wrote code on similar lines and ended up with all rows of dt1 intact and dt2 containing only row 2 &3 of from dt1
var dt1 = new DataTable("Test");
dt1.Columns.Add("id", typeof(int));
dt1.Columns.Add("name", typeof(string));
var dt2 = new DataTable("Test");
dt2.Columns.Add("id", typeof(int));
dt2.Columns.Add("name", typeof(string));
dt1.Rows.Add(1, "Apple"); dt1.Rows.Add(2, "Oranges");
dt1.Rows.Add(3, "Grapes");
dt1.AcceptChanges();
dt1.Rows[0].Delete();
dt2.Merge(dt1);
dt2.AcceptChanges();
dt1.RejectChanges();
Let me know if you find it acceptable.
Vijay
You could go through the rows separately and merge them into the table, something like
public static class DataTableExtensions
{
public static void MergeRange(this DataTable dest, DataTable table, int startIndex, int length)
{
List<string> matchingColumns = new List<string>();
for (int i = 0; i < table.Columns.Count; i++)
{
// Only copy columns with the same name and type
string columnName = table.Columns[i].ColumnName;
if (dest.Columns.Contains(columnName))
{
if (dest.Columns[columnName].DataType == table.Columns[columnName].DataType)
{
matchingColumns.Add(columnName);
}
}
}
for (int i = 0; i < length; i++)
{
int row = i + startIndex;
DataRow destRow = dest.NewRow();
foreach (string column in matchingColumns)
{
destRow[column] = table.Rows[row][column];
}
dest.Rows.Add(destRow);
}
}
}