I'm developing a LOB app targeted to windows store and I'd like to know what are the options to create custom reports for it. The user may want to, besides printing, export to PDF or CSV.
I don't know which API there is for windows store apps. Googling didn't help much.
If there isn't any tool to create the report, what would you guys suggest?
Looking the PrintSample from Microsoft, it prints the content of a grid component. I doubt how to set the size of page in this case so I can format the report properly.
Any help/idea is much appreciated.
Thanks!
I've committed to a client to build them a Windows Store App for their RT Tablet. I had no idea the technology was so... limited at the time. For example no System.Data, StreamWriter, and many other common business application functionalities are missing... Probably most surprising of all for me was a standard method of building reports. So far their appears to be no SSRS integration (Hopefully coming soon?). Looking at Crystal Reports they currently have no plans of extending to the Windows RT Platform.
I wasn't to impressed with Microsoft's Print sample either, which seemed like a hack more than anything. So I created a more suitable method for my needs. I am sure many of you have come up with your own methods including purchasing third party tools, but as for me I generated my custom reports through HTML and the current WindowsRT available SQLite methods (How Much I miss System.Data!). As mentioned StreamWriter doesn't seem really plausible with Windows RT so I did a little research for an alternative and this is what works for me:
private async void PrintEstimate()
{
// BUILD ESTIMATE WHICH IS AN HTML PAGE BECAUSE THEIR DID NOT APPEAR TO BE
// A WAY TO REALLY BUILD REPORTS FOR WINRT APPLICATIONS AT THIS POINT WITHOUT
// PURCHASING THRIRD PARTY TOOLS.
// Validate Estimate
// Are their values in the estimate list?
if (this.listServices.Items.Count < 1)
{
MessageDialog msgDialog = new MessageDialog("You must first add services before you can print an estimate.");
// Show the message dialog
await msgDialog.ShowAsync();
return;
}
if (string.IsNullOrEmpty(this.txtTotal1.Text))
{
MessageDialog msgDialog = new MessageDialog("You must first add the total before you can print an estimate.");
// Show the message dialog
await msgDialog.ShowAsync();
return;
}
var strAppPath = Path.Combine(Windows.ApplicationModel.Package.Current.InstalledLocation.Path, #"EstimateReport\NewAPEMiniLogo.png");
var dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "APE.db");
// ESTIMATE VARIABLES
string dtDateOfEstimate = Convert.ToString(this.dateEstimate.Date.ToString("MM/dd/yyyy"));
string strCustomerName = null;
string strCustomerAddress = null;
string strCustomerPhone = null;
string strCustomerNotes = null;
double totalCost = Convert.ToDouble(this.txtTotal1.Text);
double taxes = .08 * totalCost;
string strEstimateNote = this.txtNotes.Text;
string base64;
// THE WINRT Environment is very limited as far as accessing local resources... and from all that I have found
// Is purposely limited in allowing this to be done... thus here I am converting the image to a base64 string
//StorageFolder appFolder = ApplicationData.Current.LocalFolder;
StorageFolder appFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("EstimateReport");
StorageFile imageFile = await appFolder.GetFileAsync("NewAPEMiniLogo.png");
using (var stream = await imageFile.OpenAsync(FileAccessMode.Read))
{
var reader = new DataReader(stream.GetInputStreamAt(0));
var bytes = new byte[stream.Size];
await reader.LoadAsync((uint)stream.Size);
reader.ReadBytes(bytes);
base64 = Convert.ToBase64String(bytes);
}
// IF NEW ESTIMATE
if (currentEstimateID == 0)
{
// CREATE/ INSERT NEW ESTIMATE
using (var db = new SQLite.SQLiteConnection(dbPath))
{
db.CreateTable<APE_Painting_App.DataAccess.Estimate>();
db.RunInTransaction(() => { db.Insert(new DataAccess.Estimate() { CustomerID = currentCustomerID, EstimateDate = Convert.ToDateTime(dtDateOfEstimate), TotalCost = totalCost, EstimateNotes = strEstimateNote }); });
string sql = "SELECT last_insert_rowid()";
currentEstimateID = db.ExecuteScalar<int>(sql);
db.Close();
}
}
else
{
// ELSE UPDATE CURRENT ESTIMATE
dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "APE.db");
using (var db = new SQLite.SQLiteConnection(dbPath))
{
// THE ONLY THREE ITEMS THAT SHOULD BE CHANGEABLE AT THE ESTIMATE LEVEL ARE TOTAL COST, ESTIMATE NOTES AND ESTIMATE DATE.
var objEstimate = db.Table<Estimate>().Where(c => c.EstimateID == currentEstimateID).Single();
objEstimate.EstimateDate = Convert.ToDateTime(dtDateOfEstimate);
objEstimate.TotalCost = totalCost;
objEstimate.EstimateNotes = strEstimateNote;
objEstimate.JobAwarded = this.chkJobAwarded.IsChecked.Value;
db.Update(objEstimate);
db.Close();
}
}
// GET CUSTOMER VALUES
using (var db = new SQLite.SQLiteConnection(dbPath))
{
var objCustomer = db.Table<Customer>().Where(c => c.CustomerID == currentCustomerID).Single();
strCustomerName = objCustomer.FirstName + " " + objCustomer.LastName;
strCustomerAddress = objCustomer.Address1 + " " + objCustomer.Address2 + " " + objCustomer.City + " " + objCustomer.State + " " + objCustomer.Zip;
strCustomerPhone = objCustomer.Phone1;
strCustomerNotes = objCustomer.CustomerNote;
db.Close();
}
StringBuilder sb = new StringBuilder();
sb.Append(#"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">" + "\r\n");
sb.Append(#"<!-- saved from url=(0016)http://localhost-->" + "\r\n");
sb.Append(#"<html xmlns=""http://www.w3.org/1999/xhtml"">" + "\r\n");
sb.Append(#"<head>" + "\r\n");
sb.Append(#"<meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"" />" + "\r\n");
sb.Append(#"<title>Service Estimate: A.P.E. Painting Inc.</title>" + "\r\n");
sb.Append(#"<style type='text/css' media='print'>.printbutton {visibility: hidden; display: none;}</style>" + "\r\n");
sb.Append(#"<style type=""text/css"">" + "\r\n");
sb.Append(#"body{font-family:""Palatino Linotype"", ""Book Antiqua"", Palatino, serif;}" + "\r\n");
sb.Append(#"#printablePage{ width:1000px; height:1300px; padding: 30px; position:relative; left:10px; top:10px; }" + "\r\n");
sb.Append(#"#headTitle{ font-size:24px; position:absolute; left:225px; top:15px;}" + "\r\n");
sb.Append(#"#reportName{ font-size:30px; position:absolute; left:850px; top:10px; color:#FFA61B;}" + "\r\n");
sb.Append(#"#companyBlock{ position:absolute; top:45px; left:225px;}" + "\r\n");
sb.Append(#"#footerNote{ font-size:16px;position:absolute; width:500px; left:150px; top:1135px; font-weight:bold;}" + "\r\n");
sb.Append(#"#logo{ position:absolute; top:20px; left:20px;}" + "\r\n");
sb.Append(#".customertable{font-size:14px;color:#333333;width:94%;border-width: 1px;border-color:#ebab3a;border-collapse:collapse;position:absolute;top:200px;}" + "\r\n");
sb.Append(#".apetable {font-size:14px;color:#333333;width:94%;border-width: 1px;border-color: #ebab3a;border-collapse: collapse; position:absolute; top: 350px;}" + "\r\n");
sb.Append(#".apetableB{font-size:14px;color:#333333;width:94%;border-width: 1px;border-color: #ebab3a;border-collapse: collapse; position:absolute; top: 1125px;}" + "\r\n");
sb.Append(#".apetableC{font-size:10px;color:#333333;width:94%;border-width: 1px;border-color: #ebab3a;border-collapse: collapse; position:absolute; top: 1236px;}" + "\r\n");
sb.Append(#"th {font-size:16px;background-color:#FFA61B;border-width: 1px;padding: 8px;border-style: solid;border-color: #ebab3a;text-align:left; color:#fff;}" + "\r\n");
sb.Append(#"tr {background-color:#FFF;}" + "\r\n");
sb.Append(#"td {font-size:12px;border-width: 1px;padding: 8px;border-style: solid;border-color: #FFA61B; height:20px;}" + "\r\n");
sb.Append(#".apetable tr:hover {background-color:#FFA61B;}" + "\r\n");
sb.Append(#".col1{width:80%;}" + "\r\n");
sb.Append(#".col1B{width:80%; border-left-color:#FFF; border-bottom-color:#FFF; border-top:none; text-align:right; font-size:16px; font-weight:bold;}" + "\r\n");
sb.Append(#".col1C{width:50%; font-size:12px; }" + "\r\n");
sb.Append(#".col2{width:20%; }" + "\r\n");
sb.Append(#"</style>" + "\r\n");
sb.Append(#"<script>function printDiv() {" + "\r\n");
sb.Append(#" window.focus(); window.print(); } " + "\r\n");
sb.Append(#"</script>" + "\r\n");
sb.Append(#"</head>" + "\r\n");
sb.Append(#"<body>" + "\r\n");
sb.Append(#"<input style = 'position:absolute; width: 150px; height:75px; z-index: 99;' type='button' class='printbutton' onClick='printDiv()' value='Print Report' />" + "\r\n");
sb.Append(#"<div id=""printablePage"">" + "\r\n");
sb.Append(#"<h1 id=""headTitle"">A.P.E. Painting Inc.</h1>" + "\r\n");
sb.Append(#"<h1 id=""reportName"">" + this.pageTitle.Text + #"</h1>" + "\r\n");
sb.Append(#"<h3 id=""companyBlock"">" + "\r\n");
sb.Append(#"30809 NE Coyote Lane <br/>" + "\r\n");
sb.Append(#"Yacolt, WA 98675 <br/>" + "\r\n");
sb.Append(#"(360) 263-7699 <br/>" + "\r\n");
sb.Append(#"<em> WA State Lic. & Reg. #APEPAI*011QQ</em>" + "\r\n");
sb.Append(#"</h3>" + "\r\n");
//sb.Append(#"<img id= ""logo"" src=""" + strAppPath + #""" width=""197"" height=""148"" alt=""APE LOGO"" />" + "\r\n");
sb.Append("<img src=\"data:image/png;base64,");
sb.Append(base64);
sb.Append("\" />");
sb.Append(#"<table class=""customertable"" border=""1"">" + "\r\n");
sb.Append(#"<tr><td> <strong>Estimate Date:</strong> " + dtDateOfEstimate + " | <strong>Customer:</strong> " + strCustomerName + " | <strong>Customer Phone:</strong> " + strCustomerPhone + " </td></tr>" + "\r\n");
sb.Append(#"<tr><td> <strong>Customer Address:</strong> " + strCustomerAddress + " </td></tr>" + "\r\n");
sb.Append(#"<tr><td> <strong>Project Notes:</strong> " + strEstimateNote + " </td></tr>" + "\r\n");
sb.Append(#"</table>" + "\r\n");
sb.Append(#"<table class=""apetable"" border=""1"">" + "\r\n");
sb.Append(#"<tr><th class=""col1"">Services</th></tr>" + "\r\n");
// Get Count of Estimate Items
int intEstimateLines = this.listServices.Items.Count;
// DELETE ALL PREVIOUS SERVICE LINES FOR THIS ESTIMATE IF ANY EXIST
using (var db = new SQLite.SQLiteConnection(dbPath))
{
SQLiteAsyncConnection conn = new SQLiteAsyncConnection(dbPath);
var query = conn.Table<EstimateDetails>().Where(x => x.EstimateID == currentEstimateID);
var result = await query.ToListAsync();
foreach (var item in result)
{
// FIRST DELETE ALL ESTIMATE DETAIL RECORDS
// GET CURRENT ESTIMATE ID
int estimateDetailID = item.EstimateDetailID;
try
{
db.Execute("DELETE FROM EstimateDetails WHERE EstimateDetailID = ?", estimateDetailID);
}
catch (Exception ex)
{
}
}
}
// LOOP 20 Times TO CREATE THE STATIC LINES IN THE INVOICE WHETHER THEIR IS A SERVICE OR NOT. ALSO:
// INSERT SERVICES/ LOOP THORUGH SERVICES ARRAY TO OBTAIN VALUES
for (int i = 0; i < 20; i++)
{
// INSERT RECORD TO DATABASE IF NECESSARY FIELDS HAVE VALUE
if (i >= intEstimateLines)
{
// NO SERVICES OR COST JUST ADD EMPTY SPACE ON REPORT
sb.Append(#"<tr><td class=""col1""> </td></tr>" + "\r\n");
}
else
{
this.listServices.SelectedIndex = i;
string currentValue = this.listServices.SelectedItem.ToString();
using (var db = new SQLite.SQLiteConnection(dbPath))
{
db.CreateTable<APE_Painting_App.DataAccess.EstimateDetails>();
db.RunInTransaction(() => { db.Insert(new DataAccess.EstimateDetails() { EstimateID = currentEstimateID, EstimateLineItem = currentValue }); });
// FILL REPORT WITH CORRESPONDING VALUES
sb.Append(#"<tr><td class=""col1""> " + currentValue + #" </td></tr>" + "\r\n");
}
}
}
sb.Append(#"</table>" + "\r\n");
sb.Append(#"<table class=""apetableB"" border=""1"">" + "\r\n");
sb.Append(#"<tr><td class=""col1B"">Sub Total:</td><td class=""col2"" style="" text-align:Left;"">" + String.Format("{0:C}", totalCost) + #" </td></tr>" + "\r\n");
sb.Append(#"<tr><td class=""col1B""> Taxes:</td><td class=""col2"" style="" text-align:Left;""> " + String.Format("{0:C}", taxes) + #" </td></tr>" + "\r\n");
sb.Append(#"<tr><td class=""col1B"">Total:</td><td class=""col2"" style="" text-align:Left;"">" + String.Format("{0:C}", (taxes + totalCost)) + #" </td></tr>" + "\r\n");
sb.Append(#"</table>" + "\r\n");
sb.Append(#"<div id=""footerNote"">We propose to furnish material and labor - complete in accordance with the above specifications, for the sum of:<br /><br />Method of Payment:</div>" + "\r\n");
sb.Append(#"<table class=""apetableC"" border=""1"">" + "\r\n");
sb.Append(#"<tr>" + "\r\n");
sb.Append(#"<td class=""col1C"">All material is guaranteed to be as specified. All work to be completed in a workman like manner according to standard practices. Any alteration or deviation from above specifications involving extra costs will be executed only upon written orders, and will become an extra charge over and above the estimate. All agreements contingent upon strikes, accidents or delays beyond our control. Owner to carry fire, tornado and other necessary insurance. Our workers are fully covered by Workmans Compensation Insurance. </td>" + "\r\n");
sb.Append(#"<td class=""colC""><span style=""font-weight:bold;"">Acceptance of Proposal- </span>The above prices, specifications and conditions are satisfactory and are hereby accepted. Your are authorized to do the work as specified. Payment will be made as outlined above. <span style=""font-weight:bold;"">Date of Acceptance:_______________________ </span><br /><br /><br /> <span style=""font-weight:bold;"">Signature:________________________________________________________________________</span></td></tr>" + "\r\n");
sb.Append(#"</table>" + "\r\n");
sb.Append(#"</div>" + "\r\n");
sb.Append(#"<body>" + "\r\n");
sb.Append(#"</body>" + "\r\n");
sb.Append(#"</html>" + "\r\n");
// Create a file in local storage
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync("APE_Printable_Estimate.html", CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, sb.ToString());
string strURL = #"file:/// " + file.Path.ToString(); //
// OPEN FILE
await Windows.System.Launcher.LaunchFileAsync(file);
}
Unfortunately there is no free library (tool/sdk) for generating PDF/Excel reports in Windows Store App now. But if you have money for buying - check PDFTron and Syncfusion
Related
I have data appended line by line in a text file for all confirmed transaction. I want to add Search functionality, where the user enters their E-mail address and all related transaction details connected to that E-mail must be displayed.
bool writeNextLine = false;
StringBuilder sb = new StringBuilder();
// Read the file and display it line by line.
using (System.IO.StreamReader file = new System.IO.StreamReader("record.txt"))
{
while ((line = file.ReadLine()) != null)
{
if (line.Contains(txt_SearchBooking.Text))
{
// This append the text and a newline into the StringBuilder buffer
sb.AppendLine(line.ToString());
lbl_result.Text += sb.ToString();
}
}
}
but only the line containing Email is displayed other details are not.
Email is located on the last line of every transaction detail.
confirmmsg =
" Transaction # : " + EmployeeIDTextBox.Text + ClientIDTextBox.Text + UniqueIDTextBox.Text + "\r\n"
+ " First Name : " + ClientFirstNameTextBox.Text + "\r\n"
+ " Telephone Number : " + ClientTelephoneNumberTextBox.Text + "\r\n"
+ " Investment : " + investmentamt.ToString("C2") + "\r\n"
+ " Interest : " + (twelvemonthint * 100).ToString() + "%" + "\r\n"
+ " Interest Amount : " + (invesmentcalc(investmentamt, twelvemonthterm, twelvemonthint) - investmentamt).ToString("C2") + "\r\n"
+ " Bonus : " + bonus.ToString("c2") + "\r\n"
+ " Total Returns : " + invesmentcalc(investmentamt, twelvemonthterm, twelvemonthint).ToString("C2") + "\r\n"
+ " E-mail : " + ClientEmailTextBox.Text;
This is the data which is written into the text file.
If you always have 9 lines per transaction, with email being the last line, you could use File.ReadAllLines and a counter.
var lines = File.ReadAllLines("records.txt");
for(int i = 0; i < lines.Length; i++)
{
var line = lines[i];
if(line.Contains(txt_SearchBooking.Text))
{
//Retrieve the previous lines
for(int y = i-8; y <= i; y++)
{
lbl_result.Text += lines[y];
}
}
}
Is there a way to add a pause (preferably 1 second) in Amazon Alexa without using SSML? Perhaps there is a trick I can do with the Outputspeech.Text and I just don't know it.
Below, I am saying "Here are works of art by {artist name}" but the name and the start of the works of art become mixed together - in spite of the period - so I end up with things like "Here are the works of art by Pablo Picasso Harlequin..."
I am using C# and my own https endpoint, not AWS Lambda.
Any suggestions? Otherwise I will add it as SSML. Thanks.
var output = new StringBuilder();
var outputCard = new StringBuilder();
string m_location;
string m_current_location;
string m_artist = dt_artist.Rows[0]["DisplayName"].ToString();
output.Append("here are works of art for " + m_artist + ". ");
outputCard.Append("Here are works of art for " + m_artist + ".\n\n");
foreach (DataRow dr in dt_artist_objs.Rows)
{
m_current_location = dr["CurrentLocation"].ToString();
if (m_current_location == " ")
{
m_location = "The location is not available.";
}
else
{
m_location = "It is located on the " + m_current_location;
}
output.Append(dr["Title"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + m_location);
outputCard.Append(dr["Title"].ToString() + ", " + dr["Dated"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + dr["Creditline"].ToString() + ". " + m_location + ".\n"); // It is located on the " + dr["CurrentLocation"].ToString());
}
sql_conn_data.Close();
response.Response.OutputSpeech.Text = output.ToString();
response.Response.Card.Title = "Art";
response.Response.Card.Type = "Standard";
response.Response.Card.Text = outputCard.ToString();
response.Response.ShouldEndSession = true;
return response;
UPDATE
OK. Ended up going the SSML route which looks like this:
var output = new StringBuilder();
var outputCard = new StringBuilder();
string m_location;
string m_current_location;
string m_location_card;
string m_artist = dt_artist.Rows[0]["DisplayName"].ToString();
output.Append("<speak>");
output.Append("here are works of art for " + m_artist + ". <break time='1s'/> ");
outputCard.Append("Here are works of art for " + m_artist + ".\n\n");
foreach (DataRow dr in dt_artist_objs.Rows)
{
m_current_location = dr["CurrentLocation"].ToString();
if (m_current_location == " ")
{
m_location = "The location is not available. <break time='1s' />";
m_location_card = "The location is not available. ";
}
else
{
m_location = "It is located on the " + m_current_location + "<break time = '1s' />";
m_location_card = "It is located on the " + m_current_location;
}
output.Append(dr["Title"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + m_location);
outputCard.Append(dr["Title"].ToString() + ", " + dr["Dated"].ToString() + " is a " + dr["Classification"].ToString() + ". The medium is " + dr["Medium"].ToString() + ". " + dr["Creditline"].ToString() + ". " + m_location_card + ". \n");
}
output.Append("</speak>");
sql_conn_data.Close();
response.Response.OutputSpeech.Ssml = output.ToString();
response.Response.OutputSpeech.Type = "SSML";
response.Response.Card.Title = "Art";
response.Response.Card.Type = "Standard";
response.Response.Card.Text = outputCard.ToString();
response.Response.ShouldEndSession = true;
return response;
}
There is not a way to introduce a pause in Alexa without SSML. You will need to build the ssml string and return it back to Alexa using the pause, or the cadence strings.
I'm generating a HTML file using C#. Using objects and their properties, I'm adding rows to an HTML table . However, I'm seeing some duplicate rows which I don't want, even though the column values are correct. After doing some googling, I found a few HTML functions that people posted for accomplishing this, such as:
function removeDuplicateRows($table){
function getVisibleRowText($row){
return $row.find('td:visible').text().toLowerCase();
}
$table.find('tr').each(function(index, row){
var $row = $(row);
$row.nextAll('tr').each(function(index, next){
var $next = $(next);
if(getVisibleRowText($next) == getVisibleRowText($row))
$next.remove();
})
});
}
and
var seen = {};
$('table tr').each(function() {
var txt = $(this).text();
if (seen[txt])
$(this).remove();
else
seen[txt] = true;
});
However, I'm not sure how to utilize those in my c# code (possibly from my lack of HTML coding). When I tried using these and wrap each line with a sw.WriteLine, all I get is text of the function. So my question is, how can I remove duplicate HTML table rows in my code?
What I have:
StreamWriter sw = new StreamWriter(Path.Combine(cdsPublishRoot, "GeneralActive.htm"));
sw.WriteLine("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \" http://www.w3.org/TR/html4/strict.dtd \">");
sw.WriteLine("<html>");
sw.WriteLine("<head>");
sw.WriteLine("<meta http-equiv=\"Expires\" content=\"0\">");
sw.WriteLine("<title>GPCSE-CDS General</title>");
sw.WriteLine("</head>");
sw.WriteLine("<body onmousemove=\"MouseMove(event)\">");
sw.WriteLine("<script type=\"text/javascript\">");
sw.WriteLine("DoMainMenu(false,\"SDS\");");
sw.WriteLine("DoSdsSubMenu(true,\"ARCHIVE\");");
sw.WriteLine("</script>");
sw.WriteLine("<p class=Heading2><br>Active PCM General Requirement Specifications<br></p>");
sw.WriteLine("<table cellpadding=5 cellspacing=0 border=1 width=760 id=\"MainDataTable\">");
sw.WriteLine("<tr><th style=\"width:14%\" align=left class=SdsHeader>Spec.</th>");
sw.WriteLine("<th style=\"width:64%\" align=left class=SdsHeader>Specification Name</th>");
sw.WriteLine("<th style=\"width:7%\" align=left class=SdsHeader>Spec. Ver.</th>");
sw.WriteLine("<th style=\"width:7%\" align=left class=SdsHeader>Rev. Level</th>");
sw.WriteLine("<th style=\"width:8%\" align=left class=SdsHeader>Rev. Date</th></tr>");
foreach (string file in genActive.Distinct())
{
string[] genOldDirectories = file.Split(Path.DirectorySeparatorChar);
string path = Path.GetDirectoryName(file);
string[] files = Directory.GetFiles(path);
var acro = ArdApp.Data.GeneralSpecification.GeneralSpecVersion.DataLoad(genOldDirectories[2].ToString(), Convert.ToInt32(genOldDirectories[3][0].ToString()), Convert.ToInt32(genOldDirectories[3][2].ToString() + genOldDirectories[3][3].ToString()));
sw.WriteLine("<tr><td id=\"idTDMenuTitle0008\">");
sw.WriteLine("<div id=\"idMenuTitle0008\" class=\"clsMenuTitle\" onclick=\"DoMenu(this)\">");
sw.WriteLine(genOldDirectories[2] + "</div>");
sw.WriteLine("<div id=\"idMenu0008\" class=\"clsMenu\">");
sw.WriteLine("<ul class=\"clsMenuBullets\">");
foreach (var fileName in files)
{
string[] fileDirectory = fileName.Split(Path.DirectorySeparatorChar);
sw.WriteLine("<li class=\"clsMenuItem\"><a class=\"clsMenuItem\" href=" + StripToWebFriendlyName(file) + ">" + StripToWebFriendlyName(fileDirectory[5]) + "</a></li>");
}
sw.WriteLine("</ul>");
sw.WriteLine("</div></td>");
sw.WriteLine("<td class=BodyText>" + acro.AcronymName + "</td>");
sw.WriteLine("<td class=BodyText>" + Convert.ToInt32(genOldDirectories[3][0].ToString()) + "</td>");
sw.WriteLine("<td class=BodyText>" + genOldDirectories[3][2].ToString() + genOldDirectories[3][3] + "</td>");
sw.WriteLine("<td class=BodyText>" + acro.RevisionDate + "</td>");
sw.WriteLine("</tr>");
}
sw.WriteLine("</table>");
sw.WriteLine("</Body>");
sw.WriteLine("</HTML>");
sw.Close();
}
What I tried:
....
foreach (var fileName in files)
{
string[] fileDirectory = fileName.Split(Path.DirectorySeparatorChar);
sw.WriteLine("<li class=\"clsMenuItem\"><a class=\"clsMenuItem\" href=" + StripToWebFriendlyName(file) + ">" + StripToWebFriendlyName(fileDirectory[5]) + "</a></li>");
}
sw.WriteLine("</ul>");
sw.WriteLine("</div></td>");
sw.WriteLine("<td class=BodyText>" + acro.AcronymName + "</td>");
sw.WriteLine("<td class=BodyText>" + Convert.ToInt32(genOldDirectories[3][0].ToString()) + "</td>");
sw.WriteLine("<td class=BodyText>" + genOldDirectories[3][2].ToString() + genOldDirectories[3][3] + "</td>");
sw.WriteLine("<td class=BodyText>" + acro.RevisionDate + "</td>");
sw.WriteLine("</tr>");
}
sw.WriteLine("var seen = {};");
sw.WriteLine("$('table tr').each(function() {");
sw.WriteLine("var txt = $(this).text();");
sw.WriteLine("if (seen[txt])");
sw.WriteLine(" $(this).remove();");
sw.WriteLine("else");
sw.WriteLine("seen[txt] = true;");
sw.WriteLine("});");
Looks like your just reading in file info and just want to display distinct files in your HTML display?
If this is still a c# question, consider just reading in the file info (full file path info) into a List<string> and then you could use linq "Distinct" to get your non-duplicated items and then output in html as needed.
I'am exporting some data to a .txt file as follows:
String content;
String path=#"e:\coding\";
String name="test.txt";
path+=name;
System.IO.File.Delete(path);
for (i=0;i<row-1;i++)
{
try
{
if (r[i].points.Count() > 2)
{
content = "Route " + (i + 1).ToString() +" Truck_id:"+trk[i].truck_name.ToString()+ " Max_load="+trk[i].capacity.ToString()+ "\n";
System.IO.File.AppendAllText(path, content + Environment.NewLine);
System.IO.File.AppendAllText(path, "Points Load Reached_AT Max_load" + Environment.NewLine);
System.IO.File.AppendAllText(path, "========================================" + Environment.NewLine);
for (int j = 0; j < (r[i].points.Count()); j++)
{
content = r[i].points[j].ToString() + " " + c[r[i].points[j]].load.ToString() +" "+ r[i].time_list[j].ToString()+" "+c[r[i].points[j]].max_load.ToString()+"\n";
System.IO.File.AppendAllText(path, content + Environment.NewLine);
}
content = "Total " + r[i].ld.ToString() + "\n";
System.IO.File.AppendAllText(path, content + Environment.NewLine );
content = "Route Complete: " + r[i].reach_at.ToString();
System.IO.File.AppendAllText(path, content + Environment.NewLine+Environment.NewLine);
}
}
catch (IndexOutOfRangeException e)
{
break;
}
}
As expected the output I get is not properly formatted:
The spaces are causing the text to be jumbled and not arranged. My reputation does'nt allow me to post a screenshot but I guess It can be understood what is happening.
Is there way so that the text is properly formatted neatly column wise without looking jumbled.
If you need a text, you can use tabs:
System.IO.File.AppendAllText(path, "Points\t\tLoad\t\tReached_AT\t\tMax_load" + Environment.NewLine);
// ...
content = r[i].points[j].ToString() + "\t\t " + c[r[i].points[j]].load.ToString() +"\t\t"+ r[i].time_list[j].ToString()+"\t\t"+c[r[i].points[j]].max_load.ToString()+"\n";
Just play with amount of tabs (\t for one, \t\t for two, etc...). Hope it can help.
Another solution would be to use commas:
System.IO.File.AppendAllText(path, "Points,Load,Reached_AT,Max_load" + Environment.NewLine);
and save to CSV-file (comma-separated values). Then you can import the data to Microsoft Excel or to other software.
You can find bunch full of good information on how to format the string contents in the The format item MSDN but for quick answer, an example for your string
content = "Route " + (i + 1).ToString() + " Truck_id:" + trk[i].truck_name.ToString() + " Max_load=" + trk[i].capacity.ToString() + "\n";
If we assume,
i maximum 10 digits,
Truck_name max 45 characters
capacity max 10 digits
content = String.Format("{0,-20}{1,55}{2,20} " + Environment.NewLine, "Route " + (i + 1).ToString(), " Truck_id:" + trk[i].truck_name.ToString(), " Max_load=" + trk[i].capacity.ToString());
I'm using the following code:
if (e.Data.MessageArray[0] == "!streams")
{
try
{
WebClient webclient = new WebClient();
var data = webclient.DownloadString("http://api.justin.tv/api/stream/list.json?channel=dotademon");
JArray ja = JArray.Parse(data);
WebClient webclient2 = new WebClient();
var data2 = webclient2.DownloadString("http://api.justin.tv/api/stream/list.json?channel=trixilulz");
JArray ja2 = JArray.Parse(data2);
WebClient webclient3 = new WebClient();
var data3 = webclient3.DownloadString("http://api.justin.tv/api/stream/list.json?channel=thepremierleague");
JArray ja3 = JArray.Parse(data3);
string streamingString = "Live right now: ";
streamingString += (char)3 + "03EG.Demon" + (char)15 + " - " + "Viewers: " + ja[0]["channel_count"] + " - " + "http://www.justin.tv/dotademon" + (char)3 + "03 Mouz.Trixi" + (char)15 + " - " + "Viewers: " + ja2[0]["channel_count"] + " - " + "http://www.justin.tv/trixilulz" + (char)3 + "03 The Premier League" + (char)15 + " - " + "Viewers: " + ja3[0]["channel_count"] + " - " + "http://www.justin.tv/thepremierleague";
irc.SendMessage(SendType.Message, e.Data.Channel, streamingString);
Console.WriteLine("EG.Demon is " + ja[0]["format"]);
Console.WriteLine("Mouz.Trixi is " + ja[2]["format"]);
Console.WriteLine("The Premier League is " + ja[3]["format"]);
}
catch (ArgumentOutOfRangeException)
{
//catch something
}
}
However, if one of the streams aren't online, then it doesn't output that string at all. Even if 2 are online and 1 is offline and vice versa. However, if they're all online, then it outputs it correctly like:
Live right now: EG.Demon - Viewers: 164 - http://www.justin.tv/dotademon Mouz.Trixi - Viewers: 49 - http://www.justin.tv/trixilulz The Premier League - Viewers: 2992 - http://www.justin.tv/thepremierleague
To demonstrate it with outputting to console, here is that code, it essentially does the same thing as the above code, but sends it to the console, same issue though obviously:
using System;
using System.Net;
using Newtonsoft.Json.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
try
{
WebClient webclient = new WebClient();
var data = webclient.DownloadString("http://api.justin.tv/api/stream/list.json?channel=dotademon");
JArray ja = JArray.Parse(data);
WebClient webclient2 = new WebClient();
var data2 = webclient2.DownloadString("http://api.justin.tv/api/stream/list.json?channel=trixilulz");
JArray ja2 = JArray.Parse(data2);
WebClient webclient3 = new WebClient();
var data3 = webclient3.DownloadString("http://api.justin.tv/api/stream/list.json?channel=thepremierleague");
JArray ja3 = JArray.Parse(data3);
string streamingString = "Live right now: ";
streamingString += (char)3 + "03EG.Demon" + (char)15 + " - " + "Viewers: " + ja[0]["channel_count"] + " - " + "http://www.justin.tv/dotademon" + (char)3 + "03 Mouz.Trixi" + (char)15 + " - " + "Viewers: " + ja2[0]["channel_count"] + " - " + "http://www.justin.tv/trixilulz" + (char)3 + "03 The Premier League" + (char)15 + " - " + "Viewers: " + ja3[0]["channel_count"] + " - " + "http://www.justin.tv/thepremierleague";
Console.WriteLine(streamingString);
}
catch (ArgumentOutOfRangeException)
{
//do something
}
}
}
}
Live right now: EG.Demon - Viewers: 164 - http://www.justin.tv/dotademon Mouz.Trixi - Viewers: 49 - http://www.justin.tv/trixilulz The Premier League - Viewers: 2992 - http://www.justin.tv/thepremierleague
My question is, how can I use this as a string but output it still if it's online and not output the rest if it's offline. When at least one of them are offline, then it doesn't output it at all. It checks if it's online if it finds channel_count in the json, because if it's offline, the json file contains nothing, just []. It's the only approach I know of to check if it's online/offline. I'm using JSON.Net by the way.
You can check ja.Count to see if you got a response.
var sb = new StringBuilder("Live right now: ");
if (ja.Count > 0)
sb.Append(string.Format("EG.Demon - Viewers: {0} - http://www.justin.tv/dotademon", ja[0]["channel_count"]));
if (ja2.Count > 0)
//...
if (ja3.Count > 0)
//...
irc.SendMessage(SendType.Message, e.Data.Channel, sb.ToString());