I am trying to display these xml strings in a datagrid. I don't know much about datasets, but it does not seem to keep the data previously entered. Here is my code.
C#:
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
string rdr = reader[i].ToString();
dataList.Add(rdr);
string column = reader.GetName(i);
const string xmlAttributeFormat = "{0} = \"{1}\" ";
xmlString = xmlString + String.Format(xmlAttributeFormat, column, dataList[i]);
}
string FinalXMLString = "<row " + xmlString + " />";
StringReader streamreader = new System.IO.StringReader(FinalXMLString);
XmlTextReader xmlreader = new System.Xml.XmlTextReader(streamreader);
dataSet = new System.Data.DataSet();
dataSet.ReadXml(xmlreader);
xmlString = "";
dataList.Clear();
FinalXMLString = "";
}
I have a while loop that is going through the query and then a for loop to put the values in a list. This is working perfectly. The data is then being put into a dataset which is then binded to the datagrid. The only problem is it only shows the data from the last line read from the query. How do I make it show all of the rows from the query in the datagrid? Any help would be appreciated. Thanks in advanced.
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
string rdr = reader[i].ToString();
dataList.Add(rdr);
string column = reader.GetName(i);
}
}
Display_Grid(myGrid,dataList)
public static void Display_Grid(DataGrid d, List<string> S1)
{
ds = new DataSet();
DataTable dt = new DataTable();
ds.Tables.Add(dt);
DataColumn cl = new DataColumn(column, typeof(string));
cl.MaxLength = 200;
dt.Columns.Add(cl);
int i = 0;
foreach (string s in S1)
{
DataRow rw = dt.NewRow();
rw["Description"] = S1[i];
i++;
}
d.ItemsSource = ds.Tables[0].AsDataView();
}
you pass the name of your datagrid (d) and the string List (s1) as parameters ad inside the code you define the name of the columhn header of to be shown (I have written Description).
In your case S1=datalist.
if datalist contains e.g 3 elements then the method will iterate through those and produce 3 rows...
Related
I'm making a desktop application using the windows form with C#, I stored uploaded csv data with data grid view, then I make a transpose feature in the application, but did not work well, because the row of index or row 0 does not included in transpose output file.
Picture 1
So, I decided to add a empty row inside csv file at the top of data with this code
DataRow dr1 = dt.NewRow();
dt.Rows.InsertAt(dr1, 0);
I tried manually by insert empty row in csv and the application look like this
Picture 2
How should I code to make application insert an empty data row at 0 and store it in data grid view looks like a picture above? so my transpose feature works well
here I wrote to store the data in data grid
public DataSet ConnectCSV()
{
DataSet ds = new DataSet();
string fileName = openFileDialogCSVFilePath.FileName;
CsvReader reader = new CsvReader(fileName);
ds = reader.RowEnumerator;
dGridCSVdata.DataSource = ds;
dGridCSVdata.DataMember = "TheData";
return ds;
}
private void dGridCSVdata_Navigate(object sender, NavigateEventArgs ne)
{
}
here I wrote to read the data
public DataSet RowEnumerator
{
get
{
if (null == __reader)
throw new System.ApplicationException("I can't start reading without CSV input.");
__rowno = 0;
string sLine;
string sNextLine;
DataSet ds = new DataSet();
DataTable dt = ds.Tables.Add("TheData");
DataRow dr1 = dt.NewRow();
dt.Rows.InsertAt(dr1, 0);
while (null != (sLine = __reader.ReadLine()))
{
while (rexRunOnLine.IsMatch(sLine) && null != (sNextLine = __reader.ReadLine()))
sLine += "\n" + sNextLine;
__rowno++;
DataRow dr = dt.NewRow();
string[] values = rexCsvSplitter.Split(sLine);
for (int i = 0; i < values.Length; i++)
{
values[i] = Csv.Unescape(values[i]);
if (__rowno == 1)
{
dt.Columns.Add(values[i].Trim());
}
else
{
if (Csv.CharNotAllowes(values[i]))
{
dr[i] = values[i].Trim();
}
}
}
if (__rowno != 1)
{
dt.Rows.Add(dr);
}
ds.Tables.Add(Transposer.Transpose(dt));
// transpose code
StringBuilder sb = new StringBuilder();
for (int u = 0; u < dt.Columns.Count; u++)
{
for (int i = 0; i < dt.Rows.Count; i++)
{
sb.Append(dt.Rows[i][u].ToString());
if (i < dt.Rows.Count - 1)
{
sb.Append(',');
}
}
sb.AppendLine();
}
File.WriteAllText("C:\\Users\\Desktop\\Output.csv", sb.ToString());
}
__reader.Close();
return ds;
}
}
This is going to be my text file (30 lines)
OrderNo:37374
OrderQuantity:250
BarcodeQR:584,25478Klkd28
NormalBarcode:1565484864
.......
.......
.......
This is the code :
public DataTable DTforReport()
{
DataTable dt = new DataTable();
DataColumn col = new DataColumn("test");
col.DataType = System.Type.GetType("System.String");
dt.Columns.Add(col);
string[] lines = File.ReadAllLines("C:\\Users\\abc\\Desktop\\abc.txt");
foreach (var line in lines)
{
var segments = line.Split(';');
foreach (var seg in segments)
{
DataRow dr = dt.NewRow();
dr[0] = seg;
dt.Rows.Add(dr);
}
}
return dt;
}
I want my output like this
OrderNo OrderQuantity BarcodeQR
37374 250 584,25478Klkd28
How can I change my code to achieve this?
You have generated only one column. Change your code like below to see your desired result:
public DataTable DTforReport()
{
DataTable dt = new DataTable();
string[] lines = File.ReadAllLines("C:\\Users\\abc\\Desktop\\abc.txt");
DataRow dr = dt.NewRow();
for (int i = 0; i < lines.Length; i++)
{
DataColumn col = new DataColumn(lines[i].Split(':')[0]);
col.DataType = Type.GetType("System.String");
dt.Columns.Add(col);
var segment = lines[i].Split(':')[1];
dr[i] = segment;
}
dt.Rows.Add(dr);
return dt;
}
I suggest you to modify your method like the following:
public DataTable DTforReport()
{
DataTable testTable = new DataTable("Test");
testTable.Columns.Add("OrderNo");
testTable.Columns.Add("OrderQuantity");
testTable.Columns.Add("BarcodeQR");
string[] lines = File.ReadAllLines("C:\\Users\\abc\\Desktop\\abc.txt");
foreach (var line in lines)
{
DataRow dRow = testTable.NewRow();
var segments = line.Split(';');
for (int i = 0; i < segments.Length; i++)
{
var colValues = segments[i].Split(':');
dRow[i] = colValues[1];
}
testTable.Rows.Add(dRow);
}
return testTable;
}
Few suggestions for improvement:
I have given static column names, if you want to add more or they may change in future means you can create dynamic columns in the datatable.
If you have doubts in the input values, make use of proper validation
Validations in the sense, make sure about the splitted values before accessing them through index otherwise they may ends up with IndexOutOfRangeException
DataTable dt = new DataTable();
string[] lines = File.ReadAllLines("C:\\Users\\abc\\Desktop\\abc.txt");
var firstLine = lines.First();
var columns = firstLine.Split(';');
for (var icount = 0; icount < columns.Count(); icount++)
{
var colName = columns[icount].Contains(":") ? columns[icount].Split(':')[0] : "Column" + icount;
var dataCol = new DataColumn(colName);
dataCol.DataType = System.Type.GetType("System.String");
dt.Columns.Add(dataCol);
}
foreach (var line in lines)
{
DataRow dr = dt.NewRow();
var segments = line.Split(';');
for (var icount = 0; icount < segments.Count(); icount++)
{
var colVal = segments[icount].Contains(":") ? segments[icount].Split(':')[1] : "";
dr[icount] = colVal;
}
dt.Rows.Add(dr);
}
*Number of column must be same in each row.
I'm using this code while reading from SQL Server. The problem is that it runs the loop as many times are my SQL Server results.
SqlCommand sqlCmd = new SqlCommand("Select Name from TablesDesigner", con);
SqlDataReader sqlReader = sqlCmd.ExecuteReader();
while (sqlReader.Read())
{
for (int row = 0; row < NUM_ROWS; row++)
{
TableRow tablerow = new TableRow(this);
TableLayout.LayoutParams linearLayoutParams = new TableLayout.LayoutParams(TableLayout.LayoutParams.MatchParent, TableLayout.LayoutParams.MatchParent, 1.0f);
tablerow.LayoutParameters = linearLayoutParams;
table.AddView(tablerow);
for (int col = 0; col < NUM_COLS; col++)
{
int FINAL_COL = col;
int FINAL_ROW = row;
Button btn = new Button(this);
TableRow.LayoutParams linearLayoutParams2 = new TableRow.LayoutParams(TableRow.LayoutParams.MatchParent, TableRow.LayoutParams.MatchParent, 1.0f);
btn.LayoutParameters = linearLayoutParams2;
btn.Text = sqlReader["Name"].ToString();
tablerow.AddView(btn);
}
}
}
My result is below:
And my desired result is:
Where should I place my loop for getting the desired result? Or should I break it somehow?
Thanks.
Also what if I want to use two rows??
When confronted with a difficult problem, break it down into manageable bits (this is good coding practice anyway).
First, get the data you need into a single list. Don't forget to Dispose your DataReader.
public List<string> GetButtonNames()
{
var buttonNames = new List<string>();
SqlCommand sqlCmd = new SqlCommand("Select Name from TablesDesigner", con);
using (var sqlReader = sqlCmd.ExecuteReader())
{
while (sqlReader.Read())
{
buttonNames.Add(sqlReader["Name"].ToString());
}
}
return buttonNames;
}
Then write a function to organize it into a 2D list. I stole the logic for this from this question.
public static List<List<string>> Make2DList(List<string> input, int width=4)
{
var output = new List<List<string>>();
for (int i=0; i < input.Count; i+= width)
{
output.Add(input.GetRange(i, Math.Min(width, input.Count - i)));
}
return output;
}
Now you have a list of lists. The "outer" list corresponds to each table row. The inner list is a list of column values within that row.
Now all you need is code to make it into a table. Because we organized the data into a grid already, we can use normal foreach syntax which makes it very easy.
public void RenderButtonTable(List<List<string>> names)
{
var layout = new TableLayout.LayoutParams
(
TableLayout.LayoutParams.MatchParent,
TableLayout.LayoutParams.MatchParent,
1.0f
);
tablerow.LayoutParameters = layout;
foreach (var row in names)
{
TableRow tablerow = new TableRow(this);
tablerow.LayoutParameters = layout;
table.AddView(tablerow);
foreach (var col in row)
{
Button btn = new Button(this);
btn.Text = col;
tablerow.AddView(btn);
}
}
}
Put it all together:
void CreateDynamicButtonsWhileReadingFromSQLServer()
{
var buttonNames = GetButtonNames();
var gridData = Make2DList(buttonNames, NUM_COLS);
RenderButtonTable(gridData);
}
I'm exporting data from SQLite into .csv but I got problem on rows why the result is always appear in the 1st row? did I miss something??
RESULT:
My Code:
private void DataExport()
{
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Title = "Choose file to save to",
FileName = ".csv",
Filter = "CSV (*.csv)|*.csv",
FilterIndex = 0,
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};
if (saveFileDialog.ShowDialog() == true)
{
SQLiteCommand cmd = new SQLiteCommand();
String sSQL;
sSQL = "select * from Tile1";
cmd.CommandText = sSQL;
clsCon.con.Open();
cmd.Connection = clsCon.con;
SQLiteDataReader dr2;
dr2 = cmd.ExecuteReader();
dr2.Read();
DataSet _dataSet = new DataSet();
DataTable _dataTable = new DataTable();
for (var i = 0; i < dr2.FieldCount; i++)
{
_dataTable.Columns.Add("" + dr2.GetName(i) + "", typeof(string));
_dataTable.Rows.Add("" + dr2.GetValue(i) + "");
}
var rows = _dataTable.Rows;
StringBuilder sb = new StringBuilder();
IEnumerable<string> columnNames = _dataTable.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
sb.AppendLine(string.Join(",", columnNames));
foreach (DataRow row in rows)
{
IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
sb.AppendLine(string.Join(",", fields));
}
File.WriteAllText(saveFileDialog.FileName, sb.ToString());
clsCon.con.Close();
}
}
it looks the DataTable object has not been filled correctly, check the part here:
for (var i = 0; i < dr2.FieldCount; i++)
{
_dataTable.Columns.Add("" + dr2.GetName(i) + "", typeof(string));
_dataTable.Rows.Add("" + dr2.GetValue(i) + "");
}
I guess you tried to set up columns of the data table here, but you can't append rows in the same time, you actually add each column values of the first row into different rows. The table you generated would be like this:
col1 col2 col3 col4
row1 val(1,1)
row2 val(1,2)
row3 val(1,3)
row4 val(1,4)
val(x,y) means value at column y and row x in database.
#Darin Dimitrov 's solution works very well for your issue.
Try simplifying your code a bit, I mean those DataTables and DataSets are driving me nuts:
private void DataExport()
{
SaveFileDialog saveFileDialog = new SaveFileDialog
{
Title = "Choose file to save to",
FileName = ".csv",
Filter = "CSV (*.csv)|*.csv",
FilterIndex = 0,
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};
if (!saveFileDialog.ShowDialog())
{
return;
}
using (var conn = new SQLiteConnection(ConnectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT * FROM Tile1";
using (var reader = cmd.ExecuteReader())
using (var writer = new StreamWriter(saveFileDialog.FileName))
{
var columnNames = Enumerable
.Range(0, reader.FieldCount)
.Select(reader.GetName);
string header = string.Join(", ", columnNames);
writer.WriteLine(header);
while (reader.Read())
{
var values = Enumerable
.Range(0, reader.FieldCount)
.Select(reader.GetValue);
string valuesRow = string.Join(", ", values);
writer.WriteLine(valuesRow);
}
}
}
}
I have a excel sheet with two tabs so i want to get a row from one tab and insert into another,i thought it would be same like in sqlserver or mysql . Just select and insert..
I am using this query but it says syntax error not sure what is wrong in it.
testCommand.CommandText = "Insert into [ActiveLicenses$]( Select * from [companies$]
where [License Number] = '" + lnumber + "')";
testCommand.ExecuteNonQuery();
UPDATE
Is there any way to delete the rows directly from excel sheet?
You can use SQL to extract the data from Excel:
using (OleDbDataAdapter da = new OleDbDataAdapter(
"SELECT " + columns + " FROM [" + worksheetName + "$]", conn))
{
DataTable dt = new DataTable(tableName);
da.Fill(dt);
ds.Tables.Add(dt);
}
Unfortunately inserting into excel doesn't work this way. I am pretty sure you cant specify a cell to write to using OleDb Insert Command, it will automatically go to the next open row in the specified column. You can workaround it with an update statement:
sql = "Update [Sheet1$A1:A10] SET A10 = 'YourValue'";
myCommand.CommandText = sql;
myCommand.ExecuteNonQuery();
Personally I would use VSTO rather than oleDB. Once you have extracted the cell simply open up the spreadsheet with code and insert the data:
Excel.Workbook wb = xlApp.Workbooks.Open(filePath);
rng = wb.Range["A1"];
rng.Value2 = "data";
A faster method.
I take all the licenses into a DataTable and remove the ones not required takes less than 1 minute. and then simply export DataTable to Csv so i have the file ready in less than 1 minute.
Sample below:
static List<string> licensecAll = new List<string>();
DataTable dt = new DataTable();
OleDbDataAdapter dp = new OleDbDataAdapter("select * from [companies$]", testCnn);
dp.Fill(dt);
if (dt.Rows.Count > 0)
{
for (int i = dt.Rows.Count-1; i >= 0; i--)
{
string lnum = dt.Rows[i][0].ToString();
Console.WriteLine("LICENSE NUMBER" + lnum);
if (!licensecAll.Contains(lnum))
{
Console.WriteLine("ROW REMOVED");
dt.Rows.RemoveAt(i);
}
}
}
Then simply run datatable to csv....
public static void DataTable2CSV(DataTable table, string filename, string seperateChar)
{
StreamWriter sr = null;
try
{
sr = new StreamWriter(filename);
string seperator = "";
StringBuilder builder = new StringBuilder();
foreach (DataColumn col in table.Columns)
{
builder.Append(seperator).Append(col.ColumnName);
seperator = seperateChar;
}
sr.WriteLine(builder.ToString());
foreach (DataRow row in table.Rows)
{
seperator = "";
builder = new StringBuilder();
foreach (DataColumn col in table.Columns)
{
builder.Append(seperator).Append(row[col.ColumnName]);
seperator = seperateChar;
}
sr.WriteLine(builder.ToString());
}
}
finally
{
if (sr != null)
{
sr.Close();
}
}
}