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
Related
I have a problem with duplicates words in memory game.
I have a code (bellow) and what I want to duplicate labels and pass it (in random position every time when app is open) to bellow row e.g
Open app first time
| label1 | label2 | label3 | <= first row
| label3 | label2 | label1 | <= second row
Open app second time
| label1 | label2 | label3 | <= first row
| label1 | label3 | label2 | <= second row
private void AssingWordsToSquares()
{
Label label;
int randomNumber;
string path = $"{_currentPath}\\Resources\\Words.txt";
_loadWordsList = File.ReadAllLines(path).ToList();
for (int i = 0; i < tableLayoutPanel1.Controls.Count; i++)
{
if (tableLayoutPanel1.Controls[i] is Label)
{
label = (Label)tableLayoutPanel1.Controls[i];
}
else
continue;
randomNumber = random.Next(0, _loadWordsList.Count);
label.Text = _loadWordsList[randomNumber];
_loadWordsList.RemoveAt(randomNumber);
}
``
So, at the moment, the function you shared is doing 2 things.
1 is to find random words from a dictionary in a file
2 is to place the words in a random order on screen
So you have 2 random operations happening. Remember the golden rule which is 1 function should try and do just 1 thing. It should have just 1 purpose.
So, you could seperate out that functionality to make it clearer.
We could start by creating a function that will generate a random list of words from your dictionary file. Something like this:
List<string> GenerateRandomWords(int numWords)
{
var randomWordList = new List<string>();
var wordList = System.IO.File.ReadAllLines("RandomWords.txt").ToList();
for (int nLoopCnt = 0; nLoopCnt < numWords; nLoopCnt++)
{
var randomNumber = random.Next(0, wordList.Count);
randomWordList.Add(wordList[randomNumber]);
}
return randomWordList;
}
Now you have your random words extracted from the file we need to put them on the screen in a random order. So, we could create another function GenerateRandomPosOrder that takes a TableLayoutPanel and generates a list of columns in a random order. So, each time you run this function is could return 1,2,3 or 1,3,2 or 3,2,1.
private HashSet<int> GenerateRandomPosOrder(TableLayoutPanel table)
{
Thread.Sleep(500);
Random rnd = new Random();
var result = new HashSet<int>();
while (result.Count < table.ColumnCount)
{
var randomNumber = rnd.Next(0, table.ColumnCount);
result.Add(randomNumber);
}
return result;
}
Now we can put these 2 functions together in your AssignWordsToSquares like so.
private void AssignWordsToSquares(TableLayoutPanel table)
{
var wordList = GenerateRandomWords(table.ColumnCount);
// loop around every row in the table
for (int rowCount = 0; rowCount < table.RowCount; rowCount++)
{
// this could return 0,2,1 or 1,0,2 or 1,2,0
var order = GenerateRandomPosOrder(table);
int pos = 0;
foreach (var randomPosition in order)
{
var tableCell = (Label)table.GetControlFromPosition(column: randomPosition, row: rowCount);
tableCell.Text = wordList[pos++];
}
}
}
The above function first gets a list of random words from the dictionary, then for ever row of the TableLayoutPanel it puts the words in a random order.
I have a datatable like that:
column1 column2 column3
a b c
d e f
I want to get index numbers of the cell "e" and i wrote these
int[] indexrowcol = new int[2];
for (int i = 0; i < dt.Columns.Count ; i++)
{
for (int j = 0; j < dt.Rows.Count; j++)
{
if (dt.Rows[i][j] == "e")
{
indexrowcol[0] = j; indexrowcol[1] = i;
}
}
}
How to write the same thing with usin LINQ? thanks.
I don't believe you have your original code implemented correctly to get what you're after. But at least it's more or less clear what you're trying to do. Here's some commented link code that can accomplish it.
var valToSearch = "e";
int[] indexrowcol = dt.AsEnumerable() // allows you to use linq
.SelectMany((row,rix) => // like 'Select', but stacks up listed output
row.ItemArray.Select( // ItemArray gets the row as an array
(col,cix) => new { rix, cix, value = col.ToString() }
)
)
.Where(obj => obj.value == valToSearch)
.Select(obj => new int[] { obj.rix, obj.cix })
.FirstOrDefault();
When I use the above code on the following DataTable, I get the result [1,1], which is the same result I get using your original code when I correct for the i/j reversal that existed at the time of this writing.
var dt = new DataTable();
dt.Columns.Add("Column1");
dt.Columns.Add("Column2");
dt.Columns.Add("Column3");
DataRow rw = dt.NewRow();
rw["Column1"] = "a";
rw["Column2"] = "b";
rw["Column3"] = "c";
dt.Rows.Add(rw);
rw = dt.NewRow();
rw["Column1"] = "d";
rw["Column2"] = "e";
rw["Column3"] = "f";
dt.Rows.Add(rw);
The reason your original code isn't quite right is that you use 'i' for columns and 'j' for rows, but then call dt.Rows[i][j], which is backwards. I highly recommend that your variables can be matched to what they are associated with. This is why I use names such as col, row, cix (column index), and rix to keep things straight.
In that vein, you might want to also output something other than an int[2]. Maybe a class or struct, or even just leave it as an anonymous object (get rid of the 'select' part of my query). Though I don't know your end use case, so I'll leave you alone on that.
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.
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();
}
}
we try to sort the column of my datagridview in C# from the most recent to the other, but i didn't find a solution.
Below the image of my little program
references
my last test it's to use:
for (int i=1; i<dsForecast.Columns.Count; i++)
{
DataColumn col = dsForecast.Columns[i];
dtListDate.Add(DateTime.Parse(col.ColumnName));
}
Dictionary<DateTime, int> dList = new Dictionary<DateTime, int>();
for (int i = 0; i < dtListDate.Count; i++)
dList.Add(dtListDate[i], i);
dtListDate.Sort((a, b) => a.CompareTo(b));
foreach (DataColumn c in dsForecast.Columns)
this.dgwForecast.Columns[c.ColumnName].DisplayIndex = dsForecast.Columns.IndexOf(c);
Can anyone help me to find a solution for this?
i want a result like this,result
I undestrand that the solution is to move the columnn with its contents, but how?
Can someone Help me?