How to get the value of the table using HtmlAgilityPack - html

i Need to get the content of the table. Below is my table
<tr class="oddRow" id="activeFiles25472825Row">
<td>Author Photo</td>
<td></td>
<td>
<div id="active_25472825_CALLOUT" class="fileTruncateCallout" style="position:absolute; display:none">JCS.jpg</div>
</td>
<td>01/28/2017</td>
<td>30.7 KB</td>
<td>Member</td>
<td>
download
</td>
</tr>
Here is my code. But i don't know what's next. I tried getting the value i need but i can't make it work. it didn't give me output, or error
HtmlAgilityPack.HtmlDocument newdoc = new HtmlAgilityPack.HtmlDocument();
newdoc.LoadHtml(htmlString);
GeckoElementCollection links = wb.Document.GetElementsByTagName("td");
foreach (var itm in links)
{
}
And the output
is
Name: JCS.jpg
Link: https://google.com.download

You can try something like this, I didn't test it but hopefully you understand the idea behind
foreach (var td in newDoc.DocumentNode.Descendants("td"))
{
var div = td.ChildNodes.FirstOrDefault(c => c.Name.Equals("div") && c.GetAttributeValue("class", "").Equals("fileTruncateCallout"));
if (div != null)
{
var name = div.InnerText;
}
else
{
var aNode = td.ChildNodes.FirstOrDefault(c => c.Name.Equals("a"));
if(aNode != null)
{
var href = aNode.GetAttributeValue("href", "");
}
}
}

Related

How can I change with onclick event of a <td>the color of the td? The critical point is that the td elements are generated dynamically with code

In my Blazor server app, I am reading the CNC Files of a remote machine and listing them in the table's rows.
So far everything is OK.
When the user clicks on one TD element, the content of the CNC file will be shown on the screen in another table(This part I have not shown because it is not related to my problem)
I want that the last choosen CNC file (last clicked ) should be highlighted (font=red).
That means each time when the user selects another CNC-File, just the related should be higlighted all others should be in default color (black).
If I would have a static table I would use the a:focus. But my problem is that my td's will be generated dynamically. And I have to apply the a:focus function for just one td (that was clicked).
How can I do that?
I have tried to call a function in the style of the td style="#Style_CNC_File()" but the colors that I define in the function are applied to all of the td's.
Here is my code:
<table >
<tr>
<td>CNC Files</td>
</tr>
#{ if (Deltalogic.Return_Read_CNC_File == 0 && Deltalogic.Selected_CNC_File_Path_Type == "file")
{
for (var i = 0; i < Deltalogic.CNC_File_Array_lenght_dir - 1; i++)
{
var arg0 = "abc";
var arg1 = "def";
var arg2 = "ghi";
<tr >
<td style="#Style_CNC_File()" #onclick='#(e => Read_CNC_Files(arg0,arg1,arg2))'>/#Deltalogic.CNC_File_Out_Array_dir[i]</td>
</tr>
}
}
}
</table>
In my razor.cs file:
public string Style_CNC_File()
{
if (var_clicked == true)
{
return "color:#FF0000";
}
else
{
return "color:#000000";
}
}
Maybe you can set an id to your td and store the selected id :
<tr>
<td>CNC Files</td>
</tr>
#{ if (Deltalogic.Return_Read_CNC_File == 0 && Deltalogic.Selected_CNC_File_Path_Type == "file")
{
for (var i = 0; i < Deltalogic.CNC_File_Array_lenght_dir - 1; i++)
{
var arg0 = "abc";
var arg1 = "def";
var arg2 = "ghi";
<tr >
<td #onclick='#(e => HandleClick(i, arg0,arg1,arg2))' style="#Getstyle(i)">/#Deltalogic.CNC_File_Out_Array_dir[i]</td>
</tr>
}
}
}
</table>
#code {
int selectedId = -1;
void HandleClick(int id, string args0, string args1, string args2)
{
selectedId = i;
Read_CNC_Files(arg0,arg1,arg2);
}
void Getstyle(int id)
{
if (selectedId == i)
return "background-color:red;";
return string.Empty;
}
}
You can change the class or style as you want according to the index of the line.

How to export multiple HTML tables into a single excel file, along with the html table's css/style?

I know there are a lot of this type of question in this site, but i cant find any working solution for this that suit my need. What i need is
1. export multiple html table to excel
2. the table in the excel look exactly like the html table (the css, styling are the same. e.g background-color)
Is there any way to do this using javascript,etc.?
I found one question for this problem here, but the solution shown there did not solve the css problem. Means that the excel table not have the css like the html table (e.g The excel table doesnt have yellow background eventhough the html table have it)
So basically the main problem is I need the format for the excel file to be same as the html table (css,etc.). Sorry I am new to programming..
Here you can access the jsfiddle. Or if the link doesnt work, you can just try it below (The codes are taken from the original post , but with an addition of a simple yellow-colored background css in it's tr)Thanks in advance.
var tablesToExcel = (function() {
var uri = 'data:application/vnd.ms-excel;base64,'
, tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
+ '<Styles>'
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
+ '</Styles>'
+ '{worksheets}</Workbook>'
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{rows}</Table></Worksheet>'
, tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>'
, base64 = function(s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function(s, c) { return s.replace(/{(\w+)}/g, function(m, p) { return c[p]; }) }
return function(tables, wsnames, wbname, appname) {
var ctx = "";
var workbookXML = "";
var worksheetsXML = "";
var rowsXML = "";
for (var i = 0; i < tables.length; i++) {
if (!tables[i].nodeType) tables[i] = document.getElementById(tables[i]);
for (var j = 0; j < tables[i].rows.length; j++) {
rowsXML += '<Row>'
for (var k = 0; k < tables[i].rows[j].cells.length; k++) {
var dataType = tables[i].rows[j].cells[k].getAttribute("data-type");
var dataStyle = tables[i].rows[j].cells[k].getAttribute("data-style");
var dataValue = tables[i].rows[j].cells[k].getAttribute("data-value");
dataValue = (dataValue)?dataValue:tables[i].rows[j].cells[k].innerHTML;
var dataFormula = tables[i].rows[j].cells[k].getAttribute("data-formula");
dataFormula = (dataFormula)?dataFormula:(appname=='Calc' && dataType=='DateTime')?dataValue:null;
ctx = { attributeStyleID: (dataStyle=='Currency' || dataStyle=='Date')?' ss:StyleID="'+dataStyle+'"':''
, nameType: (dataType=='Number' || dataType=='DateTime' || dataType=='Boolean' || dataType=='Error')?dataType:'String'
, data: (dataFormula)?'':dataValue
, attributeFormula: (dataFormula)?' ss:Formula="'+dataFormula+'"':''
};
rowsXML += format(tmplCellXML, ctx);
}
rowsXML += '</Row>'
}
ctx = {rows: rowsXML, nameWS: wsnames[i] || 'Sheet' + i};
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
}
ctx = {created: (new Date()).getTime(), worksheets: worksheetsXML};
workbookXML = format(tmplWorkbookXML, ctx);
console.log(workbookXML);
var link = document.createElement("A");
link.href = uri + base64(workbookXML);
link.download = wbname || 'Workbook.xls';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
})();
<table id="tbl1" class="table2excel">
<tr style="background-color:yellow;">
<td>Product</td>
<td>Price</td>
<td>Available</td>
<td>Count</td>
</tr>
<tr>
<td>Bred</td>
<td>1
</td>
<td>2
</td>
<td>3
</td>
</tr>
<tr>
<td>Butter</td>
<td>4
</td>
<td>5
</td>
<td >6
</td>
</tr>
</table>
<hr>
<table id="tbl2" class="table2excel">
<tr>
<td>Product</td>
<td>Price</td>
<td>Available</td>
<td>Count</td>
</tr>
<tr>
<td>Bred</td>
<td>7
</td>
<td>8
</td>
<td>9
</td>
</tr>
<tr>
<td>Butter</td>
<td>14
</td>
<td>15
</td>
<td >16
</td>
</tr>
</table>
<button onclick="tablesToExcel(['tbl1','tbl2'], ['ProductDay1','ProductDay2'], 'TestBook.xls', 'Excel')">Export to Excel</button>
Found the solution for this. I use the DataTables. Read more here DataTables forum

Navigate through form with arrow keys

I have a html form, which is created like a table (with rows and columns). Basically it looks like excel.
And now I would like to navigate just like in excel with the arrow keys. Is that possible?
<table>
<tr>
<td/>
<td/>
</tr>
<tr>
<td/>
<td/>
</tr>
</table>
Yes, it was easy, once I got your tips. This is my solution:
var UP = 38;
var DOWN = 40;
var LEFT = 37;
var RIGHT = 39;
var TAB = 9;
$('#tab-columns').on('keydown', 'input', function (event) {
var $focused = $(':focus');
var id = ($focused.parents("td").attr('id'));
if (id.startsWith("field_")) {
idArr = id.replace("field_", "").split("_");
row = Number(idArr[0]);
col = Number(idArr[1]);
newId = id;
switch (event.which) {
case UP:
newId = "field_"+(row-1)+"_"+col;
break;
case DOWN:
newId = "field_"+(row+1)+"_"+col;
break;
case TAB:
case RIGHT:
newId = "field_"+row+"_"+(col+1);
break;
case LEFT:
newId = "field_"+row+"_"+(col-1);
break;
default:
// nothing
}
$("#"+newId).find("input").focus();
}

Splitting foreach in a table

As of right now my table looks like this:
But I want to split the foreach to have it look something like this
Is possible to do this?
And this is the foreach:
#foreach (var date in ViewBag.MissingDays)
{
var isoDate = date.ToString("yy-MM-dd");
<tr>
<td>
#isoDate
</td>
</tr>
}
You can use the following code to generate rows containing 9 columns
#{var counter = 1; }
<tr>
#foreach (var date in ViewBag.MissingDays)
{
var isoDate = date.ToString("yy-MM-dd");
<td>#isoDate</td>
if (counter % 9 == 0)
{
#:</tr><tr> // end current row and begin new one
}
counter++;
}
</tr>

Using HtmlAgilityPack to get the last <tr> of a html table

I have a html table stucture. I need to get the value of the value of the first <td> in the final <tr> tag. Here is my table structure. The value I require from the below function getFinalNodeValue is "3".
<table id="test">
<tr>
<td>ID</td>
<td>Name</td>
<td>Age</td>
</tr>
<tr>
<td>1</td>
<td>Yasoda</td>
<td>21</td>
</tr>
<tr>
<td>2</td>
<td>Samantha</td>
<td>25</td>
</tr>
<tr>
<td>3</td>
<td>Sajee</td>
<td>26</td>
</tr>
</table>
Here is the code I wrote using HtmlAgilityPack.
public String getFinalNodeValue(String URL)
{
var webGet = new HtmlWeb();
var pageSource = webGet.Load(URL);
var table = pageSource.DocumentNode.SelectSingleNode("//table[#id='test']//tr[1]");
string id = null;
IEnumerable<HtmlNode> trNodes = table.DescendantsAndSelf();
foreach (var currentItem in trNodes)
{
if (currentItem == trNodes.Last())
{
IEnumerable<HtmlNode> tdNodes = currentItem.Descendants();
foreach (var x in tdNodes)
{
if(x == tdNodes.First())
{
id = x.InnerText;
}
else
{
break;
}
}
}
else
{
continue;
}
}
return id;
}
The method doesn't return a value. Any help is highly appreciated.
This should do it:
HtmlDocument doc = new HtmlDocument();
doc.Load(MyHtmlFile);
HtmlNode node = doc.DocumentNode.SelectSingleNode("//table[#id='test']/tr[last()]/td");
Console.WriteLine(node.InnerText);
Note the usage of the XPATH last() function
The XPath you use to populate the table variable - "//table[#id='test']//tr[1]", selects the second TR element, no the table.
This most likely should just be "//table[#id='test']".
At this point, to fetch the descendant TR nodes into the trNodes variable, you should use:
IEnumerable<HtmlNode> trNodes = table.SelectNodes("tr");
if you change your table like this:
<table id="test" runat="server">
You can iterate over it in the codebehind, like this:
HtmlTable myTable = this.test;
int rowCount = myTable.Rows.Count;
HtmlTableCell td = myTable.Rows(rowCount - 1).Cells(0);
string val = td.InnerText;