I want to take each row in a datagridview and add it to a string variable that I will then print using a custom PrintDocument class. Everything in my program works, except for getting the data from the datagridview into the string variable. I can't find an example on how to do this. Wouldn't I just use a "foreach(DataRow Row in dataGridView1)..." to loop through the data table and add it to my string variable? Can someone show me an example of this?
Right now, my code looks like this, but it won't compile (getting an error message on the way I'm trying to get the value from the column.row into the string. The error message is "The best overloaded method match for 'System.Windows.Form.DataGridViewRowCollection.This[int]' has some invalid arguments).:
//Loop through the dataGridView1 and add it to the text
//that we want to print
foreach (DataRow row in dataGridView1.Rows)
{
textToPrint = textToPrint + dataGridView1.Rows[row][0].ToString() + "\t" +
dataGridView1.Rows[row][1].ToString() + "\t" +
dataGridView1.Rows[row][2].ToString() + "\t" +
dataGridView1.Rows[row][3].ToString() + "\t";
}
I recommend a more generic method for doing this so you don't have to rewrite it in the future. This will also be independent of how many columns you might have in your DataGridView.
public static string DGVtoString(DataGridView dgv, char delimiter)
{
StringBuilder sb = new StringBuilder();
foreach (DataGridViewRow row in dgv.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
sb.Append(cell.Value);
sb.Append(delimiter);
}
sb.Remove(sb.Length - 1, 1); // Removes the last delimiter
sb.AppendLine();
}
return sb.ToString();
}
Try this
dataGridView.Rows[RowIndex].Cells[ColumnIndex].Value as string
for (int row = 0 ; row < dataGridView1.Rows.Count; row ++)
{
textToPrint = textToPrint +
dataGridView1.Rows[row].Cells[0].Value.ToString() + "\t" +
dataGridView1.Rows[row].Cells[1].Value.ToString() + "\t" +
dataGridView1.Rows[row].Cells[2].Value.ToString() + "\t" +
dataGridView1.Rows[row].Cells[3].Value.ToString() + "\t";
}
Related
I have two string lists:
currentRow = contains the info that the row should have
currentCol = contains the names of the columns that data from currentRow should go in.
each List contains 25(0-24) items, and is ordered in the same way as the dataRow it should be written to.
I am filling the Lists here, from labels and textboxes on a form:
List<string> currentRow = new List<string>();
List<string> currentCol = new List<string>();
foreach (var c in form11.Controls)
{
if (c.GetType() == typeof(TextBox))
{
var str = c.ToString();
var str1 = str.Substring(35);
currentRow.Add(str1);
}
if (c.GetType() == typeof(Label))
{
var str = c.ToString();
var str1 = str.Substring(34);
currentCol.Add(str1);
}
}
I then select the row in the dataTable that needs to be updated from the 3rd item in currentRow, which is a unique identifier.
var updateRow = arraysDt.Select("SERIAL =" + "'" + currentRow.ElementAtOrDefault(2) + "'");
Now i try to update the row from the items in the Lists here:
for (int i = 0; i < currentRow.Count; i++)
{
//MessageBox.Show(currentCol.ElementAtOrDefault(i).ToString() + " " + currentRow.ElementAtOrDefault(i).ToString());
updateRow[0][currentCol.ElementAtOrDefault(i)] = currentRow.ElementAtOrDefault(i);
}
As soon as it gets inside the for loop i throws a "index was out of bounds of the array" error.
As i said, currentCol contains column names and currentRow is the value.
So when it get here i expect it to find the column name and then update it with the value.
updateRow[0][currentCol.ElementAtOrDefault(i)] = currentRow.ElementAtOrDefault(i);
What am i doing wrong?
I have found out the issue:
"SERIAL =" + "'" + currentRow.ElementAtOrDefault(2) + "'"
will give me this:
SERIAL=' XXXXX'
What i need is:
SERIAL='XXXXX'
so to fix it i did:
string SMnum = currentRow.ElementAt(2).ToString().Replace(" ", string.Empty);
string query = string.Format("SERIAL='{0}'", SMnum.Replace(#"'", "''"));
var updateRow = arraysDt.Select(query);
This removes any white space in the string that i am looking for.
I want to remove the last (empty) row of a StringBuilder Object
EDIT: The empty row is from the "AllowUserToAddRows" how can i skip it?
c# Forms application
dataGridView1 on form2
I want Export to CSV (separated by semicolon) [btw. it's just one column]
It Could happen, that a previously created CSV is parsed to the dataGridView again
I use a altered solution from here:
Exporting datagridview to csv file
my code
void SaveDataGridViewToCSV(string filename)
{
var sb = new StringBuilder();
var headers = dataGridView1.Columns.Cast<DataGridViewColumn>();
sb.AppendLine(string.Join(";", headers.Select(column => "" + column.HeaderText + ";").ToArray()));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
sb.AppendLine(string.Join(";", cells.Select(cell => "" + cell.Value + ";").ToArray()));
}
try
{
File.WriteAllText(filename, sb.ToString());
}
catch (Exception exceptionObject)
{
MessageBox.Show(exceptionObject.ToString());
}
}
The sb.ToString looks like this {Coumn;90;90;626;626;;}
The "real" StringBuilder Object as String is: {Coumn;\r\n90;\r\n90;\r\n626;\r\n626;\r\n;}
I want to remove the empty last row.
I tried to parse the stringbuilder to a string, and then remove last semicolon
but with no success (i have problem with the End Of Line.)
string s = sb.ToString();
while (s.EndsWith(";\r\n;") == true)
{
s.Substring(0, s.Length - 5);
}
I tried to remove last element of array, but StingBuilder is no array
I'm stuck.
As i found out the empty set is always exported to the csv.
It's from the ability that the user can input data to the dataGridView, and there is always a empty, active row.
if i disable dataGridView1.AllowUserToAddRows the empty row for userinput is not within the stringbuilder set of data.
void SaveDataGridViewToCSV(string filename)
{
var sb = new StringBuilder();
//SOLUTION disable AllowUserInput to avoid empty set saved to CSV
dataGridView1.AllowUserToAddRows = false;
var headers = dataGridView1.Columns.Cast<DataGridViewColumn>();
sb.AppendLine(string.Join(";", headers.Select(column => "" + column.HeaderText + ";").ToArray()));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
sb.AppendLine(string.Join(";", cells.Select(cell => "" + cell.Value + ";").ToArray()));
}
try
{
File.WriteAllText(filename, sb.ToString());
}
catch (Exception exceptionObject)
{
MessageBox.Show(exceptionObject.ToString());
}
}
thanks for help!
Can anybody help me understand what these lines of codes really means...i understand it but not exactly...i mean what foreach is exactly doing here???
if (dt.Rows.Count > 0)
{
//GridView1.Visible = true;
Gridview1.DataSource = dt;
Gridview1.DataBind();
StringBuilder sb = new StringBuilder();
foreach (DataColumn col in dt.Columns)
{
sb.Append(col.ColumnName + ",");
}
sb.Remove(sb.Length - 1, 1);
sb.Append(Environment.NewLine);
foreach (DataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
sb.Append(row[i].ToString() + ",");
}
sb.Append(Environment.NewLine);
}
Response.ClearHeaders();
Response.AppendHeader("Content-Disposition", "attachment; filename=CDR OF " + TextBox1.Text + ".csv");
Response.AppendHeader("Content-Length", sb.Length.ToString());
Response.ContentType = "text/csv";
Response.Write(sb.ToString());
Response.Flush();
Response.End();
}
else
{
//GridView1.Visible = false;
Show("No CDR Found!");
}
And can we use StringWriter or string in place of StringBuilder ???
The first loop lists all your column names with a comma:
colname1,colname2,colname3,
The Remove then removes the last comma and adds a newline
colname1,colname2,colname3\n
The second loop lists all your values of each column of each row
colname1,colname2,colname3\n
row1col1value,row1col2value,row1col3value,\n -- note that the comma is NOT removed here
row2col1value,row2col2value,row2col3value,\n
row3col1value,row3col2value,row3col3value,\n
row4col1val etc...
And yes, I think you can use a string instead of the string builder.
The first foreach is appending the column header names.
The second is appending the cell values. Both in comma separated way.
Ao you are converting a GridView to a csv.
Why don't use a simple converter like the CSV helper.
Has everything you need.
CSV Helper
Looks like the code is trying to generate csv file with headers for the data table. The first for each loops through the columns in DataTable and generates a comma separated column name string (referred by StringBuffer).
sb.Remove(sb.Length - 1, 1);
sb.Append(Environment.NewLine);
The above code snippet removes the last comma from the comma separated column name string and then adds a new line
foreach (DataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
sb.Append(row[i].ToString() + ",");
}
sb.Append(Environment.NewLine);
}
the loop above iterates through each row of DataTable, and creates a comma separated string for each column value of the. After each row is processed, a new line is added so that the next row contents are added as comma separated string in new line.
The first loop is taking each column name from Datatable and appending with a separator comma to a stringBuilder. Then it is trimming the last comma appended and adding a new line to it.
The second loop is taking all the data values of DataRow(row by row) , then comma and appending to the same stringbuilder.
I'm a C# newbie_and in programming in general_ and in a previous question C# return linq result as a list from a wcf service method then use it in aspx web forms page , I managed to return a row from a table and display the result in labels in my apx web forms page. Now I want to display the whole table-> an unknown number of rows. I edited my code and I was almost successful. The problem is that the table that I get, instead of the four different rows that my table contains, displays the first one four times. I check again and again but I can't find the error nor some friends. Here is my code:
staffPanel.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
displayClients_Ref.IdisplayClientsSrvcClient dcClient = new displayClients_Ref.IdisplayClientsSrvcClient();
List<string> allClients = new List<string>(dcClient.displayClients());
foreach (string row in allClients)
{
int size = 0;
string client = allClients.FirstOrDefault();
if (String.IsNullOrEmpty(client))
{
// record cannot be found
}
else
{
string[] columns = client.Split(';');
size = columns.Length;
TableRow tr = new TableRow();
allClients_tbl.Rows.Add(tr);
for (int i = 0; i < size; i++)
{
TableCell tc = new TableCell();
tc.Text = columns[i];
tr.Cells.Add(tc);
}
}
}
}
displayClient.svc.cs
public List<string> displayClients()
{
List<string> result = new List<string>();
try
{
using (paragon_db_Models.clients_Entity context = new paragon_db_Models.clients_Entity())
{
var query = from cl in context.clients
select cl;
foreach (var c in query)
{
string row = c.user_account_id + ";" + c.client_name + ";" + c.client_surname + ";" + c.business_name + ";" + c.client_address + ";" + c.postal_code + ";" + c.telephone_number + ";" + c.fax + ";" + c.email + ";" + c.fiscal_code + ";" + c.public_fiscal_service;
result.Add(row);
}
}
return result;
}
catch (Exception)
{
return result;
}
}
If it is a simple, stupid little mistake that I cannot see I will remove the question. I'm open to suggestions and comments concerning a different way of doing this.
You don't need
string client = allClients.FirstOrDefault();
You are already getting the info you want with "row" in
foreach (string row in allClients)
Replace your "client" instances with "row". FirstOrDefault would always get the first object or null.
I'm working on a application which will export my DataGridView called scannerDataGridView to a csv file.
Found some example code to do this, but can't get it working. Btw my datagrid isn't databound to a source.
When i try to use the Streamwriter to only write the column headers everything goes well, but when i try to export the whole datagrid including data i get an exeption trhown.
System.NullReferenceException: Object reference not set to an instance
of an object. at Scanmonitor.Form1.button1_Click(Object sender,
EventArgs e)
Here is my Code, error is given on the following line:
dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();
//csvFileWriter = StreamWriter
//scannerDataGridView = DataGridView
private void button1_Click(object sender, EventArgs e)
{
string CsvFpath = #"C:\scanner\CSV-EXPORT.csv";
try
{
System.IO.StreamWriter csvFileWriter = new StreamWriter(CsvFpath, false);
string columnHeaderText = "";
int countColumn = scannerDataGridView.ColumnCount - 1;
if (countColumn >= 0)
{
columnHeaderText = scannerDataGridView.Columns[0].HeaderText;
}
for (int i = 1; i <= countColumn; i++)
{
columnHeaderText = columnHeaderText + ',' + scannerDataGridView.Columns[i].HeaderText;
}
csvFileWriter.WriteLine(columnHeaderText);
foreach (DataGridViewRow dataRowObject in scannerDataGridView.Rows)
{
if (!dataRowObject.IsNewRow)
{
string dataFromGrid = "";
dataFromGrid = dataRowObject.Cells[0].Value.ToString();
for (int i = 1; i <= countColumn; i++)
{
dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();
csvFileWriter.WriteLine(dataFromGrid);
}
}
}
csvFileWriter.Flush();
csvFileWriter.Close();
}
catch (Exception exceptionObject)
{
MessageBox.Show(exceptionObject.ToString());
}
LINQ FTW!
var sb = new StringBuilder();
var headers = dataGridView1.Columns.Cast<DataGridViewColumn>();
sb.AppendLine(string.Join(",", headers.Select(column => "\"" + column.HeaderText + "\"").ToArray()));
foreach (DataGridViewRow row in dataGridView1.Rows)
{
var cells = row.Cells.Cast<DataGridViewCell>();
sb.AppendLine(string.Join(",", cells.Select(cell => "\"" + cell.Value + "\"").ToArray()));
}
And indeed, c.Value.ToString() will throw on null value, while c.Value will correctly convert to an empty string.
A little known feature of the DataGridView is the ability to programmatically select some or all of the DataGridCells, and send them to a DataObject using the method DataGridView.GetClipboardContent(). Whats the advantage of this then?
A DataObject doesn't just store an object, but rather the representation of that object in various different formats. This is how the Clipboard is able to work its magic; it has various formats stored and different controls/classes can specify which format they wish to accept. In this case, the DataGridView will store the selected cells in the DataObject as a tab-delimited text format, a CSV format, or as HTML (*).
The contents of the DataObject can be retrieved by calling the DataObject.GetData() or DataObject.GetText() methods and specifying a predefined data format enum. In this case, we want the format to be TextDataFormat.CommaSeparatedValue for CSV, then we can just write that result to a file using System.IO.File class.
(*) Actually, what it returns is not, strictly speaking, HTML. This format will also contain a data header that you were not expecting. While the header does contain the starting position of the HTML, I just discard anything above the HTML tag like myString.Substring(IndexOf("<HTML>"));.
Observe the following code:
void SaveDataGridViewToCSV(string filename)
{
// Choose whether to write header. Use EnableWithoutHeaderText instead to omit header.
dataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
// Select all the cells
dataGridView1.SelectAll();
// Copy selected cells to DataObject
DataObject dataObject = dataGridView1.GetClipboardContent();
// Get the text of the DataObject, and serialize it to a file
File.WriteAllText(filename, dataObject.GetText(TextDataFormat.CommaSeparatedValue));
}
Now, isn't that better? Why re-invent the wheel?
Hope this helps...
Please check this code.its working fine
try
{
//Build the CSV file data as a Comma separated string.
string csv = string.Empty;
//Add the Header row for CSV file.
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
csv += column.HeaderText + ',';
}
//Add new line.
csv += "\r\n";
//Adding the Rows
foreach (DataGridViewRow row in dataGridView1.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
if (cell.Value != null)
{
//Add the Data rows.
csv += cell.Value.ToString().TrimEnd(',').Replace(",", ";") + ',';
}
// break;
}
//Add new line.
csv += "\r\n";
}
//Exporting to CSV.
string folderPath = "C:\\CSV\\";
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
File.WriteAllText(folderPath + "Invoice.csv", csv);
MessageBox.Show("");
}
catch
{
MessageBox.Show("");
}
Found the problem, the coding was fine but i had an empty cell that gave the problem.
Your code was almost there... But I made the following corrections and it works great. Thanks for the post.
Error:
string[] output = new string[dgvLista_Apl_Geral.RowCount + 1];
Correction:
string[] output = new string[DGV.RowCount + 1];
Error:
System.IO.File.WriteAllLines(filename, output, System.Text.Encoding.UTF8);
Correction:
System.IO.File.WriteAllLines(sfd.FileName, output, System.Text.Encoding.UTF8);
The line "csvFileWriter.WriteLine(dataFromGrid);" should be moved down one line below the closing bracket, else you'll get a lot of repeating results:
for (int i = 1; i <= countColumn; i++)
{
dataFromGrid = dataFromGrid + ',' + dataRowObject.Cells[i].Value.ToString();
}
csvFileWriter.WriteLine(dataFromGrid);
I think this is the correct for your SaveToCSV function : ( otherwise Null ...)
for (int i = 0; i < columnCount; i++)
Not :
for (int i = 1; (i - 1) < DGV.RowCount; i++)
This is what I been using in my projects:
void export_csv(string file, DataGridView grid)
{
using (StreamWriter csv = new StreamWriter(file, false))
{
int totalcolms = grid.ColumnCount;
foreach (DataGridViewColumn colm in grid.Columns) csv.Write(colm.HeaderText + ',');
csv.Write('\n');
string data = "";
foreach (DataGridViewRow row in grid.Rows)
{
if (row.IsNewRow) continue;
data = "";
for (int i = 0; i < totalcolms; i++)
{
data += (row.Cells[i].Value ?? "").ToString() + ',';
}
if (data != string.Empty) csv.WriteLine(data);
}
}
}