How to transfer data from SQLiteDataTable to a TextBox - c#

I'm trying to link data from my db (sqlite) to my textboxes, but I don't know exactly how...
Here's what i'm trying:
private void btnUpdate_Click(object sender, EventArgs e)
{
con.Open();
adapter = new SQLiteDataAdapter("SELECT PRECO_PRODUTO FROM INGREDIENTES WHERE NOME_PRODUTO='"+listProdutos.SelectedIndex+"'", con);
adapter.Fill(populate);
List<DataTable> precoIng = new List<DataTable>();
precoIng.Add(populate.Tables[0]);
con.Close();
tbPrecoProduto.Text = precoIng[0]; //error here
}
I think I need a way to convert the SQLiteDataTable to a string? I'm new on db stuffs. This is my table and this is my form design, if helps...

It seems as if you're trying to set the text of the TextBox to a DataTable. This doesn't quite make sense, as the type DataTable isn't the same as a string. You'd first have to extract the data out of your table like that:
var builder = new StringBuilder ();
foreach (var rowObject in precoIng [0].Rows)
{
var row = (DataRow) rowObject;
var id = row ["ID_PRODUTO"].ToString ();
var name = row ["NOME_PRODUTO"].ToString ();
var price = row ["PRECO_PRODUTO"].ToString ();
var count = row ["QNT_PRODUTO"].ToString ();
builder.AppendLine ($"Id: {id}; Name: {name}; Price: {price}; Count: {count}");
}
tbPrecoProduto.Text = builder.ToString ();
You can of course shorten this if you only want for example the price:
var builder = new StringBuilder ();
foreach (var rowObject in precoIng [0].Rows)
{
var row = (DataRow) rowObject;
var price = row ["PRECO_PRODUTO"].ToString ();
builder.AppendLine (price);
}
tbPrecoProduto.Text = builder.ToString ();
And, btw, precoIng[0] will always be the same as populate.Tables[0].
Alternatively you could write an extension method like that:
public static string GetData (this DataTable table)
{
var builder = new StringBuilder ();
foreach (DataRow row in table.Rows)
foreach (DataColumn column in table.Columns)
builder.Append (column.ColumnName).Append (": ").Append (row [column]).Append ("; ");
return builder.ToString ();
}
And then call precoIng[0].GetData() to get the data as a string.
If you want to be able to filter the data to get printed, you could do something like this:
public static string GetData (this DataTable table, List <string> columns = null)
{
var builder = new StringBuilder ();
foreach (DataRow row in table.Rows)
if (columns == null)
foreach (DataColumn column in table.Columns)
builder.Append (column.ColumnName).Append (": ").Append (row [column]).Append ("; ");
else
foreach (var column in columns)
builder.Append (column).Append (": ").Append (row [column]).Append ("; ");
return builder.ToString ();
}
I do however feel as if you don't want the data of your whole table as a string, but rather want the data to certain ids or something. To help you with this, however, I'd need more precise information.
Ok, so it seems as if what you actually want is something like this:
var preco = precoIng.FirstOrDefault ()?.Rows.Cast <DataRow> ().FirstOrDefault ()? ["PRECO_PRODUTO"]?.ToString () ?? "";

Related

Why do I get System.Data.DataRow? instead of datatable (I've retrieved a table from outlook as html body then I've parse it to a data table)

I've retrieved a table from outlook as html body then I've parse it to a datatable but when I run the code, all I get is System.Data.DataRow
static void Main(string[] args)
{
var mails = OutlookEmails.ReadMailItems();
foreach (var mail in mails)
{
StringBuilder builder = new StringBuilder();
builder.Append(mail.EmailBody.ToString());
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(builder.ToString());
var nodes = doc.DocumentNode.SelectNodes("//table//tr");
DataTable dataTable = new DataTable();
var headers = nodes[0]
.Elements("th")
.Select(th => th.InnerText.Trim());
foreach (var header in headers)
{
dataTable.Columns.Add(header);
}
var rows = nodes.Skip(1).Select(tr => tr
.Elements("td")
.Select(td => td.InnerText.Trim())
.ToArray());
foreach (var row in rows)
{
dataTable.Rows.Add(row);
}
Console.WriteLine(dataTable.Rows);
Console.ReadLine();
}
}
Because you are just printing out the type of the object.
What else did you expect?
If you want to print out every column for every row in your dataTable, you must specify it.
Try this:
foreach (DataRow row in dataTable.Rows)
{
Console.WriteLine();
foreach (DataColumn col in dataTable.Columns)
{
Console.Write(row[col] + " ");
}
}
For further information: MS DataTable Docs

Datatable from List<Row>

I have downloaded data that is contained in a List<Row> Rows like this:
class Row
{
string[] Items { get; set; }
public Row(string[] Items)
{
this.Items = Items;
}
}
The rows are basically comma delimited entries (.csv)
using (var reader = new StreamReader(spreadSheetStream))
{
string header = reader.ReadLine(); //This is the header
Rows.Add(new Row(header.Split(',')));
while (!reader.EndOfStream)
{
string tickerInfo = reader.ReadLine(); //This is a data entry
Rows.Add(new Row(tickerInfo.Split(',')));
}
}
I convert the List<Row> into a Datatable like this
DataTable historicalDataTable = ToDataTable<Row>(Rows);
The first element of List<Row> Rows contains the names of the columns, seven of them. Then each element thereafter is an actual data element.
public static DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name);
//Get all the properties
PropertyInfo[] Props = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in Props)
{
//Setting column names as Property names
dataTable.Columns.Add(prop.Name);
}
foreach (T item in items)
{
var values = new object[Props.Length];
for (int i = 0; i < Props.Length; i++)
{
//inserting property values to datatable rows
values[i] = Props[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
}
//put a breakpoint here and check datatable
return dataTable;
}
When I try to write out the contents of the table, I see the right number of rows, but there is nothing in ItemArray
foreach (DataRow dataRow in historicalDataTable.Rows)
{
Console.WriteLine(dataRow.ToString());
foreach (var item in dataRow.ItemArray)
{
Console.WriteLine(item);
}
}
Your code is a bit contradictory. You are trying to copy properties as column names, however your csv code actually populates the first row as the column names. You have no distinction between header rows and data rows
You can just read it straight into a datatable with something like :-
(though you may want to do better error checking)
var dt = new DataTable("Rows");
string data = "a,b,c\r\n1,2,3\r\n4,5,6";
var stream = GenerateStreamFromString(data); // http://stackoverflow.com/questions/1879395/how-to-generate-a-stream-from-a-string
using (var reader = new StreamReader(stream))
{
reader.ReadLine()?.Split(',').ToList().ForEach(h => dt.Columns.Add(h));
while (!reader.EndOfStream)
{
dt.Rows.Add(reader.ReadLine()?.Split(',').ToArray());
}
}
foreach (DataColumn dataColumn in dt.Columns)
{
Console.Write($"{dataColumn.ColumnName} ");
}
Console.WriteLine();
foreach (DataRow dataRow in dt.Rows)
{
Console.Write("Row: ");
foreach (var item in dataRow.ItemArray)
{
Console.Write(item + " ");
}
Console.WriteLine();
}

C# KeyValue foreach column in row

I am here today trying to work out how I can do this. I have the code below to look through each column in a DataRow, but how can I access the key AND value? I want to assign it to a dictionary in the class but I can't seem to get both of them, the only way I can get anything is by calling:
var columnValue = playerDataRow[column];
Here is the full thing:
using (var mysqlConnection = Sirius.GetServer().GetDatabaseManager().GetConnection())
{
mysqlConnection.SetQuery("SELECT * FROM `users` WHERE `auth_ticket` = #authTicket LIMIT 1");
mysqlConnection.AddParameter("authTicket", authTicket);
var playerDataTable = mysqlConnection.GetTable();
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
foreach (DataColumn column in playerDataTable.Columns)
{
var columnValue = playerDataRow[column];
}
}
}
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
var myDic = new Dictionary<string, object>();
foreach (DataColumn column in playerDataTable.Columns)
{
myDic.Add(column.ColumnName, playerDataRow[column]);
}
}
the variable column will be the key and the value will be columnValue
looks that you only want one row of output - perhaps for this specific user based on auth_ticket
here is an example of how to get all values for this row into a Dictionary of strings (I'm converting all data to strings by the way just for this example)
var htRowValues = new Dictionary<string,string>();
using (var mysqlConnection = Sirius.GetServer().GetDatabaseManager().GetConnection())
{
mysqlConnection.SetQuery("SELECT * FROM `users` WHERE `auth_ticket` = #authTicket LIMIT 1");
mysqlConnection.AddParameter("authTicket", authTicket);
var playerDataTable = mysqlConnection.GetTable();
foreach (DataRow playerDataRow in playerDataTable.Rows)
{
foreach (DataColumn column in playerDataTable.Columns)
{
var columnValue = playerDataRow[column];
htRowValues[column.ColumnName]=System.Convert.ToString(columnValue);
}
}
}
now you have all column values in the dictionary for this one row of data.

Loop through DataTable and select only certain values in column

I have a DataTable from which I would like to loop through each row and column and then select a value from a specific column depending on the other values in the columns/each row.
My code currently looks like this:
foreach (DataRow drow in dt.Rows)
{
foreach (DataColumn dcol in dt.Columns)
{
foreach (var Item in ImportData)
{
if (Item.Value.Equals(true))
{
if (Item.Key.Equals("" + dcol))
{
string value = drow[dcol].ToString();
if (value.Equals("X"))
{
outDraws += drow["Drawing"].ToString();
outDraws += "\n";
}
}
}
}
}
}
ImportData is a Dictionary<string, bool>, which holds the data that I want to compare with my DataTable.
string outDraws is just a string which should hold the content of the drawings I want to print out.
My problem now is that I only want to print out the content in the column 'Drawing' of the row where all columns with the same name as the Keys in ImportData have 'X' as value. At the moment I'm getting all the rows where any of the columns have 'X' as value and has the same name as any Key in ImportData.
I understand that it will be quite hard for you to get what I want to do but please ask if you need any more information and I will try to provide.
Many thanks in advance.
Edit:
ImportData contains the name of different products as keys. These products have either been selected or not by the customer through another program, if they have been selected they have the value true and if not selected they have the value false.
With the method presented above I would like to compare ALL the keys that have the value true with the column names in the DataTable. If the column name corresponds to the key in ImportData (which is the name of a product) then I want to check if that column in a specific row has 'X' as value.
This goes on for ALL the keys in ImportData and in the end I should know which row in the DataTable that has an 'X' in all the columns with the same name as the keys in ImportData. For this row I would like to get the content of the column called 'Drawing'.
So for an example say that ImportData contains:
[Motor, true][Product6, true][Product7, true]
Then I would like to print out the column Drawing at row 6.
Unfortunately I can't post pictures..
As with any problem: divide and conquer. Break down your problem in smaller pieces and go from there.
From what I understand, you want to do something with certain rows from the datatable. Something like:
foreach (var drow in dt.Rows.OfType<DataRow>())
{
if (SomeConditionIsMet(dt, drow, ImportData))
{
outDraws += drow["Drawing"].ToString();
outDraws += "\n";
}
}
The function SomeConditionIsMetcould looks like this:
private static bool SomeConditionIsMet(
DataTable dt, DataRow drow,
IDictionary<string, bool> importData)
{
// TODO if the condition is met, return true
// otherwise, return false
}
Now your problem is simplified to thinking about what it means that 'Some condition is met'. Once you can clearly express that in words, rename the function to reflect that (e.g. to 'AllColumnsAreChecked')
Here's a sample with solution as I understand it:
internal class Program
{
private static void Main(string[] args)
{
var importData = new Dictionary<string, bool>()
{
{"Product1", true},
{"Product2", false},
{"Product3", true},
};
var dt = new DataTable();
dt.Columns.Add("Product1");
dt.Columns.Add("Product2");
dt.Columns.Add("Product3");
dt.Columns.Add("Product4");
dt.Columns.Add("Drawing");
// row1 should be added
var row1 = dt.NewRow();
row1["Product1"] = "X";
row1["Product3"] = "X";
row1["Drawing"] = "Drawing1";
dt.Rows.Add(row1);
// row2 should not be added
var row2 = dt.NewRow();
row2["Product1"] = "X";
row2["Drawing"] = "Drawing2";
dt.Rows.Add(row2);
string outDraws = string.Empty;
foreach (DataRow drow in dt.Rows.OfType<DataRow>())
{
if (AllColumnsAreChecked(drow, importData))
{
outDraws += drow["Drawing"].ToString();
outDraws += "\n";
}
}
Console.WriteLine(outDraws);
}
private static bool AllColumnsAreChecked(DataRow drow, Dictionary<string, bool> importData)
{
foreach (var key in importData.Keys)
{
if (!importData[key])
continue;
var value = drow[key] as string;
if (value != "X")
return false;
}
}
}
Bonus: here's a LINQ based implementation of the check:
private static bool AllColumnsAreChecked(DataRow drow, Dictionary<string, bool> importData)
{
return importData.Keys
.Where(k => importData.ContainsKey(k) && importData[k]) // the field must be enabled in importData
.All(k => (drow[k] as string) == "X"); // the corresponding value in the row must be 'X'
}
Try this
DataTable tbl = new DataTable();
foreach (DataRow row in tbl.Rows)
{
object cellData = row["colName"];
}

Should I Convert excel to csv or write htmltable to csv

I have 10 reports in my application which I let users to export to excel. I have never written CSV files. In my existing application, I convert the results from the stored procedure to an HTML table and write it to Excel. Some of my results from the stored procedures have dynamic columns so I use dapper. My new requirement is to provide CSV export as well.
So should I first convert html datatable to excel and convert it to CSV or write HTML datatable to CSV. I dont want to manually parse because there are 10 different reports with different columns and some of the reports have dynamic columns so I cant manually parse.
Stored procs returning Dapper, Dynamic Columns
EFDbContext db = new EFDbContext();
var recordDate = StartDate.Date;
var cnn = new SqlConnection(db.Database.Connection.ConnectionString);
cnn.Open();
var p = new DynamicParameters();
p.Add("#StartDate", StartDate);
p.Add("#UserRoleID", UserRoleID);
p.Add("#SelectedSystemIDs", SelectedSystemIDs);
p.Add("#SelectedPartIDs", SelectedPartIDs);
p.Add("#SelectedSubSystems", SelectedSubsystems);
p.Add("#SelectedServiceTypes", SelectedServiceTypes);
var obs = cnn.Query(sql: "spExportInstrumentConfigAll", param: p, commandType: CommandType.StoredProcedure);
var dt = ToDataTable(obs);
return ExportDatatableToHtml(dt);
public static DataTable ToDataTable(IEnumerable<dynamic> items)
{
if (items == null) return null;
var data = items.ToArray();
if (data.Length == 0) return null;
var dt = new DataTable();
foreach (var pair in ((IDictionary<string, object>)data[0]))
{
dt.Columns.Add(pair.Key, (pair.Value ?? string.Empty).GetType());
}
foreach (var d in data)
{
dt.Rows.Add(((IDictionary<string, object>)d).Values.ToArray());
}
return dt;
}
public static string ExportDatatableToHtml(DataTable dt)
{
StringBuilder strHTMLBuilder = new StringBuilder();
strHTMLBuilder.Append("<html >");
strHTMLBuilder.Append("<head>");
strHTMLBuilder.Append("</head>");
strHTMLBuilder.Append("<body>");
strHTMLBuilder.Append("<table border='1px' cellpadding='1' cellspacing='1 style='font-family:Garamond; font-size:medium'>");
strHTMLBuilder.Append("<tr >");
foreach (DataColumn myColumn in dt.Columns)
{
strHTMLBuilder.Append("<td >");
strHTMLBuilder.Append(myColumn.ColumnName);
strHTMLBuilder.Append("</td>");
}
strHTMLBuilder.Append("</tr>");
foreach (DataRow myRow in dt.Rows)
{
strHTMLBuilder.Append("<tr >");
foreach (DataColumn myColumn in dt.Columns)
{
strHTMLBuilder.Append("<td >");
strHTMLBuilder.Append(myRow[myColumn.ColumnName].ToString());
strHTMLBuilder.Append("</td>");
}
strHTMLBuilder.Append("</tr>");
}
//Close tags.
strHTMLBuilder.Append("</table>");
strHTMLBuilder.Append("</body>");
strHTMLBuilder.Append("</html>");
string Htmltext = strHTMLBuilder.ToString();
return Htmltext;
}
Non-Dynamic Columns mapped to entity
return db.Database.SqlQuery<ServiceEntryPartExportDataRow>("[dbo].[spExportServiceParts] #parm1, #parm2, #parm3, #parm4,#parm5,#parm6",
new SqlParameter("parm1", StartDate),
new SqlParameter("parm2", EndDate),
new SqlParameter("parm3", Reconciled),
new SqlParameter("parm4", ServiceTypes),
new SqlParameter("parm5", SelectedSystemIDs),
new SqlParameter("parm6", UserRoleID)
).ToList().ToHTMLTable();
public static string ToHTMLTable<T>(this IList<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
StringBuilder builder = new StringBuilder();
builder.Append("<table border=\"1\">");
builder.Append("<tr>");
for (int i = 0; i < props.Count; i++)
{
builder.Append("<td>");
PropertyDescriptor prop = props[i];
builder.Append(prop.Name);
builder.Append("</td>");
}
builder.Append("</tr>");
object[] values = new object[props.Count];
foreach (T item in data)
{
builder.Append("<tr>");
for (int i = 0; i < values.Length; i++)
{
builder.Append("<td>");
builder.Append(props[i].GetValue(item));
builder.Append("</td>");
}
builder.Append("</tr>");
}
builder.Append("</table>");
return "<html><body>" + builder.ToString() + "</body></html";
}
Current code Sending to Excel
return new PostActionResult(htmlTable, "ServiceEntryHistory", submit);
public PostActionResult(string htmlTable, string typeName, string submit) { this.htmlTable = htmlTable; this.typeName = typeName; this.submit = submit; }
public PostActionResult(DataTable dataTable, string typeName, string submit) { this.dataTable = dataTable; this.typeName = typeName; this.submit = submit; }
public override void ExecuteResult(ControllerContext context)
{
if (submit == "Excel")
{
ExcelHelpers.ExportToExcel(context.HttpContext, typeName, htmlTable);
}
if (submit == "CSV")
{
ExcelHelpers.ExportToExcelCSV(context.HttpContext, typeName, htmlTable);
}
}
public static void ExportToExcel(HttpContextBase httpBase, string fileNamePrefix, string table)
{
string TimeStamp = DateTime.Now.ToLocalTime().ToString();
string fileName = string.Format("attachment;filename={0}_{1}.xls", fileNamePrefix, TimeStamp);
httpBase.Response.ClearHeaders();
httpBase.Response.ClearContent();
httpBase.Response.Clear();
httpBase.Response.AddHeader("content-disposition", fileName);
httpBase.Response.ContentType = "application/vnd.ms-excel";
httpBase.Response.Write(table);
httpBase.Response.End();
}
You already have code to build an HTML table from the data. Building a CSV is very nearly identical. For brevity, let's simplify the HTML table pseudo-code:
builder.Append("<table>");
// header
builder.Append("<tr>");
foreach (var column in columns)
builder.Append("<th>" + column.name + "</th>");
builder.Append("</tr>");
// rows
foreach (var row in rows)
{
builder.Append("<tr>");
foreach (var column in row.columns)
builder.Append("<td>" + column.value + "</td>");
builder.Append("</tr>");
}
builder.Append("</table>");
Building a CSV is the exact same structure:
// header
foreach (var column in columns)
builder.Append("\"" + column.name + "\",");
// there's now an extra comma at the end. remove it, or use a
// different method to have built the row, such as string.Join.
// rows
foreach (var row in rows)
{
foreach (var column in row.columns)
builder.Append("\"" + column.value + "\",");
// there's now an extra comma at the end. remove it, or use a
// different method to have built the row, such as string.Join.
builder.Append(Environment.NewLine);
}
Remember that this is free-hand pseudo-code, there are some clean-ups you can employ. You might also check the column types to determine if you need those escaped quotes or not, since numeric types wouldn't want them. But the point is that the structure is the same. A CSV is text in the same way that HTML is text. It's only the dressing around the values that's different.
Side note: This is actually a classic example of the Template Method Pattern.

Categories

Resources