C# Compare 2 strings, sorting, put into array - c#

hi im formulating my question now better.
in the foreach command i get for temp(save variable) values in an array. The values that i save in temp are from the datagridview cells.
in the next step, in the for command, i want to compare 2 strings, the string and the next string, if the fist string is bigger than the second, i want to change their positions. But there is the problem, they dont change positions they even get an empty value, and i cant understand why they get an empty value.
Im thinking that they get an empty value because of the foreach command, the index [i] just stays the same, but if i would put in i = i+1, the command would be out of bound.
Thank you
senc. NIko
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[i].Value == null)
{
//MessageBox.Show("This row is empty");
break;
}
if (row.Cells[i].Value != null)
{
temp = row.Cells[i].Value.ToString();
UnsortArray[i] = temp;
i = i + 1;
}
}
for (int a = 0; a < MaxZeilen; a++)
{
if (i < MaxZeilen)
{
*if (String.Compare(UnsortArray[a], UnsortArray[a + 1]) > 0)
{
UnsortArray[a] = temp;
UnsortArray[a + 1] = temp2;
temp = UnsortArray[a + 1];
temp2 = UnsortArray[a];
}*
}
}
for (int i = 0; i < MaxZeilen; i++)
{
UnsortArray[i] = SortArray[i];
MessageBox.Show(UnsortArray[i]);
}

You're backwards, assigning the array to your temp variables before assigning the temp variables:
UnsortArray[a] = temp;
UnsortArray[a + 1] = temp2;
temp = UnsortArray[a + 1];
temp2 = UnsortArray[a];
Try:
temp = UnsortArray[a + 1];
temp2 = UnsortArray[a];
UnsortArray[a] = temp;
UnsortArray[a + 1] = temp2;
And you've done it again here UnsortArray[i] = SortArray[i];. I think you mean SortArray[i] = UnsortArray[i];

temp = UnsortArray[a + 1];
UnsortArray[a + 1] = UnsortArray[a];
UnsortArray[a] = temp;
instead of
UnsortArray[a] = temp;
UnsortArray[a + 1] = temp2;
temp = UnsortArray[a + 1];
temp2 = UnsortArray[a];

Why using an array and not a List ?
This page tells about sorting lists.

Here is some improvements to your code. You had an error at the top that could cause a infinite loop and just use the Array.Sort method. If you want it to sort differently, add an IComparable interface.
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[i].Value == null)
{
//MessageBox.Show("This row is empty");
i++;
break;
}
else (row.Cells[i].Value != null)
{
UnsortArray[i] = row.Cells[i].Value.ToString();
i++;
}
}
Array.Sort(UnsortArray);
SortArray = UnsortArray;

List<String> itemList = new List<string>();
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[0].Value = null)
{
itemList.Add(row.Cells[0].Value.ToString());
}
}
itemList.Sort();
string[] SortedArray = itemList.ToArray();
for (int j = 0; j < SortedArray.Length; j++)
{
MessageBox.Show(SortedArray[j]);
}
and if this code doesn't work, than add
foreach(string item in itemList)
{
MessageBox.Show(item);
}
after first foreach loop and check the values

Replace it with the following code block
int i= 0;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row != null)
{
temp = row.ToString();
UnsortArray[i] = temp;
i = i + 1;
}
}
for (int a = 0; a < MaxZeilen; a++)
{
if (String.Compare(UnsortArray[a], UnsortArray[a + 1]) > 0)
{
temp = UnsortArray[a + 1];
UnsortArray[a + 1] = UnsortArray[a];
UnsortArray[a] = temp;
}
}
for (int i = 0; i < MaxZeilen; i++)
{
MessageBox.Show(UnsortArray[i]);
}

int MaxArrayCount = 0;
foreach(DataGridViewRow row in dataGridView1.Rows)
{
MaxArrayCount += row.Cells.Count;
}
string[] UnsortArray= new string[MaxArrayCount];
int cnt = 0;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i = 0; i < row.Cells.Count; i++ )
{
if (row.Cells[i].Value != null)
{
temp = row.Cells[i].Value.ToString();
UnsortArray[cnt] = temp;
cnt++;
}
}
}
for (int b = 1; b < UnsortArray.Count; b++)
{
for (int a = 0; a < UnsortArray.Count - 1; a++)
{
if (String.Compare(UnsortArray[a], UnsortArray[a + 1]) > 0)
{
temp = UnsortArray[a + 1];
UnsortArray[a + 1] = UnsortArray[a];
UnsortArray[a] = temp;
}
}
}
for (int i = 0; i < MaxZeilen; i++)
{
MessageBox.Show(UnsortArray[i]);
}

Related

Debug.Log() A 2D array from a custom class to main class

Here's my code.
CustomClass.cs
class ScoreBoard(){
private int m_lastCnt;
public ScoreBoard{
m_lastCnt = 0;
}
public void makeBoard(string history) {
string[] arrPartStr = history.Split(',');
int[] arrPart = new int[arrPartStr.Length];
for (int c = 0; c < arrPart.Length; c++)
{
int temp = 0;
if (arrPartStr[c][0] == 'P') temp = 100;
else if (arrPartStr[c][0] == 'B') temp = 200;
else temp = 300;
if (arrPartStr[c][1] == 'P') temp += 10;
if (arrPartStr[c][2] == 'P') temp += 1;
arrPart[c] = temp;
}
//var strTmp : String = strData;
//strTmp = "311|101|211|211|211|211|211|211|211|211|111|111|111|111|111|111|111|111|111"
//strTmp = strData.replace(/:/g,"");
int[,] arrTmp = new int[6100, 104];
}
}
Main Class i call the void method like this
ScoreBoard sb = ScoreBoard();
string history = "s ,o ,m ,e ,s ,t ,r ,i ,n ,g";
private void Start(){
sb.makeBoard(history);
}
How can i print my 2D array in my console?
I tried doing it like the for(int row){for(int col){}} but its not working i don't know why
Do you mean this?
for (int j = 0; j < arrTmp.GetLength(1); j++)
{
for (int i = 0; i < arrTmp.GetLength(0); i++)
{
var msg = "[" + i.ToString() + ", " + j.ToString() + "] = " + arrTmp[i, j].ToString();
Debug.Log(msg);
}
}
I got it to display:)
CustomClass.cs
int[,] arrTmp = new int[104, 6];
public int[,] GetBoard(){ return arrTmp }
MainClass.cs
int[,] arrayBigRoad = bsb.GetBoard();
for (int j = 0; j < arrTmp.GetLength(1); j++)
{
for (int i = 0; i < arrTmp.GetLength(0); i++)
{
var msg = "[" + i.ToString() + ", " + j.ToString() + "] = " + arrTmp[i, j].ToString();
Debug.Log(msg);
}
}
Thanks though Rodrigo . I'll mark yours as an answer

How do I set the debugger to catch what changed the variable

I am implementing the NEH algorithm following this slide and video:
http://mams.rmit.edu.au/b5oatq61pmjl.pdf
https://www.youtube.com/watch?v=TcBzEyCQBxw
My problem during the test is the variable Sorted_list got changed which cause different results from what I expect:
This the portion where I have the problem but I couldn't know what it changes it(I used breakpoints and watch variable window):
for (int i = 0; i < kmsList.Count; i++)
{
for (int j = 0; j < kmsList[i].Length - 1; j++)
{
/*
*
* HERE Sorted_list GET MODIFIED UNEXPECTEDLY
*/
if (i == 0 && j == 0)
kmsList[0][0] = Sorted_list[0][0];
else if (i == 0)
kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
else if (j == 0)
kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
}
}
Complete implementation:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FINAL_NEH
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("entre the nmbr of jobs : ");
string row = Console.ReadLine();
Console.WriteLine("entre the nmbr of machines : ");
string column = Console.ReadLine();
int job = int.Parse(row.ToString());
int machine = int.Parse(column.ToString());
List<int[]> list = new List<int[]>();
// read the nmbrs and put it in list-----------------------------------------------------
for (int i = 0; i < job; i++)
{
list.Add(new int[machine + 1]);
for (int j = 0; j < machine; j++)
{
list[i][j] = int.Parse(Console.ReadLine());
}
list[i][list[i].Length - 1] = int.Parse((i + 1).ToString()); //Last Elemnt Is Job Number-
}
// show the list----------------------------------------------------------------------------
for (int i = 0; i < job; i++)
{
for (int j = 0; j < machine + 1; j++)
{
Console.Write("\t" + "[" + list[i][j] + "]");
}
Console.WriteLine();
}
// sort the list------------------------------------------------------------------------------
for (int i = 0; i < list.Count; i++)
{
for (int j = i + 1; j < list.Count; j++)
{
int sumI = 0, sumJ = 0;
for (int a = 0; a < list[i].Length - 1; a++)
{
sumI += list[i][a];
}
for (int a = 0; a < list[j].Length - 1; a++)
{
sumJ += list[j][a];
}
if (sumI < sumJ)
{
int[] temp = new int[int.Parse(job.ToString())];
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
Console.Write("\n\n-----------------after sorting ------------------------------------\n\n");
// shaw the list after sorting------------------------------------------
for (int i = 0; i < job; i++)
{
for (int j = 0; j < machine + 1; j++)
{
Console.Write("\t" + "[" + list[i][j] + "]");
}
Console.WriteLine();
}
// clculate the maxpane of the first 2 jobs---------------------------------------
List<int[]> initMaxpane = new List<int[]>();
initMaxpane.Add((int[])list[0].Clone());
initMaxpane.Add((int[])list[1].Clone());
// calculer maxspan of first jobs..............................................
for (int i = 0; i < initMaxpane.Count; i++)
{
for (int j = 0; j < initMaxpane[i].Length - 1; j++)
{
if (j == 0 && i == 0)
initMaxpane[0][0] = list[i][j];
else if (i == 0)
initMaxpane[0][j] = (int)(initMaxpane[0][j - 1] + list[0][j]);
else if (j == 0)
initMaxpane[i][0] = (int)(initMaxpane[i - 1][0] + list[i][0]);
}
}
for (int i = 1; i < initMaxpane.Count; i++)
{
for (int j = 1; j < initMaxpane[i].Length - 1; j++)
{
if ((initMaxpane[i][j - 1] > initMaxpane[i - 1][j]))
initMaxpane[i][j] = (int)(initMaxpane[i][j - 1] + list[i][j]);
else
initMaxpane[i][j] = (int)(initMaxpane[i - 1][j] + list[i][j]);
}
}
int Cmax = initMaxpane[initMaxpane.Count - 1][initMaxpane[initMaxpane.Count - 1].Length - 2];
Console.WriteLine("\n\n-------the maxpane offirst jobs----------");
for (int i = 0; i < initMaxpane.Count; i++)
{
for (int j = 0; j < initMaxpane[i].Length; j++)
{
Console.Write("\t" + "[" + initMaxpane[i][j] + "]");
}
Console.WriteLine();
}
List<int[]> initMaxpane2 = new List<int[]>();
initMaxpane2.Add(list.ElementAt(1));
initMaxpane2.Add(list.ElementAt(0));
// calculer maxspan of first jobs reverse..............................................
for (int i = 0; i < initMaxpane2.Count; i++)
{
for (int j = 0; j < initMaxpane2[i].Length - 1; j++)
{
if (j == 0 && i == 0)
initMaxpane2[0][0] = list[i][j];
else if (i == 0)
initMaxpane2[0][j] = (int)(initMaxpane2[0][j - 1] + list[0][j]);
else if (j == 0)
initMaxpane2[i][0] = (int)(initMaxpane2[i - 1][0] + list[i][0]);
}
}
for (int i = 1; i < initMaxpane2.Count; i++)
{
for (int j = 1; j < initMaxpane2[i].Length - 1; j++)
{
if ((initMaxpane2[i][j - 1] > initMaxpane2[i - 1][j]))
initMaxpane2[i][j] = (int)(initMaxpane2[i][j - 1] + list[i][j]);
else
initMaxpane2[i][j] = (int)(initMaxpane2[i - 1][j] + list[i][j]);
}
}
int Cmax2 = initMaxpane2[initMaxpane2.Count - 1][initMaxpane2[initMaxpane2.Count - 1].Length - 2];
Console.WriteLine("\n\n-------the maxpane of first jobs (reverse)----------");
for (int i = 0; i < initMaxpane2.Count; i++)
{
for (int j = 0; j < initMaxpane2[i].Length; j++)
{
Console.Write("\t" + "[" + initMaxpane2[i][j] + "]");
}
Console.WriteLine();
}
List<int[]> MaxpaneList = new List<int[]>();
if (Cmax > Cmax2)
{
MaxpaneList.Add((int[])list[1].Clone());
MaxpaneList.Add((int[])list[0].Clone());
}
else
{
MaxpaneList.Add((int[])list[0].Clone());
MaxpaneList.Add((int[])list[1].Clone());
}
List<int[]> bestSequenceList = null;
List<int[]> kmsList = null;
List<int[]> Sorted_list = list.ToList();
int bestCma = 0;
//int maxspan = 0;
for (int jo = 2; jo < job; jo++)
{
for (int ins = 0; ins <= MaxpaneList.Count; ins++)
{
MaxpaneList.Insert(ins, list[jo]);
kmsList = MaxpaneList.ToList();
int Cma = 0;
for (int i = 0; i < kmsList.Count; i++)
{
for (int j = 0; j < kmsList[i].Length - 1; j++)
{
/*
*
* HERE Sorted_list GET MODIFIED UNEXPECTEDLY
*/
if (i == 0 && j == 0)
kmsList[0][0] = Sorted_list[0][0];
else if (i == 0)
kmsList[0][j] = kmsList[0][j - 1] + Sorted_list[0][j];
else if (j == 0)
kmsList[i][0] = kmsList[i - 1][0] + Sorted_list[i][0];
}
}
for (int i = 1; i < kmsList.Count; i++)
{
for (int j = 1; j < kmsList[i].Length - 1; j++)
{
if ((kmsList[i][j - 1] > kmsList[i - 1][j]))
kmsList[i][j] = kmsList[i][j - 1] + Sorted_list[i][j];
else
kmsList[i][j] = kmsList[i - 1][j] + Sorted_list[i][j];
}
}
Cma = kmsList[kmsList.Count - 1][kmsList[kmsList.Count - 1].Length - 2];
Console.WriteLine("\n\n\n------- the maxpane sequence ----------");
for (int i = 0; i < MaxpaneList.Count; i++)
{
for (int j = 0; j < MaxpaneList[i].Length; j++)
{
Console.Write("\t" + "[" + MaxpaneList[i][j] + "]");
}
Console.WriteLine();
}
Console.WriteLine("MAX : " + Cma + "\n\n\n");
if (ins == 0)
{
bestCma = Cma;
}
if (jo == 2 && ins == 0)
{
bestSequenceList = MaxpaneList.ToList();
bestCma = Cma;
}
else
{
if (bestCma > Cma)
{
bestSequenceList = MaxpaneList.ToList();
bestCma = Cma;
}
}
MaxpaneList.RemoveAt(ins);
}
MaxpaneList = bestSequenceList.ToList();
}
Console.ReadLine();
}
}
}
The issue lies in the following code (snippet):
List<int[]> Sorted_list = list.ToList();
ToList will create a new list, but because in this case int[] is a reference type then the new list will contain references to the same arrays as the original list.
Updating a value (of an array) referenced in the new list will also affect the equivalent value in the original list.
kmsList[0][0] = Sorted_list[0][0];
The solution is to create a real copy of 'list' and its items (in this case int[]):
List<int[]> Sorted_list = list.ConvertAll(myArray => (int[])myArray.Clone());
This piece of code clones all arrays within the list to a new variable Sorted_list.
A useful link that explains the difference between value and reference types is: https://msdn.microsoft.com/en-us/library/t63sy5hs.aspx
Reference Types
A reference type contains a pointer to another memory location that holds the data.
Reference types include the following:
String
All arrays, even if their elements are value types Class
types, such as Form
Delegates
When you create a List<> (or any other container) from another container (as you do when you call list.ToList()) you do not create copies of all of the elements in the container. You create new references to the items in the list that you're copying. In CS parlance it's a shallow copy and not a deep copy.
So, if you do this:
int[] ia = new[] {0, 1, 2, 3, 4};
int[] ib = new[] {5, 6, 7, 8, 9};
List<int[]> la = new List<int[]>() { ia, ib };
List<int[]> lb = la.ToList();
Both lists refer to the same two arrays, and if you change one array like this:
la[1][4] = 10;
Then lb[1][4] will also be 10 because the two lists each contain the same arrays. Copying the list does not copy the elements in the list.

My two dimensional array does not want to accept all my data

I am giving an array a size by what is contained in the text file. So when I look at my array it shows [4,7]. But when I read data into the array it only goes up until [1,6].
Take note that the last name is a position of the data in the array, the other entries then shows a ? sign and a no-entry sign on the right.
What is wrong with the below code?
static void buildArray()
{
int rowCount = 0;
int colCount = 0;
int placeHolder = 0;
double devideNumber = 0;
int tempNumber = 0;
string typeOptimum;
string[] objValue;
string[] constraintValues;
List<string> testNumbers;
List<double> ratioList;
List<double> rhs;
foreach (string item in constraintsList)
{
if (rowCount > 0)
{
colCount++;
}
rowCount++;
}
rowCount = colCount + 1;
colCount = colCount + 4;
string[,] arrayConstraints = new string[8, 9];
//Console.WriteLine("row {0} col {1}", colCount+1, colCount+4);
for (int i = 0; i < rowCount; i++)
{
for (int j = 0; j < colCount; j++)
{
arrayConstraints[i, j] = "0";
}
}
arrayConstraints[0, 0] = "1";
objValue = constraintsList[0].Split(' ');
typeOptimum = objValue[0].ToUpper();
arrayConstraints[0, 1] = (int.Parse(objValue[1]) * -1).ToString();
arrayConstraints[0, 2] = (int.Parse(objValue[2]) * -1).ToString();
for (int i = 1; i < rowCount; i++)
{
constraintValues = constraintsList[i].Split(' ');
arrayConstraints[i, 1] = constraintValues[0];
arrayConstraints[i, 2] = constraintValues[1];
arrayConstraints[i, i + 2] = "1";
arrayConstraints[i, colCount - 1] = constraintValues[3];
}
//for (int i = 0; i < rowCount; i++)
//{
// Console.WriteLine(" ");
// for (int j = 0; j < colCount; j++)
// {
// Console.Write(arrayConstraints[i, j] + " ");
// }
//}
do
{
//Console.WriteLine(testNumbers[entryPosition]);
//Console.WriteLine(arrayConstraints[0,entryPosition+1]);
//Console.WriteLine(entryPosition+1);
testNumbers = new List<string>();
for (int i = 1; i < colCount - 1; i++)
{
testNumbers.Add(arrayConstraints[0, i]);
}
ratioList = new List<double>();
rhs = new List<double>();
for (int i = 1; i < rowCount; i++)
{
ratioList.Add(double.Parse(arrayConstraints[i, entryPosition + 1]));
rhs.Add(double.Parse(arrayConstraints[i, colCount - 1]));
}
placeHolder = findRatioTest(ratioList, rhs);
#region multiplyArray
for (int i = 0; i < rowCount; i++)
{
if (i == placeHolder)
{
devideNumber = double.Parse(arrayConstraints[entryPosition + 1, placeHolder]);
for (int j = 0; j < colCount; j++)
{
tempNumber = int.Parse(arrayConstraints[placeHolder, j]);
arrayConstraints[placeHolder, j] = (tempNumber / devideNumber).ToString();
}
}
else
{
for (int k = 0; k < colCount; k++)
{
arrayConstraints[i, k] = (double.Parse(arrayConstraints[i, k]) - (double.Parse(arrayConstraints[i, entryPosition + 1])) * double.Parse(arrayConstraints[placeHolder, k])).ToString();
}
}
}
#endregion
foreach (string item in arrayConstraints)
{
Console.WriteLine(item);
}
} while (findNumber(typeOptimum, testNumbers) == true);
//while (findNumber(typeOptimum, testNumbers) == true)
//{
// testNumbers.Clear();
// for (int i = 1; i < colCount - 1; i++)
// {
// testNumbers.Add(arrayConstraints[0, i]);
// }
//}
}
static Boolean findNumber(string type, List<string> listNumbers)
{
Boolean found = false;
int tempInt, count = 0;
tempInt = int.Parse(listNumbers[0]);
if (type == "MIN")
{
#region MIN
foreach (string item in listNumbers)
{
count++;
if (int.Parse(item) > 0 || int.Parse(item)> tempInt)
{
entryPosition = count - 1;
tempInt = int.Parse(item);
found = true;
}
}
#endregion
}
else
{
#region MAX
foreach (string item in listNumbers)
{
count++;
if (int.Parse(item) < 0 || int.Parse(item) < tempInt)
{
entryPosition = count - 1;
tempInt = int.Parse(item);
found = true;
}
}
#endregion
}
return (found);
}
static int findRatioTest(List<double> listRatio, List<double> rhs)
{
int placeHolder = 0;
List<double> ratioTest = new List<double>();
int count = 0;
double tempSmall;
int tempPlace = 0;
foreach (double item in listRatio)
{
try
{
ratioTest.Add(rhs[count]/ item);
}
catch (Exception)
{
ratioTest.Add(double.Parse("-1"));
throw;
}
count++;
}
count = 0;
tempSmall = ratioTest[0];
foreach (double item in ratioTest)
{
if (item != 0 && item > 0)
{
if (item < tempSmall)
{
tempSmall = item;
tempPlace = count;
}
}
count++;
}
placeHolder = tempPlace + 1;
ratioTest.Clear();
return (placeHolder);
}

C# How to exclude an int from an array?

So I've got an array of integer. I want to use a loop and exclude integers that makes the equation true. So that would be like
for (int n = 0; n < first9char.Length; n++ ) {
if (first9char[n] == clickValue) {
first9char[n] = first9char[n + 1];
But then it only changes the value that is equal to not changing whole array. So is there any way to do this?
I want to use it in this loop.
if (UserSquareMethod.clickedBoxes[0] == -1) {
MessageBox.Show("You have not selected any box");
} else {
int i = 0;
do {
if (textButtonArray[clickedBox[i]].Text == "" || clickValue == "") {
textButtonArray[clickedBox[i]].Text = clickValue;
textButtonArray[clickedBox[i]].Font = new Font(textButtonArray[clickedBox[i]].Font.FontFamily, 14, FontStyle.Bold);
}
else
{
textButtonArray[clickedBox[i]].Text += "," + clickValue;
textButtonArray[clickedBox[i]].Font = new Font(textButtonArray[clickedBox[i]].Font.FontFamily, 5, FontStyle.Regular);
string[] first9char = textButtonArray[clickedBox[i]].Text.Split(new string[] { "," }, StringSplitOptions.None);
for (int j = 1; j < first9char.Length; j++)
{
for (int k = j - 1; k >= 0; k--)
{
if (first9char[j] == first9char[k])
{
if (clearNumberClicked == true)
{
first9char = Array.FindAll(first9char, x => x != clickValue);
label2.Text = first9char[0];
//int n = 0;
//for (int p = 0; p < first9char.Length; p++)
//{
// if (first9char[p] != clickValue)
// {
// first9char[n] = first9char[p];
// n++;
// label2.Text += "," + first9char[n];
// }
// }
//for (int n = 0; n < first9char.Length; n++ ) {
//if (first9char[n] == clickValue) {
// first9char[n] = first9char[n + 1];
// for ( int p = 0; p < n; p++) {
//}
//}
//}
MessageBox.Show("Clear the number" + first9char[(first9char.Length - 1)] + "and " + clickValue + " " + first9char.Length);
}
else {
first9char[j] = "";
textButtonArray[clickedBox[i]].Text = first9char[0];
MessageBox.Show("You cannot enter the same number again!"+ first9char[j]+j);
for (int m = 1; m < (first9char.Length - 1); m++) {
textButtonArray[clickedBox[i]].Text += ","+ first9char[m];
}
}
}
}
}
if (textButtonArray[clickedBox[i]].Text.Length > 9)
{
textButtonArray[clickedBox[i]].Text = first9char[0] + "," + first9char[1] + "," + first9char[2] + "," + first9char[3] + "," + first9char[4];
MessageBox.Show("You cannot enter more than 5 numbers, please clear the box if you want to enter different number." + textButtonArray[clickedBox[i]].Text.Length);
}
}
i++;
}
while (clickedBox[i] != -1);
}
}
I would use LINQ for this:
first9char = first9char.Where(x => x != clickValue).ToArray();
It just means "pick the items that don't match". If you can't use LINQ for some reason, then just keep another counter, and make sure to only loop to n from there on in:
int n = 0;
for(int i = 0; i < first9char.Length; i++) {
if(first9char[i] != clickValue) {
first9char[n] = first9char[i];
n++;
}
}
Clean and efficient.

DataGridView: Copy complete to clipboard

I have a DataGridView in a .Net application (V4 C# VS2010) & want to copy all the data to the clipboard on the click of a button. No problem -
private void copyToClipboard()
{
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
Problem is that the user might already have some cells, rows etc selected on the DataGrid & I don't really want to change that selection. The above obviously selects everything. I could dataGridView1.ClearSelection(); at the end which is marginally better but still doesn't achieve what's required.
I can save the selected cells:
var mySelectedCells = dataGridView1.SelectedCells;
but how do I get those selected cells reselected on the DataGrid after the copy? Is there an easy way to get the selected cells collection back into the DataGrid? Perhaps there is a better way to get the whole grid copied to the clipboard in the first place without affecting presently selected cells?
I suppose if you just wanted to represent the contents of the cells as text and copy them to the clipboard, tab-delimited, you could do something like:
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = "";
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i=0; i < row.Cells.Count; i++)
{
if(i == (row.Cells.Count - 1))
clipboard_string += row.Cells[i].Value + newline;
else
clipboard_string += row.Cells[i].Value + tab;
}
}
Clipboard.SetText(clipboard_string);
The output seems pretty similar to that of the GetClipboardContent(), but be careful for any DataGridViewImageColumns or any type that isn't implicitly a string.
Edit: Anthony is correct, use StringBuilder to avoid allocating a new string for every concatenation. The new code:
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = new StringBuilder();
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i = 0; i < row.Cells.Count; i++)
{
if (i == (row.Cells.Count - 1))
clipboard_string.Append(row.Cells[i].Value + newline);
else
clipboard_string.Append(row.Cells[i].Value + tab);
}
}
Clipboard.SetText(clipboard_string.ToString());
Here is a version of the VB code in C# with options to copy headers and to only copy selected rows.
private void CopyDataGridViewToClipboard(DataGridView dgv, bool includeHeaders = true, bool allRows = false)
{
// copies the contents of selected/all rows in a data grid view control to clipboard with optional headers
try
{
string s = "";
DataGridViewColumn oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
if (includeHeaders)
{
do
{
s = s + oCurrentCol.HeaderText + "\t";
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
}
while (oCurrentCol != null);
s = s.Substring(0, s.Length - 1);
s = s + Environment.NewLine; //Get rows
}
foreach (DataGridViewRow row in dgv.Rows)
{
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
if (row.Selected || allRows)
{
do
{
if (row.Cells[oCurrentCol.Index].Value != null) s = s + row.Cells[oCurrentCol.Index].Value.ToString();
s = s + "\t";
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
}
while (oCurrentCol != null);
s = s.Substring(0, s.Length - 1);
s = s + Environment.NewLine;
}
}
Clipboard.SetText(s);
}
catch (Exception ex)
{
toolStripStatusLabel2.Text = #"Error: " + ex.Message;
}
}
You might want to include the column headers:
private void copyAllToClipboard()
{
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = new StringBuilder();
int i;
for (i = 0; i < this.Columns.Count - 1; i++)
{
clipboard_string.Append(this.Columns[i].Name);
clipboard_string.Append(tab);
}
clipboard_string.Append(this.Columns[i].Name);
clipboard_string.Append(newline);
foreach (DataGridViewRow row in this.Rows)
{
for ( i = 0; i < row.Cells.Count - 1; i++)
{
clipboard_string.Append(row.Cells[i].Value);
clipboard_string.Append(tab);
}
clipboard_string.Append(row.Cells[i].Value);
clipboard_string.Append(newline);
}
Clipboard.SetText(clipboard_string.ToString());
}
I think below method will exactly do what you want. Just call this method with the DataGridView name at the button click event.
Private Sub CopyDataGridViewToClipboard(ByRef dgv As DataGridView)
Try
Dim s As String = ""
Dim oCurrentCol As DataGridViewColumn 'Get header
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
Do
s &= oCurrentCol.HeaderText & Chr(Keys.Tab)
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
Loop Until oCurrentCol Is Nothing
s = s.Substring(0, s.Length - 1)
s &= Environment.NewLine 'Get rows
For Each row As DataGridViewRow In dgv.Rows
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
Do
If row.Cells(oCurrentCol.Index).Value IsNot Nothing Then
s &= row.Cells(oCurrentCol.Index).Value.ToString
End If
s &= Chr(Keys.Tab)
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
Loop Until oCurrentCol Is Nothing
s = s.Substring(0, s.Length - 1)
s &= Environment.NewLine
Next 'Put to clipboard
Dim o As New DataObject
o.SetText(s)
Clipboard.SetDataObject(o, True)
Catch ex As Exception
ShowError(ex, Me)
End Try
End Sub
DataGridView columns can be visible/invisible and also can be displayed in different order then the order they were created. This code takes care of both:
public static void CopyGridViewToClipboard(DataGridView gvCopy)
{
if (gvCopy == null) return;
StringBuilder s = new StringBuilder();
int offset = gvCopy.ColumnHeadersVisible ? 1 : 0;
int visibleColumnsCount = 0;
//count visible columns and build mapping between each column and it's display position
Dictionary<int, int> indexMapping = new Dictionary<int, int>();
int currIndex = 0;
int lastFoundMinDisplayIndex = -1;
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
//find min DisplayIndex >= currIndex where column is visible
int minDisplayIndex = 100000;
int minDisplayIndexColumn = 100000;
for (int k = 0; k < gvCopy.ColumnCount; k++)
{
if ((gvCopy.Columns[k].Visible) && (gvCopy.Columns[k].DisplayIndex >= currIndex) && (gvCopy.Columns[k].DisplayIndex > lastFoundMinDisplayIndex))
{
if (gvCopy.Columns[k].DisplayIndex < minDisplayIndex)
{
minDisplayIndex = gvCopy.Columns[k].DisplayIndex;
minDisplayIndexColumn = k;
}
}
}
if (minDisplayIndex == 100000) break;
indexMapping.Add(minDisplayIndexColumn, currIndex);
lastFoundMinDisplayIndex = minDisplayIndex;
currIndex++;
}
visibleColumnsCount = currIndex;
//put data in temp array -- required to position columns in display order
string[,] data = new string[gvCopy.RowCount + offset, visibleColumnsCount];
if (gvCopy.ColumnHeadersVisible)
{
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
if (gvCopy.Columns[j].Visible)
{
data[0, indexMapping[j]] = gvCopy.Columns[j].HeaderText;
}
}
}
for (int i = 0; i < gvCopy.RowCount; i++)
{
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
if (gvCopy.Columns[j].Visible)
{
data[i + offset, indexMapping[j]] = gvCopy[j, i].FormattedValue.ToString();
}
}
}
//copy data
for (int i = 0; i < gvCopy.RowCount + offset; i++)
{
for (int j = 0; j < visibleColumnsCount; j++)
{
s.Append(data[i, j]);
s.Append("\t");
}
s.Append("\r\n");
}
Clipboard.SetDataObject(s.ToString());
}
You should change multiselect property of DataGridView. Here is the code:
private void copyToClipboard()
{
dataGridView1.MultiSelect = True;
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}

Categories

Resources