Generating Dynamic Table Rows for HTML Table - c#

Im having a Html Email Template for Invoice Like Bellow.
<table border="1">
<thead>
<tr>
<td>Item ID</td>
<td>Name</td>
<td>Qty</td>
<td>Unit Price</td>
</tr>
</thead>
<tbody>
<tr>
<td>{ItemID}</td>
<td>{Name}</td>
<td>{Qty}</td>
<td>{UnitPrice}</td>
</tr>
</tbody>
</table>
I have an Item List with 5 Items,
List<ItemList> ItemList = new List<ItemList>();
The class Structure for Item List
public Class ItemList{
public int ItemID {get;set;}
public string Name {get;set;}
public int Qty {get;set;}
public decimal UnitPrice {get;set}
}
My Question is how to dynamically generate the table rows for the tbody based on the item list which i have by replacing the values with {ItemID},{Name},{Qty},{UnitPrice}?
Im using ASp.Net MVC4, I have came across a library called Html Agility Pack, please any body let me know how to archive this using Html Agility Pack.

Related

How to Retrieve Specific table from HTML FILE in c#?

I have an HTML file that contains many tables, but I want to access a specific table from the file (not all tables).
So how can I do that?
Code is look something like below and all tables are without ids
`<table border=1>
<tr><td>VI not loadable</td><td>0</td></tr>
<tr><td>Test not loadable</td><td>0</td></tr>
<tr><td>Test not runnable</td><td>0</td></tr>
<tr><td>Test error out</td><td>0</td></tr>
</table>`
every table should have an Id or something that could be Identified from the others, if so you can get it via jquery. for example :
<table class="table table-striped" id="tbl1">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
and get it like this:
var table = $('#tbl1').html();
if not you can find it by its priority in the file. for example you can access to 2nd table like this :
var table = $('table:nth-child(2)')
or in C# maybe this would help:
HtmlNode table = doc.DocumentNode.SelectSingleNode("//table[1]")
foreach (var cell in table.SelectNodes(".//tr/td"))
{
string someVariable = cell.InnerText
}

c# - html "nested table" in class

WebClient client = new WebClient();
var data = client.DownloadString("a web link");
and i am getting an HTML page in which there's a table like this
<table>
<tr>
<td> Team 1 ID </td>
<td> Team 1 Name </td>
<td>
<table>
<tr>
<td> Member 1 name </td>
<td> Member 1 age </td>
</tr>
<tr>
<td> Member 2 name </td>
<td> Member 2 age </td>
</tr>
</table>
</td>
</tr>
<tr>
<td> Team 2 ID </td>
<td> Team 2 Name </td>
<td>
<table>
<tr>
<td> Member 1 name </td>
<td> Member 1 age </td>
</tr>
</table>
</td>
</tr>
that means another table in each row of main table so i called it nested table.
whatever, now i want to get these data into class like this
class Team
{
public int teamID;
public string teamName;
public struct Member
{
public string memberName;
public int memberAge;
}
public Member member1;
public Member member2;
}
note that, each team might have 0 to 3 members
so i am seeking for a sound solution that can solve my problem.
should i use RegEx or HtmlAgilityPack or which way is appropriate and how?
thanks in advance
Just use HtmlAgilityPack. If you run into any troubles, I can help you.
Regular expressions can only match regular languages but HTML is a
context-free language. The only thing you can do with regexps on HTML
is heuristics but that will not work on every condition. It should be
possible to present a HTML file that will be matched wrongly by any
regular expression.
Using regular expressions to parse HTML: why not?
It will be easier if your html contains any identifiers (css classes or id)
Updated code: Here is my suggestion to approach your problem
string mainURL = "your url";
HtmlAgilityPack.HtmlWeb web = new HtmlAgilityPack.HtmlWeb();
HtmlAgilityPack.HtmlDocument doc = web.Load(mainURL);
var tables = doc.DocumentNode.Descendants("table").Where(_ => _.Descendants("table").Any());//this will give you all tables which contain another table inside
foreach (var table in tables)
{
var rows = table.ChildNodes.Where(_ => _.Name.Equals("tr"));//get all tr children (not grand children)
foreach (var row in rows)
{
for (int i = 0; i < row.ChildNodes.Count; i++)
{
if (row.ChildNodes[i].Name.Equals("td"))
{
//you can put your logic here, for eg i == 0, assign it to TeamID properties etc...
}
if (row.ChildNodes[i].Name.Equals("table"))
{
//here is your logic to handle nested table
}
}
}
}

Sort DateTime object in DD/MM/YYYY format in .cshtml file

I currently have a for-loop in my .cshtml file which iterates through items inside a ViewBag. I want to sort these objects based on a DateTime property called orderDate in the Order.cs file. The for loop in the .cshtml file looks like the following:
<table id="order-history-table" class="table table-hover">
<thead>
<tr>
<th>
Order Number
</th>
<th>
Order Date
</th>
<th>
Order Total
</th>
</tr>
</thead>
<tbody>
#foreach (var item in ViewBag.list)
{
<tr>
<td>
<a class="orderNumber" data-toggle="modal" data-target="#modal-container" href="#Url.Action("orderDetails", "Orders", new { orderNumber = item.order.OrderNumber })">#item.order.OrderNumber</a>
<br />
#Html.ActionLink("Re-Order", "ReOrder", new { orderNumber = #item.order.OrderNumber }, new { onclick = "return confirm('Are you sure you wish to re-order?');" })
</td>
<td>#item.order.OrderDate.ToString("dd/MM/yyyy")</td>
<td style="text-align: center">$#(Math.Round(item.order.OrderTotal, 2))</td>
</tr>
}
</tbody>
I want this table to be sorted so that the most recent orders are shown at the top of the table. Since the data is being pulled from a database, and the tables values are generated dynamically, where do I perform this sorting? is it done through jQuery? How do I do this?
Thank you in advance
You can use LINQ OrderBy to do that.
So in your action method where you set the ViewBag.list, You can use OrderByDescending method on the collection.
var yourOrderList=new List<Order>();
// to do : Load Order items to yourOrderList
yourOrderList=yourOrderList.OrderByDescending(f=>f.OrderDate).ToList();
ViewBAg.list=yourOrderList;
I also recommend using a view model to pass data from your action method to view.
var yourOrderList=new List<Order>();
// to do : Add orders to yourOrderList
yourOrderList=yourOrderList.OrderByDescending(f=>f.OrderDate).ToList();
return View(yourOrderList);
And in your view
#model List<Order>
<h3>Orders</h3>
#foreach(var o in Model)
{
<p>#o.OrderDate.ToString()</p>
}
Since your view is strongly typed, you can do the same ordering in your razor view also as needed.
#model List<Order>
<h3>Orders</h3>
#foreach(var o in Model.OrderByDescending(g=>g.OrderDate))
{
<p>#o.OrderDate.ToString()</p>
}

C#, convert columns to one row in a list

Ok, here is the situation: I've got a C# partial class that returns a list of objects, using the .Select().ToList() functionality.
I get how this works.
The issue that I'm running into, though, is that there are four properties in the class that I need to use in one column. To compound this, each column is supposed to be tied to a row, which displays a lot of redundant information.
An example helps:
I currently have this, let's say, as my class:
public class MyClass{
public string PersonName {get;set;}
public string PersonAddress {get;set;}
public string Field1 {get;set;}
public string Field2 {get;set;}
public string Field3 {get;set;}
public string Field4 {get;set;}
}
That gives you a basic idea of my class. My original suggestion was do set the code up where it did this:
<table>
<tr>
<td>Name</td>
<td>Address</td>
<td>Field 1<br>Field 2<br>Field 3<br>Field 4</td>
</tr>
</table>
Which makes sense.
However, those above me have decided that they want a layout like this:
<table>
<tr>
<td>Name</td>
<td>Address</td>
<td>Field 1</td>
</tr>
<tr>
<td>Name</td>
<td>Address</td>
<td>Field 2</td>
</tr>
<tr>
<td>Name</td>
<td>Address</td>
<td>Field 3</td>
</tr>
<tr>
<td>Name</td>
<td>Address</td>
<td>Field 4</td>
</tr>
</table>
Where, if you'll notice, Name and Address are redundant for each row.
So, how could I do this in C#?
You can use LINQ SelectMany method to generate a list that contains 4 objects per a single MyClass object like this:
List<MyClass> list = ...
var result = list.SelectMany(x =>
new[]
{
new {x.PersonAddress, x.PersonName, Value = x.Field1},
new {x.PersonAddress, x.PersonName, Value = x.Field2},
new {x.PersonAddress, x.PersonName, Value = x.Field3},
new {x.PersonAddress, x.PersonName, Value = x.Field4}
}).ToList();
This will return a list of anonymous type objects.
Each one of these objects will contain a PersonAddress, a PersonName, and a Value property.
You can then loop over them to generate the HTML that you want.

How to get a link's title and href value separately with html agility pack?

Im trying to download a page contain a table like this
<table id="content-table">
<tbody>
<tr>
<th id="name">Name</th>
<th id="link">link</th>
</tr>
<tr class="tt_row">
<td class="ttr_name">
<a title="name_of_the_movie" href="#"><b>name_of_the_movie</b></a>
<br>
<span class="pre">message</span>
</td>
<td class="td_dl">
<img alt="Download" src="#">
</td>
</tr>
<tr class="tt_row"> .... </tr>
<tr class="tt_row"> .... </tr>
</tbody>
</table>
i want to extract the name_of_the_movie from td class="ttr_name" and download link from td class="td_dl"
this is the code i used to loop through table rows
HtmlAgilityPack.HtmlDocument hDocument = new HtmlAgilityPack.HtmlDocument();
hDocument.LoadHtml(htmlSource);
HtmlNode table = hDocument.DocumentNode.SelectSingleNode("//table");
foreach (var row in table.SelectNodes("//tr"))
{
HtmlNode nameNode = row.SelectSingleNode("td[0]");
HtmlNode linkNode = row.SelectSingleNode("td[1]");
}
currently i have no idea how to check the nameNode and linkNode and extract data inside it
any help would be appreciated
Regards
I can't test it right now, but it should be something among the lines of :
string name= namenode.Element("a").Element("b").InnerText;
string url= linknode.Element("a").GetAttributeValue("href","unknown");
nameNode.Attributes["title"]
linkNode.Attributes["href"]
presuming you are getting the correct Nodes.
public const string UrlExtractor = #"(?: href\s*=)(?:[\s""']*)(?!#|mailto|location.|javascript|.*css|.*this\.)(?<url>.*?)(?:[\s>""'])";
public static Match GetMatchRegEx(string text)
{
return new Regex(UrlExtractor, RegexOptions.IgnoreCase).Match(text);
}
Here is how you can extract all Href Url. I'm using that regex in one of my projects, you can modify it to match your needs and rewrite it to match title as well. I guess it is more convenient to match them in bulk

Categories