I have a DataGridView and I want to save its content to a CSV file. Then when I run the program again it loads the data from the CSV file to the gridview.
I have this code to save to CSV file:
private void button1_Click(object sender, EventArgs e)
{
FileInfo todel = new FileInfo(#"c:\dd\GB STOCK.csv");
todel.Delete();
int cols;
//open file
StreamWriter wr = new StreamWriter(#"c:\dd\GB STOCK.csv");
//determine the number of columns and write columns to file
cols = dataGridView1.Columns.Count;
for (int i = 0; i < cols ; i++)
{
wr.Write(dataGridView1.Columns[i].Name.ToString().ToUpper() + ",");
}
wr.WriteLine();
//write rows to excel file
for (int i = 0; i < (dataGridView1.Rows.Count - 1); i++)
{
for (int j = 0; j < cols; j++)
{
if (dataGridView1.Rows[i].Cells[j].Value != null)
{
wr.Write(dataGridView1.Rows[i].Cells[j].Value + ",");
}
else
{
wr.Write(",");
}
}
wr.WriteLine();
}
//close file
wr.Close();
}
And this code to load from the csv to the gridview:
private void Form1_Load(object sender, EventArgs e)
{
string rowValue;
string[] cellValue;
if (System.IO.File.Exists(#"C:\dd\GB STOCK.csv"))
{
System.IO.StreamReader streamReader = new StreamReader(#"C:\dd\GB STOCK.csv");
// Reading header
rowValue = streamReader.ReadLine();
cellValue = rowValue.Split(',');
for (int i = 0; i <= cellValue.Count() - 1; i++)
{
DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
column.Name = cellValue[i];
column.HeaderText = cellValue[i];
dataGridView1.Columns.Add(column);
}
// Reading content
while (streamReader.Peek() != -1)
{
rowValue = streamReader.ReadLine();
cellValue = rowValue.Split(',');
dataGridView1.Rows.Add(cellValue);
}
streamReader.Close();
}
else
{
MessageBox.Show("No File is Selected");
}
}
now the problem is that whenever I save and load the gridview it adds one extra column (without header) every time.
Could anybody tell me what is the wrong with this code?
When you save you are ending the line with a comma. So when the file gets read back in it thinks there is an extra (empty) value on the end. Try:
rowValue.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
While Saving the Data grid values to CSV, Check the Count of Grid view Column (How much its coming.? and How much column is actually.?) In Your button1_Click.
Carefully debug your code.
Have you tried Something like this in your button1_Click also:
`cols = dataGridView1.Columns.Count - 1;`
Or
for (int i = 0; i < cols - 1; i++)
{
wr.Write(dataGridView1.Columns[i].Name.ToString().ToUpper() + ",");
}
Related
as the Problem in the title says, I am having Problems importing Data from a txt file into a datagridview. I get the error Input Array is longer than the number of columns. Here is what I am using to save my Data from the datagridview into a txt file and what I want to use to Import the data into the datagridview:
private void OpenFile_Click(object sender, EventArgs e)
{
string[] lines = File.ReadAllLines(#"C:\Users\gv9816\source\repos\Liste\UserData.txt");
string[] values;
for (int i = 0; i < lines.Length; i++)
{
values = lines[i].ToString().Split('|');
string[] row = new string[values.Length];
for (int j = 0; j < values.Length; j++)
{
row[j] = values[j].Trim();
}
_table.Rows.Add(row);
}
}
private void SaveFile_Click_1(object sender, EventArgs e)
{
TextWriter writer = new StreamWriter(#"C:\Users\gv9816\source\repos\Liste\UserData.txt");
for (int i = 0; i < _table.Rows.Count - 1; i++)
{
for (int j = 0; j < _table.Columns.Count; j++)
{
writer.Write("\t" + DataGridViewCell.Rows[i].Cells[j].Value.ToString() + "\t");
}
writer.WriteLine("");
}
writer.Close();
MessageBox.Show("Data Exported");
}
Also, here is what I use to create the columns:
private void Form1_Load(object sender, EventArgs e)
{
_table.Columns.Add("First Name", typeof(string));
_table.Columns.Add("Last Name", typeof(string));
_table.Columns.Add("Age", typeof(int));
DataGridViewCell.DataSource = _table;
}
Here is the Output in my UserData.txt file
Hans | Müller | 12 |
Here is what the application Looks like
And this is what is generated into the UserData file
Any help would be appreciated :)
The last | character is the problem, If you can't change the data inside txt file. Just change this line,
values = lines[i].ToString().Split('|');
to this,
values = lines[i].ToString().Split('|').Where(x => !string.IsNullOrEmpty(x)).ToArray();
The follwoing code is used by me to print entires in a datagrid view into text file by converting them into strings! The data grid view has 3 columns(3rd column has several strings) and I want to print each data grid view row as a single line in the text file!
private void button1_Click_1(object sender, EventArgs e) // converting data grid value to single string
{
String file = " " ;
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
for (int j = 0; j < dataGridView2.Rows[i].Cells.Count; j++)
{
if (dataGridView2.Rows[i].Cells[j].Value != null)
{
if (j == 0)
{
file = Environment.NewLine + file + dataGridView2.Rows[i].Cells[j].Value.ToString();
}
else
{
file = file + dataGridView2.Rows[i].Cells[j].Value.ToString();
}
}
}
using (StreamWriter sw = new StreamWriter(#"C:\Users\Desktop\VS\Tfiles\file.txt"))
{
{
sw.Write(file);
}
}
}
}
Though a textfile is created the first 2 columns and the 1st string in the 3rd column are printed on the same line but the other strings of the 3rd column are printed on a new line! how can i get them onto the same line.
eg- let a sample data grid view row be like (aaa) (bbb) (ccc dddd eee) and it must appear in the textfile as aaa bbb ccc dddd eee but from my code it appears like aaa bbb ccc on the sameline, dddd on a new line and eee on another new line! how can i correct this issue?
Instead of relying on j==0, you can append new line outside of inner for loop. Also to put in that many string values you should really use StringBuilder. Try this:
private void button1_Click_1(object sender, EventArgs e) // converting data grid value to single string
{
StringBuilder file = new StringBuilder();
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
for (int j = 0; j < dataGridView2.Rows[i].Cells.Count; j++)
{
var val = dataGridView2.Rows[i].Cells[j].Value;
if (val == null)
continue;//IF NULL GO TO NEXT CELL, MAYBE YOU WANT TO PUT EMPTY SPACE
var s=val.ToString();
file.Append(s.Replace(Environment.NewLine," "));
}
file.AppendLine();//NEXT ROW WILL COME INTO NEXT LINE
}
using (StreamWriter sw = new
StreamWriter(#"C:\Users\Desktop\VS\Tfiles\file.txt"))
{
sw.Write(file.ToString());
}
}
EDIT:- Seems 3rd column contains strings with new line so we can remove the new line from string before putting to file:
var s = val.ToString();
file.Append(s.Replace(Environment.NewLine, " "));
Try this:
for (int i = 0; i < dataGridView2.Rows.Count; i++)
{
for (int j = 0; j < dataGridView2.Rows[i].Cells.Count; j++)
{
if (dataGridView2.Rows[i].Cells[j].Value != null)
{
file = file + dataGridView2.Rows[i].Cells[j].Value.ToString();
}
}
This is my code but I'm not sure what to put in a certain area (see below) as I keep getting an error there. I am basically loading up a text file and then deleting any values that are repeated and then outputting the updated copy of the text file.
The text file looks like,
5
5
3
2
2
3
My code is
{
public partial class Form1 : Form
{
//Global Variable
int[] Original;
public Form1()
{
InitializeComponent();
}
//Exit Application
private void mnuExit_Click_1(object sender, EventArgs e)
{
this.Close();
}
//Load File
private void mnuLoad_Click_1(object sender, EventArgs e)
{
//Code to Load the Numbers From a File
OpenFileDialog fd = new OpenFileDialog();
//Open the File Dialog and Check If A File Was Selected
if (fd.ShowDialog() == DialogResult.OK)
{
//Open File to Read
StreamReader sr = new StreamReader(fd.OpenFile());
int Records = int.Parse(sr.ReadLine());
//Assign Array Sizes
Original = new int[Records];
//Go Through Text File
for (int i = 0; i < Records; i++)
{
Original[i] = int.Parse(sr.ReadLine());
}
}
}
private void btnOutput_Click(object sender, EventArgs e)
{
//Store Original Array
string Output = "Original \n";
//Output Original Array
for (int i = 0; i < Original.Length; i++)
{
Output = Output + Original[i] + "\n";
}
//Create TempArray
int[] TempArray = new int[Original.Length];
//Set TempArray Equal to Original Array
for (int i = 0; i < Original.Length; i++)
{
TempArray[i] = Original[i];
}
//Current Index
int Counter = 0;
//Loop Through Entire Array
for (int i = 0; i < TempArray.Length; i++)
{
for (int j = i + 1; j < TempArray.Length; j++)
{
//Replace Duplicate Values With '-1'
if (TempArray[i] == TempArray[j])
{
TempArray[j] = -1;
Counter++;
}
}
}
//Set Size of Original Array
Original = new int[Original.Length - Counter];
//Counter = 0;
//Remove -1 Values
//error begins here
for (int i = 0; i < Original.Length; i++)
{
for (int j = i + 1; j < Original.Length; j++)
{
//Set Original Array Equal to TempArray For Values Not Equal To '-1'
if (j != -1)
{
Original[j] = TempArray[j];
//Counter++;
}
}
}
//error ends here
//Final Output -- The New Array
Output = Output + "Original Without Duplicates\n";
for (int i = 0; i < Original.Length; i++)
{
Output = Output + Original[i] + "\n";
}
lblOutput.Text = Output;
}
}
}
I understand your logic, but wer'e all lazy programmers. You could simply use LINQ in order to prevent duplication. Load the array as you did already and use the Distinct method somthing like this:
int[] newArray = Orginal.Distinct().ToArray();
Goodluck.
I have a function which Export my Windows.Form Application DataGridView to CSV.
It works fine, but the problem is that my DataGridView has 2 rows that updates every milliseconds, but the Output to CSV does not, It just output the value after Application close...
public void writeCSV(DataGridView gridIn, string outputFile)
{
//test to see if the DataGridView has any rows
if (gridIn.RowCount > 0)
{
string value = "";
DataGridViewRow dr = new DataGridViewRow();
StreamWriter swOut = new StreamWriter(outputFile);
//write header rows to csv
for (int i = 0; i <= gridIn.Columns.Count - 1; i++)
{
if (i > 0)
{
swOut.Write(",");
}
swOut.Write(gridIn.Columns[i].HeaderText);
}
swOut.WriteLine();
//write DataGridView rows to csv
for (int j = 0; j <= gridIn.Rows.Count - 1; j++)
{
if (j > 0)
{
swOut.WriteLine();
}
dr = gridIn.Rows[j];
for (int i = 0; i <= gridIn.Columns.Count - 1; i++)
{
if (i > 0)
{
swOut.Write(",");
}
value = dr.Cells[i].Value.ToString();
//replace comma's with spaces
value = value.Replace(',', ' ');
//replace embedded newlines with spaces
value = value.Replace(Environment.NewLine, " ");
swOut.Write(value);
}
}
swOut.Close();
}
}
I called the function from the SetDataGridView() function which i use to update the DataGrids Row every seconds, but it still does not update every milliseconds as the DataGrid does.
How do i make this Update the CSV file every millisecond as the DataGridView.Rows itself updates?
Add a TargetUpdated event to DataGrid:
<DataGrid TargetUpdated="DataGrid_TargetUpdated" ...
Then in each DataGrid column definitions set NotifyOnTargetUpdated=True:
<DataGridColumn Binding="{Binding Path=..., NotifyOnTargetUpdated=True,
UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
Then in TargetUpdated handler call writeCSV method:
private void DataGrid_TargetUpdated(object sender, DataTransferEventArgs e)
{
writeCSV(DataGridView,outputFile)
}
I solved it by calling the writeCSV(DataGridView,outputFile) from private void timer_0_Tick(object sender, EventArgs e) which are created automatically whenever a Timer Class has been added to a C# Application...
And, it started updating the CSV everytime the Tick Updates the DataGridView
Change your code from
gridIn.Columns
To
gridIn.HeaderRow.Cells
As gridIn.Columns does not provide data
Final code after replacing is :
public void writeCSV(DataGridView gridIn, string outputFile)
{
//test to see if the DataGridView has any rows
if (gridIn.RowCount > 0)
{
string value = "";
DataGridViewRow dr = new DataGridViewRow();
StreamWriter swOut = new StreamWriter(outputFile);
//write header rows to csv
for (int i = 0; i <= gridIn.HeaderRow.Cells.Count - 1; i++)
{
if (i > 0)
{
swOut.Write(",");
}
swOut.Write(gridIn.HeaderRow.Cells[i].HeaderText);
}
swOut.WriteLine();
//write DataGridView rows to csv
for (int j = 0; j <= gridIn.Rows.Count - 1; j++)
{
if (j > 0)
{
swOut.WriteLine();
}
dr = gridIn.Rows[j];
for (int i = 0; i <= gridIn.HeaderRow.Cells.Count - 1; i++)
{
if (i > 0)
{
swOut.Write(",");
}
value = dr.Cells[i].Value.ToString();
//replace comma's with spaces
value = value.Replace(',', ' ');
//replace embedded newlines with spaces
value = value.Replace(Environment.NewLine, " ");
swOut.Write(value);
}
}
swOut.Close();
}
}
private void open(object sender, EventArgs e)
{
// only works for opening the table
dataGridView1.Rows.Clear();
OpenFileDialog openDialog = new OpenFileDialog();
if (openDialog.ShowDialog() == DialogResult.OK)
{
fileLabel.Text = openDialog.FileName;
// Use File.ReadAllLines, it's easier
string[] lines = File.ReadAllLines(openDialog.FileName);
foreach (string line in lines)
{
var text = line.Split(',', '\n');
dataGridView1.Rows.Add(text);
}
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
dataGridView1.Rows[i].HeaderCell.Value = (i + 1).ToString();
}
}
}
This is currently my code for opening and reading. So I also have the writing code (actually I wrote a text file already) and I want to add in a few more pieces of information somewhere on the form but not on the dataGridView1
Now in my previous version I had the following code added for reading the extra lines of a text file.
int k = 0;
while (k < lines.Length)
{
for (int j = 0; j < twoDTextBox.GetLength(0); j++)
{
for (int i = 0; i < twoDTextBox.GetLength(1); i++)
{
statsBonus[j, i].Text = lines[k];
k++;
}
}
// these lines I would like to add to read in my new file
textBox1.Text = lines[k];
k++;
comboBox1.SelectedItem = lines[k];
k++;
checkBox1.Checked = Convert.ToBoolean(lines[k]);
k++;
}
Before I used to use textboxes but later found out it wasn't really efficient and dynamic.
So now how do I add the bottom lines to my form after reading the DataGridView lines?