using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
using (var mailClient = client)
using (var messagesd = msg)
{
foreach (DataColumn column in objDT.Columns)
{
writer.WriteLine(column.ColumnName);
}
writer.WriteLine();
for (int i = 0; i < objDT.Rows.Count; i++)
{
DataRow row = objDT.Rows[i];
for (int j = 0; j < row.ItemArray.Length; j++)
{
if (row.ItemArray[j] != null && !Convert.IsDBNull(row.ItemArray[j]))
{
writer.Write(row.ItemArray[j].ToString());
}
else
{
writer.Write("");
}
if (j < row.ItemArray.Length - 1)
{
writer.Write(",");
}
else if (i < objDT.Rows.Count - 1)
{
writer.WriteLine();
}
}
}
writer.Flush();
stream.Position = 0;
messagesd.Attachments.Add(new Attachment(stream, "test.csv"));
mailClient.Send(messagesd);
I have 3 columns, but result I`m getting:
testATestBTestC
under single column
Result i want is TestA column 1, TestB column 2 and TestC column 3
Any help would be appreciated. Thank you.
You should write a delimeter(,) after every value (header name or value) except last one. Use Writemethod to put values into a row and WriteLine to start a new row.
It is better to use existing libraries from Nuget. CSVHelperas example.
Related
how to Export DataSet(multiple of Datatables) to a notepad. From c#
Note: NOT A SINGLE DataTable ,Multiple DataTables From DataSet;
I would suggest something simple, create a translator or download a bunch of other libraries available on the web.
you would most like go
public interfacte IExport
{
bool Export(Databale sometable);// this can also reference interface
//concrete implementation could also handle saving of file
}
then call on a concrete class to implement that value, use a Factory Patter, Dependency Injection, etc to supply the concrete type. Then you can keep adding as many converters to support as many file types as you'd like.
private void Write(System.Data.DataSet dts, string outputFilePath)
{
System.Data.DataTable dt = new System.Data.DataTable();
for (int z = 0; z < dts.Tables.Count; z++)
{
dt = dts.Tables[z];
int[] maxLengths = new int[dt.Columns.Count];
for (int i = 0; i < dt.Columns.Count; i++)
{
maxLengths[i] = dt.Columns[i].ColumnName.Length;
foreach (DataRow row in dt.Rows)
{
if (!row.IsNull(i))
{
int length = row[i].ToString().Length;
if (length > maxLengths[i])
{
maxLengths[i] = length;
}
}
}
}
using (StreamWriter sw = new StreamWriter(outputFilePath, true))
{
for (int i = 0; i < dt.Columns.Count; i++)
{
sw.Write(dt.Columns[i].ColumnName.PadRight(maxLengths[i] + 2));
}
sw.WriteLine();
foreach (DataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
if (!row.IsNull(i))
{
sw.Write(row[i].ToString().PadRight(maxLengths[i] + 2));
}
else
{
sw.Write(new string(' ', maxLengths[i] + 2));
}
}
sw.WriteLine();
}
sw.Close();
}
}
}
I've put the .AutoSizeColumn right before the write Method
int numberOfColumns = sheet.GetRow(rowcount - 1).PhysicalNumberOfCells;
for (int i = 0; i <= numberOfColumns; i++)
{
sheet.AutoSizeColumn(i);
GC.Collect();
}
using (var fileData = new FileStream(#"C:\Temp\Contatti.xlsx", FileMode.Create))
{
wb.Write(fileData);
}
this is an example of the result
The problem also migh be, that PhysicalNumberOfCells can return 1, even if you have a cell lets say in 'Z' column. There is LastCellNum property,you i instead of PhysicalNumberOfCells:
int lastColumNum = sheet.GetRow(0).LastCellNum;
for (int i = 0; i <= lastColumNum; i++)
{
sheet.AutoSizeColumn(i);
GC.Collect();
}
using (var fileData = new FileStream(#"D:\Contatti.xlsx", FileMode.Create))
{
wb.Write(fileData);
}
How do I choose the second var array in the list? array[i+1] chooses the second column but I want to begin with the second row of the array. So I would like to disregard the first row, since this contains the column names.
Code:
foreach(var array in list)
{
var NewRow = table.NewRow();
for (int i = 0; i < columnNames.Count; i++)
{
NewRow[columnNames[i]] = array[i];
}
table.Rows.Add(NewRow);
}
EDIT: Whole method
private DataTable ConvertListToDataTable(List<WindowsFormsApplication1.ServiceReference1.ArrayOfString> list)
{
DataTable table = new DataTable();
List<string> columnNames = list[0];
for (int i = 0; i < columnNames.Count; i++)
{
table.Columns.Add(columnNames[i].ToString());
}
foreach (var array in list)
{
var NewRow = table.NewRow();
for (int i = 0; i < columnNames.Count; i++)
{
NewRow[columnNames[i]] = array[i];
}
table.Rows.Add(NewRow);
}
return table;
}
You could use Skip
foreach (var array in list.Skip(1))
{
...
}
Or alternatively, stick with a basic for loop and just start at 1
for (var i = 1; i < list.Count; i++)
{
...
}
You can use Skip:
foreach (var array in list.Skip(1))
{
var NewRow = table.NewRow();
for (int i = 0; i < columnNames.Count; i++)
{
NewRow[columnNames[i]] = array[i];
}
table.Rows.Add(NewRow);
}
Don't forget to add using System.Linq; at the top of the file.
private void write(object sender, EventArgs e)
{
FileStream outputFileStream = new FileStream("test.txt", FileMode.Create, FileAccess.Write);
StreamWriter writer = new StreamWriter(outputFileStream);
Random r = new Random();
for (int i = 0; i < dataGridView1.RowCount; i++)
{
for (int j = 0; j < dataGridView1.ColumnCount; j++)
{
double d = 0;
Double.TryParse(Convert.ToString(dataGridView1.Rows[i].Cells[j].Value), out d);
writer.Write(d + "\t");
}
writer.Write("\n");
}
writer.Close();
outputFileStream.Close();
}
So this is the method to write the text file. It works fine because I have opened it successfully with an Excel. I even tried to copy and paste it and it would work. Now the problem is.....
private void read(object sender, EventArgs e)
{
char TAB = '\t';
char NEWLINE = '\n';
FileStream inputFileStream = new FileStream("test.txt", FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(inputFileStream);
string line;
string[] fields;
for (int i = 0; i < dataGridView1.RowCount; i++)
{
for (int j = 0; j < dataGridView1.ColumnCount; j++)
{
line = reader.ReadLine();
fields = line.Split(TAB, NEWLINE);
dataGridView1.Rows[i].Cells[j].Value = fields;
}
}
inputFileStream.Close();
reader.Close();
}
However when I read the file back onto a DataGridView it does not work properly. Now this is the exact text file that I wrote on my code. Instead what happens is that it is displayed on only 1 row. How do I get back the amount of columns and rows from what the user entered? I prefer keeping it a text file.
I have used default properties for my dataGridView1
RowCount returns displayed rows count. So here it returns 1 because you are displaying one row and it's empty:
for (int i = 0; i < dataGridView1.RowCount; i++)
Instead of this, you should create new rows and add it to the Rows collection like this:
// Use File.ReadAllLines, it's easier
string[] lines = File.ReadAllLines("test.txt");
foreach(line in lines)
{
var text = line.Split('\t','\n');
dataGridView1.Rows.Add(text);
}
System.IO.StreamReader file = new System.IO.StreamReader("yourfile.txt");
string[] columnnames = file.ReadLine().Split(' ');
DataTable dt = new DataTable();
foreach (string c in columnnames)
{
dt.Columns.Add(c);
}
string newline;
while ((newline = file.ReadLine()) != null)
{
DataRow dr = dt.NewRow();
string[] values = newline.Split(' ');
for (int i = 0; i < values.Length; i++)
{
dr[i] = values[i];
}
dt.Rows.Add(dr);
}
file.Close();
dataGridView1.DataSource = dt;
try this one with your own delimiters i.e. \t and \n. And First try to search your problems on internet before posting queries and try to solve them by yourself. I am not giving full code.
How can I read data from DataGridView in C#? I want to read the data appear in Table. How do I navigate through lines?
something like
for (int rows = 0; rows < dataGrid.Rows.Count; rows++)
{
for (int col= 0; col < dataGrid.Rows[rows].Cells.Count; col++)
{
string value = dataGrid.Rows[rows].Cells[col].Value.ToString();
}
}
example without using index
foreach (DataGridViewRow row in dataGrid.Rows)
{
foreach (DataGridViewCell cell in row.Cells)
{
string value = cell.Value.ToString();
}
}
If you wish, you can also use the column names instead of column numbers.
For example, if you want to read data from DataGridView on the 4. row and the "Name" column.
It provides me a better understanding for which variable I am dealing with.
dataGridView.Rows[4].Cells["Name"].Value.ToString();
Hope it helps.
string[,] myGridData = new string[dataGridView1.Rows.Count,3];
int i = 0;
foreach(DataRow row in dataGridView1.Rows)
{
myGridData[i][0] = row.Cells[0].Value.ToString();
myGridData[i][1] = row.Cells[1].Value.ToString();
myGridData[i][2] = row.Cells[2].Value.ToString();
i++;
}
Hope this helps....
Code Example : Reading data from DataGridView and storing it in an array
int[,] n = new int[3, 19];
for (int i = 0; i < (StartDataView.Rows.Count - 1); i++)
{
for (int j = 0; j < StartDataView.Columns.Count; j++)
{
if(this.StartDataView.Rows[i].Cells[j].Value.ToString() != string.Empty)
{
try
{
n[i, j] = int.Parse(this.StartDataView.Rows[i].Cells[j].Value.ToString());
}
catch (Exception Ee)
{ //get exception of "null"
MessageBox.Show(Ee.ToString());
}
}
}
}
private void HighLightGridRows()
{
Debugger.Launch();
for (int i = 0; i < dtgvAppSettings.Rows.Count; i++)
{
String key = dtgvAppSettings.Rows[i].Cells["Key"].Value.ToString();
if (key.ToLower().Contains("applicationpath") == true)
{
dtgvAppSettings.Rows[i].DefaultCellStyle.BackColor = Color.Yellow;
}
}
}