Scrape data from local HTML file - c#

I am trying to extract the values for Design Capacity mWh and Full Charged Capacity mWh from windows battery-report.html the HTML document stores these values in a table but with no attribute name I can easily access
I do have AngleSharp added but don't have much idea how to use it in this case to get the data I need it may not be right for the job though.
</td>
</tr></thead>
<tr>
<td><span class="label">NAME</span></td>
<td>Blade</td>
</tr>
<tr>
<td><span class="label">MANUFACTURER</span></td>
<td>Razer</td>
</tr>
<tr>
<td><span class="label">SERIAL NUMBER</span></td>
<td>CNB1RC30-027097A00283-A05</td>
</tr>
<tr>
<td><span class="label">CHEMISTRY</span></td>
<td>Li-I</td>
</tr>
<tr>
<td><span class="label">DESIGN CAPACITY</span></td>
<td>65,003 mWh
</td>
</tr>
<tr style="height:0.4em;"></tr>
<tr>
<td><span class="label">FULL CHARGE CAPACITY</span></td>
<td>72,395 mWh
</td>
</tr>
<tr>
<td><span class="label">CYCLE COUNT</span></td>
<td>
I generate the battery report and pass that togetBattery
private void BatteryHealthBtn_Click(object sender, EventArgs e)
{
string designCap = null;
string fullCap = null;
ManagementObjectSearcher mybatteryObject = new ManagementObjectSearcher("select * from Win32_Battery");
foreach (ManagementObject obj in mybatteryObject.Get())
{
if (obj["DesignCapacity"] != null || obj["FullChargeCapacity"] != null)
{
designCapTxt.Text = obj["DesignCapacity"].ToString();
fullCapTxt.Text = obj["FullChargeCapacity"].ToString();
}
else
{
MessageBox.Show("No WMI Data Found Running Manually", "Error No WMI",
MessageBoxButtons.OK, MessageBoxIcon.Error);
var saveLocation = System.AppDomain.CurrentDomain.BaseDirectory + "battery-report.html";
if (saveLocation != null)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C powercfg /batteryreport /output " + '"' + saveLocation + '"';
process.StartInfo = startInfo;
process.Start();
System.Diagnostics.Process.Start(saveLocation);
GetBattery(saveLocation);
}
}
}
}
Image of the Hmtl Document
public async void GetBattery(string html)
{
var config = Configuration.Default.WithDefaultLoader();
string address = html;
IDocument document = await
BrowsingContext.New(config).OpenAsync(address);
var designCap = document.GetElementsByClassName("label");
MessageBox.Show(designCap.ToString(), "a",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
think i am getting closer with this but getting null reference still on line 4
var config = Configuration.Default.WithDefaultLoader();
var address = html;
var document = await BrowsingContext.New(config).OpenAsync(address);
var cellSelector = "tr td:nth-child(2)";
var cells = document.QuerySelectorAll(cellSelector);
var designCap = cells.Select(m => m.TextContent);

had to swap over to html agility pack but i got it
HtmlAgilityPack.HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
// There are various options, set as needed
htmlDoc.OptionFixNestedTags = true;
// filePath is a path to a file containing the html
htmlDoc.Load(saveLocation);
foreach (HtmlNode table in htmlDoc.DocumentNode.SelectNodes("//table"))
{
foreach (HtmlNode row in table.SelectNodes("tr"))
{
if(row.InnerText.Contains("DESIGN CAPACITY"))
{
designCapTxt.Text = row.InnerText;
}
if (row.InnerText.Contains("FULL CHARGE CAPACITY"))
{
fullCapTxt.Text = row.InnerText;
}
}
}

Related

How to populate HTML table with SPQuery result

I've just started playing with developing in SP2010, so I'm complete begginer .
I've created simple console application with code like this :
using (SPSite currentSite = new SPSite("http://win-e9840laitme"))
{
using (SPWeb currentWeb = currentSite.OpenWeb())
{
SPList myList = currentWeb.Lists["List1"];
string currentUserName = currentWeb.CurrentUser.Name;
SPQuery queryInformationAboutCurrentUser = new SPQuery();
queryInformationAboutCurrentUser.Query = "<Where>" +
"<Eq><FieldRef Name='EmployeeName'/><Value Type='Text'>" + currentUserName + "</Value></Eq>" +
"</Where>";
List<EmployeeInfo> listEmployeeInfo = new List<EmployeeInfo>();
SPListItemCollection collectionEmployee = myList.GetItems(queryInformationAboutCurrentUser);
foreach (SPListItem info in collectionEmployee)
{
EmployeeInfo eInfo = new EmployeeInfo();
eInfo.Deparment = info["Office"].ToString();
listEmployeeInfo.Add(eInfo);
}
foreach (EmployeeInfo eI in listEmployeeInfo)
{
SPQuery querySameOffice = new SPQuery();
querySameOffice.Query = "<Where>" +
"<Eq><FieldRef Name='Office'/><Value Type='Choice'>" + eI.Deparment + "</Value></Eq>" +
"</Where>";
SPListItemCollection collectionEmployeeDisplay = myList.GetItems(querySameOffice);
foreach (SPListItem item in collectionEmployeeDisplay)
{
Console.WriteLine(item["EmployeeName"].ToString() + " " + item["PhoneNumber"].ToString() + "\n");
}
}
}
}
Now I want to use that code inside sharepoint project , and instead of putting result of SPQuery on Console , I want to populate HTML table with the result staticly(without JS or Jquery , if it is possible).
I've created sp project and added ApplicationPage.
My idea was to use StringBuilder and something like this :
StringBuilder html = new StringBuilder();
html.Append("<table border = '1'>");
//Building the Header row.
html.Append("<tr>");
html.Append("<th>");
html.Append("EmployeeName");
html.Append("</th>");
html.Append("<th>");
html.Append("PhoneNumber");
html.Append("</th>");
html.Append("</tr>");
and in the last foreach loop this code :
foreach (SPListItem item in collectionEmployeeDisplay)
{
html.Append("<tr>");
html.Append("<td>");
html.Append(item["EmployeeName"].ToString());
html.Append("</td>");
html.Append("<td>");
html.Append(item["PhoneBook"].ToString());
html.Append("</td>");
html.Append("</tr>");
}
//Table end.
html.Append("</table>");
//Append the HTML string to Placeholder.
PlaceHolder1.Controls.Add(new Literal { Text = html.ToString() });
I beleive there are more elegant solutions to this problem, and if you now it please give me idea .Thank you.
I've found a solution.First we need to add Repeater into PlaceHolderMain :
<asp:Repeater ID="rptEmployees" runat="server">
<HeaderTemplate>
<table border="1" style="width:70%">
<tr>
<td>Employee Name</td>
<td>Phone Number</td>
<td>Position</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("EmployeeName") %></td>
<td><%# Eval("PhoneNumber") %></td>
<td><%# Eval("Position") %></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
than create another class and add this code into final loop:
foreach (SPListItem item in collectionEmployeeDisplay)
{
DisplayEmployee dE = new DisplayEmployee();
dE.EmployeeName = item[Sol.PB1.Fields.EmployeeName].ToString();
dE.PhoneNumber = item[Sol.PB1.Fields.PhoneNumber].ToString();
dE.Position = item[Sol.PB1.Fields.Position].ToString();
display.Add(dE);
}
rptEmployees.DataSource = display;
rptEmployees.DataBind();
}
You cant use XSLT transformation to convert your SPQuery results to an HTML table. see example of Applying an XSLT Transform to a DataSet

HmlAgilityPack fix not open tag

I get from url html page.
in page I get table with hot opened <tr> tag
<table class="transparent">
<tr><td>Sąrašo eil. Nr.:</td><td>B-FA001</td></tr>
<td>Įrašymo į Sąrašą data:</td><td>2006-11-13</td></tr>
</table>
how to fix to
<table class="transparent">
<tr><td>Sąrašo eil. Nr.:</td><td>B-FA001</td></tr>
<tr><td>Įrašymo į Sąrašą data:</td><td>2006-11-13</td></tr>
</table>
I tried to do
private HtmlDocument GetHtmlDocument(string link)
{
string url = "http://195.182.67.7/paslaugos/administratoriai/bankroto-administratoriai/" + link;
var web = new HtmlWeb { AutoDetectEncoding = false, OverrideEncoding = Encoding.UTF8 };
var doc = web.Load(url);
doc.OptionFixNestedTags = true;
doc.OptionAutoCloseOnEnd = true;
doc.OptionCheckSyntax = true;
// build a list of nodes ordered by stream position
NodePositions pos = new NodePositions(doc);
// browse all tags detected as not opened
foreach (HtmlParseError error in doc.ParseErrors.Where(e => e.Code == HtmlParseErrorCode.TagNotOpened))
{
// find the text node just before this error
var last = pos.Nodes.OfType<HtmlTextNode>().LastOrDefault(n => n.StreamPosition < error.StreamPosition);
if (last != null)
{
// fix the text; reintroduce the broken tag
last.Text = error.SourceText.Replace("/", "") + last.Text + error.SourceText;
}
}
doc.Save(Console.Out);
return doc;
}
but not fix
for this particular problem you could do simple regex replacing:
string wrong = "<table class=\"transparent\"><tr><td>Sąrašo eil. Nr.:</td><td>B-FA001</td></tr><td>Įrašymo į Sąrašą data:</td><td>2006-11-13</td></tr></table>";
Regex reg = new Regex(#"(?<!(?:<tr>)|(?:</td>))<td>");
string right = reg.Replace(wrong, "<tr><td>");
Console.WriteLine(right);

DownloadFile in ASP mvc 4 from physical path

I need to make downloading files from the server . Server is specified physical path.
the file is downloaded , but there are problems that I do not know how to fix .
1) All the files are named as "Download".2) does not have an extension . Help me, please, I'm new to ASP MVC
Code of Controller :
public ActionResult NIRInfo()
{
List<string> filesList = new List<string>();
var dir = new System.IO.DirectoryInfo(#"Z:\Docs");
System.IO.FileInfo[] fileNames = dir.GetFiles("*.*");
var xow = from i in db.NIRs where i.Id == id select i.File;
foreach (var i in xow)
{
fileNames = dir.GetFiles(i);
foreach (var f in fileNames)
{
filesList.Add(f.Name);
}
ViewData["fList"] = filesList;
}
return View(nir);
}
public FileResult Download(string Name)
{
return File(#"Z:\Docs\" + Name, MediaTypeNames.Application.Octet);
}
Code of view
#{ var fList = ViewData["fList"] as List<string>;}
#if (ViewData["fList"] != null)
{
<table>
#foreach (var f in fList)
{
<tr>
<td>
#f
</td>
</tr>
}
</table>
}
You need to specify a filename in method overload. Look at third parameter in File method
public FileResult Download(string Name)
{
return File(#"Z:\Docs\" + Name, MediaTypeNames.Application.Octet, "document.txt");
}
HttpResponseBase response;
response.Clear();
response.AddHeader("content-disposition", "attachment;filename=\"" + fileName + "\"");
response.TransmitFile(Path.Combine(FileName, Path.GetFileName(fileName )));

how to print asp.net c# crystal report from client's printer using client's computer

i have an asp.net website that will deployed to a server.
on one of the page, i have a page that load crystal report viewer on pageLoad()
and i want when the user click on a button there, it will print the report to their printer.
this is my asp page that contains the crystal report viewer and the button:
<body>
<link href="style.css" rel="stylesheet" type="text/css" />
<form id="form1" runat="server">
<table align="center">
<tr>
<td align=left>
<asp:LinkButton ID="toHome_LinkButton1" runat="server" onclick="toHome_LinkButton1_Click"><<< Home</asp:LinkButton>
</td>
<td align=right>
<asp:Button ID="print" runat="server" Text="Print" CssClass="css_button" OnClick="print_Click" />
</td>
</tr>
<tr>
<td colspan=2 align=center>
<CR:CrystalReportViewer ID="crv1" runat="server"
EnableDatabaseLogonPrompt="False" EnableParameterPrompt="False"
ToolPanelView="None" GroupTreeStyle-ShowLines="False" HasCrystalLogo="False"
HasDrilldownTabs="False" HasDrillUpButton="False" HasExportButton="False"
HasGotoPageButton="False" HasPageNavigationButtons="False"
HasPrintButton="False" HasSearchButton="False" HasToggleGroupTreeButton="False"
HasToggleParameterPanelButton="False" HasZoomFactorList="False"
PrintMode="ActiveX" />
</td>
</tr>
</table>
</form>
i've already try using PrinToPrinter() method, but as far as i know those method only for server side printing, because we have to declare the printer's name, am i right ?
and this is my button onClick:
(note that i still use PrintToPrinter method that i think is server side printing)
protected void print_Click(object sender, EventArgs e)
{
string url = Request.ServerVariables["QUERY_STRING"];
string[] kodeKwitansi = url.Split('=');
SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);
SqlCommand select = con.CreateCommand();
select.CommandText = "SELECT k.no_kwitansi, k.kode_vendor, k.nama_vendor, u.nama_pekerja, k.nama_pekerja_penanggungjawab, k.satuan, k.jumlah, k.jenis_pembayaran, k.tanggal FROM tb_kwitansi k, tb_user u WHERE k.no_kwitansi = '" + kodeKwitansi[1] + "' AND (k.nomor_pekerja = u.nomor_pekerja)";
con.Open();
SqlDataReader reader = select.ExecuteReader();
reader.Read();
noKwitansi = reader["no_kwitansi"].ToString();
kode_vendor = reader["kode_vendor"].ToString();
namaVendor = reader["nama_vendor"].ToString();
namaPekerja = reader["nama_pekerja"].ToString();
namaPJ = reader["nama_pekerja_penanggungjawab"].ToString();
satuan = reader["satuan"].ToString();
nominal = reader["jumlah"].ToString();
jenisPembayaran = reader["jenis_pembayaran"].ToString();
con.Close();
rd.Load(MapPath("Kwitansi.rpt"));
TextObject to = (TextObject)rd.ReportDefinition.ReportObjects["Text7"];
to.Text = noKwitansi;
to = (TextObject)rd.ReportDefinition.ReportObjects["Text10"];
to.Text = kode_vendor;
to = (TextObject)rd.ReportDefinition.ReportObjects["Text11"];
string[] val = nominal.Split('.');
string val2 = "";
int n = val[0].Length;
int count = 0;
int tan = 0;
for (int i = n - 1; i >= 0; i--)
{
if (val[0][i] == '.')
{
val2 = val[0][i] + val2;
tan = 1;
}
else if (val[0][i] >= '0' && val[0][i] <= '9')
{
val2 = val[0][i] + val2;
count++;
if (count == 3 && i != 0 && tan == 0)
{
val2 = "," + val2;
count = 0;
}
}
}
if (val.Count() == 2)
{
val2 = val2 + "." + val[1];
}
to.Text = val2;
to = (TextObject)rd.ReportDefinition.ReportObjects["Text12"];
if (satuan.Equals("$"))
{
to.Text = terbilang(nominal);
}
else
{
to.Text = terbilang(nominal);
}
to = (TextObject)rd.ReportDefinition.ReportObjects["Text13"];
to.Text = jenisPembayaran;
to = (TextObject)rd.ReportDefinition.ReportObjects["Text15"];
to.Text = namaPJ;
to = (TextObject)rd.ReportDefinition.ReportObjects["Text8"];
to.Text = namaVendor;
rd.PrintOptions.PrinterName = "Canon Inkjet iP3600 series";
rd.PrintToPrinter(1, true, 0, 0);
rd.Close();
rd.Dispose();
Response.Redirect("LihatKwitansi.aspx?"+url);
}
and i read that we can use javascript's windows.Print(), but again as far as i know when we use window.Print() it will print the whole page, while i want only the report to be printed.
so can anyone help me to do this ?
what i need is when the user access my page from their computer, then they click on the button, it will print the report directly to printer that connected to their computer.
any help would be appreciated
thanks in advance :)
The Crystal Report viewer control has this feature built in, but you have disabled it, with this option:
HasPrintButton="False"
Is there a particular reason you don't want to use the built in feature? If not, then simply set this option to True.
What you have to do to print to the client's printer is to give access to the crystal client side printing api by setting PrintMode="ActiveX" in the report viewer control, or use a hidden PDF.
Since I wanted to simplify what the users had to install on each client I went with the hidden pdf option and a separate button to print to client.
On the aspx page I have an asp literal that I populate with the pdf embeded object at 1px x 1px so it isn't visible to the user. Then on pageload call the printToPrinter method.
// On server side
// Export to PDF
Guid imageGuid = Guid.NewGuid();
string _pdfName = String.Format(#"{0}{1}{2}.pdf", _pdfPath, _reportName, imageGuid);
// expport to unique filename
// ...
// Display the pdf object
_sb.AppendFormat("<object ID=\"pdfObject\" type=\"application/pdf\" data=\"{0}\" src=\"{0}\" style=\"width: {1}; height: {2}; ", _pdf2Name, _width, _height);
_sb.AppendLine("z-index:1; display: block; border: 1px solid #cccccc; top: 0; left: 0; position: absolute;-+ \">");
_sb.Append("</object>");
pdfLiteral.Text = _sb.ToString();
pdfLiteral.Visible = true;
// javascript
// on document read call the printWithDialog function
var code = function(){
try
{
var pdf = $get('pdfObject');
if (pdf == null)
return;
try {
pdf.printWithDialog();
}
catch (err) {
alert('Please Install Adobe Acrobat reader to use this feature');
}
}
catch(err)
{
}
};
window.setTimeout(code, 1000);

Web User Control Postback Issue with Treeview

I am trying to build a website that has a custom File Explorer. Eventually I hope to build it out further and allow uploads, but I'm facing an issue calling it from the code behind.
My user control contains a Treeview, and if call it like this:
<fe:FileExplorer filePath="/Resources/" runat="server"></fe:FileExplorer>
everything works fine, but when I call it from the code behind like this:
FileExplorer uc = (FileExplorer)LoadControl("~/Controls/FileExplorer.ascx");
uc.filePath = "/Uploads/Newsletter/";
PAGECONTROLS.Controls.Add(uc);
I have an issue with the Post back.
The issue appears to be when I'm getting the selected node. It grabs the selected node when I use the .Net inline, but when I use the code behind it seems to loose the post back:
TreeNode nd = FolderTree.SelectedNode; <-- Always Null when called in code behind.
Below is the Code Behind:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Troop_101.Controls
{
public partial class FileExplorer : System.Web.UI.UserControl
{
public string FilePath;
public string filePath{
set { FilePath = value; }
get { return FilePath; }
}
protected void Page_Load(object sender, EventArgs e)
{
string RootFilePath = Server.MapPath(FilePath);
if (!IsPostBack)
{
DirectoryInfo rootDir = new DirectoryInfo(RootFilePath);
TreeNode rootNode = new TreeNode(rootDir.Name, rootDir.FullName);
FolderTree.Nodes.Add(rootNode);
TraverseTree(rootDir, rootNode);
FolderTree.CollapseAll();
}
string ReturnStr = "";
TreeNode nd = FolderTree.SelectedNode;
if (nd != null)
{
ReturnStr = getFolderContent(nd.Value);
}
else
{
ReturnStr = getFolderContent(RootFilePath);
}
RESOURCE_FolderContent.InnerHtml = ReturnStr;
foreach (TreeNode tn in FolderTree.Nodes)
{
tn.Expand();
}
}
private void TraverseTree(DirectoryInfo currentDir, TreeNode currentNode)
{
foreach (DirectoryInfo dir in currentDir.GetDirectories())
{
TreeNode node = new TreeNode(dir.Name, dir.FullName);
currentNode.ChildNodes.Add(node);
TraverseTree(dir, node);
}
}
private string getFolderContent(string filePath)
{
string ReplacePath = Server.MapPath(FilePath);
var info = new DirectoryInfo(filePath);
var fileInfo = info.GetFiles();
string LinkTemplate = "<table><tr><td><img src=\"{1}\" height=\"25px\"></td><td style=\"vertical-align:center;\">{2}</td></tr></table>";
string ReturnFiles = "";
if (fileInfo.Length <= 0)
{
ReturnFiles = "No Files In Folder<br />";
}
foreach (FileInfo file in fileInfo)
{
string FileExt = file.Extension.ToLower().Replace(".", "");
if (!File.Exists(HttpContext.Current.Server.MapPath("/images/ExtensionIcons/" + FileExt + ".png")))
FileExt = "_blank";
string fir = filePath.Replace(ReplacePath, "");
ReturnFiles += String.Format(LinkTemplate, FilePath + fir + "/" + file.Name, "/images/ExtensionIcons/" + FileExt + ".png", file.Name);
}
return ReturnFiles;
}
}
}
And here is the .NET
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="FileExplorer.ascx.cs" Inherits="Troop_101.Controls.FileExplorer" %>
<div style="width:90%; border:thick solid #656565;margin:0 auto; background-color:#ffffff; padding:5px;" class="tableroundcorners">
<style type="text/css">
.node_left {
padding:5px;
}
</style>
<table style="width:100%;height:350px;">
<tr>
<td id="RESOURCE_FileTree" runat="server" style="width:150px;border-right:solid #757575 thin;overflow:auto;">
<asp:TreeView ID="FolderTree" runat="server" NodeIndent="15" ShowLines="True" LineImagesFolder="~/Controls/FileExplorerTree">
<HoverNodeStyle Font-Underline="True" ForeColor="#6666AA" />
<NodeStyle Font-Names="Tahoma" Font-Size="8pt" Width="100%" CssClass="node_left" ForeColor="Black" HorizontalPadding="0px" NodeSpacing="0px" VerticalPadding="2px" />
<ParentNodeStyle Font-Bold="False" />
<SelectedNodeStyle Font-Underline="true" HorizontalPadding="0px" VerticalPadding="0px" BackColor="#cccccc" />
</asp:TreeView>
</td>
<td id="RESOURCE_FolderContent" runat="server" style="text-align:left;overflow:auto;">
</td>
</tr>
</table>
</div>
In the code behind make sure that your are adding the control in the OnInit method to ensure that the control exists prior to processing the post back data (before the page load event)
http://i.msdn.microsoft.com/dynimg/IC386473.png (ASP.NET LifeCycle)

Categories