I've got a htm page to arrange the position for me to export the aspx web page as pdf. Here is the code:
<form id="form1" runat="server">
<div>
<h1>Packaging Slip</h1>
<table>
<tr>
<td>Packing Date</td>
<td>[PACKINGDATE]</td>
</tr>
<tr>
<td>Delivery Date</td>
<td>[DELIVERYDATE]</td>
</tr>
<tr>
<td>Beneficiary Name</td>
<td>[BENEFICIARYNAME]</td>
</tr>
<tr>
<td colspan ="2">[ADDRESS]</td>
</tr>
<tr>
<td>Mobile</td>
<td>[MOBILE]</td>
</tr>
<tr>
<td>Contact(Work)</td>
<td>[CONTACTWORK]</td>
</tr>
<tr>
<td>Fax</td>
<td>[FAX]</td>
</tr>
</table>
[ITEMS]
</div>
</form>
The [ITEM] I should replace with grid view later on. And here is the code for me to export as pdf:
// Create a Document object
var document = new Document(PageSize.A4, 50, 50, 25, 25);
// Create a new PdfWriter object, specifying the output stream
var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, output);
// Open the Document for writing
document.Open();
string contents = File.ReadAllText(Server.MapPath("~/FoodBankSystem/Distributions/Packing/PackagingSlip.htm"));
// Replace the placeholders with the user-specified text
contents = contents.Replace("[PACKINGDATE]", lblPackDate.Text);
contents = contents.Replace("[DELIVERYDATE]", lblDeliveryDate.Text);
contents = contents.Replace("[BENEFICIARYNAME]", lblBeneficiaryName.Text);
contents = contents.Replace("[ADDRESS]", lblAddress.Text);
contents = contents.Replace("[MOBILE]", lblContactMobile.Text);
contents = contents.Replace("[CONTACTWORK]", lblWorkContact.Text);
contents = contents.Replace("[FAX]", lblFax.Text);
// Step 4: Parse the HTML string into a collection of elements...
var parsedHtmlElements = HTMLWorker.ParseToList(new StringReader(contents), null);
// Enumerate the elements, adding each one to the Document...
foreach (var htmlElement in parsedHtmlElements)
document.Add(htmlElement as IElement);
document.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "inline;filename=UserDetails.pdf");
Response.BinaryWrite(output.ToArray());
However, for the [ITEM] part, I have no idea how to loop it. Can somebody posts some example? Thanks in advance.
For [Items] You need to generate HTML Table for Code Behind based on Item data and Columns and Replace it this TAG
DataTable dt = new DataTable();
dt.Columns.Add("Item");
dt.Columns.Add("Description");
dt.Columns.Add("QTY");
for(int i=0;i<10;i++)
{
DataRow dr = dt.NewRow();
dr["Item"] = "Item" + i.ToString();
dr["Description"] = "Test" + i.ToString();
dr["QTY"] = i.ToString();
dt.Rows.Add(dr);
}
string data = "<table border=1>";
data += "<TR>";
data += "<TD>Item</TD>";
data += "<TD>Description</TD>";
data += "<TD>QTY</TD>";
data += "</TR>";
foreach(DataRow dr1 in dt.Rows)
{
data += "<TR>";
data += "<TD>" + dr1["Item"].ToString() + "</TD>";
data += "<TD>" + dr1["Description"].ToString() + "</TD>";
data += "<TD>" + dr1["QTY"].ToString() + "</TD>";
data += "</TR>";
}
data += "</table>";
contents = contents.Replace("[ITEMS]", data);
You just need to replace "data" variable with [ITEMS] Tag.
Related
I am attempting to Dynamically generate an HTML Table. What I am after is to have a header row and a second row of textboxes under the header row (all aligned horizontally across the page). I attempted this syntax - however it ignores the values that are selected in the checkboxlist, and the textboxes for input are stacked on top of each other instead of horizontal.
Can someone right the errors in my ways?
protected void btnBullDozer_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder(string.Empty);
var columnname = string.Empty;
foreach (System.Web.UI.WebControls.ListItem item in checkboxtest.Items)
{
columnname = item.Text;
sb.Append("<table>");
sb.Append("<tr>");
sb.Append("<th>Sponsor Level</th>");
sb.Append("<th>" + item.Selected + "</th>");
}
sb.Append("</tr>");
var cm = string.Empty;
int z = 1;
foreach (System.Web.UI.WebControls.ListItem item in checkboxtest.Items)
{
cm = item.Text;
sb.Append("<tr>");
sb.Append("<td><input type=\"text\" name=\"field " + z + "\"></td>");
z = z + 1;
}
sb.Append("</tr>");
sb.Append("</table>");
mask.InnerHtml = sb.ToString();
}
Hypothetical of what my desired grid should look like - let's say that the user selected 4 options from the checkboxlist then I would want 5 headers (Sponsor Level, and the names selected) then one row with 5 empty textboxes underneath for the data entry
Think about the logic of HTML.
<table>
<tr>
<th>Text</th>
<th>Text</th>
<th>Text</th>
</tr>
<tr>
<td>Text</td>
<td>Text</td>
<td>Text</td>
</tr>
</table>
So you want to:
<table>
<tr>
First foreach loop for the headings
<th>
Text
</th>
End Loop
</tr>
<tr>
Second foreach loop for the values
<td>
Value
</td>
End loop
</tr>
</table>
That is how I understand your comments. I know others have provided actual code but I wanted to go back to basics of HTML construct. When you have that clear in your mind you can convert it to logic to create it dynamically with loops.
You need to move tr and table out of for loop
Also, since you need following:
Input from you
I need header row going horizontal across the page (based off the selections from the checkboxlist) then for each header I need an input box under the header, only one row.
Changed your logic as follows:
protected void btnBullDozer_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder(string.Empty);
var columnname = string.Empty;
sb.Append("<table>");
sb.Append("<tr>");
sb.Append("<th>Sponsor Level</th>");
foreach (System.Web.UI.WebControls.ListItem item in checkboxtest.Items)
{
//This loop will genrate a horizontal header for all checkbox items
columnname = item.Text;
sb.Append("<th>" + item.Selected + "</th>");
}
sb.Append("</tr>"); //empty td for Sponsor Level header
var cm = string.Empty;
int z = 1;
sb.Append("<tr><td></td>");
foreach (System.Web.UI.WebControls.ListItem item in checkboxtest.Items)
{
//This will generate a item under each header
cm = item.Text;
//if you want input for only selected items in checkbox uncomment following line
/*if(!item.Selected)
{
sb.Append("<td></td>");
}
else
{*/
sb.Append("<td><input type=\"text\" name=\"field " + z + "\"></td>");
// }
z = z + 1;
}
sb.Append("</tr>");
sb.Append("</table>");
mask.InnerHtml = sb.ToString();
Note: First forLoop will generate headers for all checkbox items. Second for loop will generate inputbox for all checkbox items. Its not very good logic though, we can refactor it a little to use only one loop
protected void btnBullDozer_Click(object sender, EventArgs e)
{
StringBuilder sb = new StringBuilder(string.Empty);
var columnname = string.Empty;
sb.Append("<table>");
sb.Append("<tr>");
foreach (System.Web.UI.WebControls.ListItem item in checkboxtest.Items)
{
columnname = item.Text;
sb.Append("<th>Sponsor Level</th>");
sb.Append("<th>" + item.Selected + "</th>");
}
sb.Append("</tr>");
var cm = string.Empty;
int z = 1;
sb.Append("<tr>");
foreach (System.Web.UI.WebControls.ListItem item in checkboxtest.Items)
{
cm = item.Text;
sb.Append("<td colspan="2"><input type=\"text\" name=\"field " + z + "\"></td>");
z = z + 1;
}
sb.Append("</tr>");
sb.Append("</table>");
mask.InnerHtml = sb.ToString();
}
I want to create an HTML table with my c# program.
I've tried this:
internal string CreateMailBody(mailObj dataObj)
{
string body = string.Empty;
body +=
"Dear all, there is my new table:" +
"TableNo: " + dataObj.Obj.Table.TableNumber+ "<br /> <br />";
body += "<table border='1'><tr><th>Line No</th><th>Table</th><th>Description</th><th>Count</th><th>Met</th><th>something</th></tr>";
foreach (var item in dataObj.Table.TableLineCollection)
{
body += "<tr><td>" + item.LineNumber +"</td>";
body += "<tr><td>" + item.Table+"</td>";
body += "<tr><td>" + item.Description+"</td></tr>";
}
return body;
}
Will it give a better solution for this ?
You may mix StringBuilder using the method AppendFormat and string literals (# in from of a string, so you can write multiple lines).
StringBuilder body = new StringBuilder();
body.AppendFormat (
#"Dear all, there is my new table:
TableNo: {0} <br /> <br />
<table border='1'><tr><th>Line No</th><th>Table</th><th>Description</th><th>Count</th><th>Met</th><th>something</th></tr>"
, dataObj.Obj.Table.TableNumber);
foreach (var item in dataObj.Table.TableLineCollection)
{
body.AppendFormat(
#"<tr><td> {0}</td>
<tr><td> {1}</td>
<tr><td> {2}</td></tr>",
item.LineNumber, item.Table, item.Description);
}
I have a DataTable of records which I need to append as information to my Email template htm. Currently what I am doing here works fine but that is if I only have 1 row of record. How can I go about appending the htm template such that I can have multiple postings in the email
e.g Sample Email Screen (Assuming my DataTable returns 3 rows of record):
Dear Sir, your daily car posting results:
Image
Toyota
Cambry
$10000
Image
Honda
GT
$10000
Image
Nissan
Sunny
$10000
Loop DataTable row:
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dr = dt.Rows[i];
primaryImage = dr["PrimaryImage"].ToString();
email = dr["Email"].ToString();
postTitle = dr["Model"].ToString();
model = dr["Model"].ToString();
askingPrice = dr["AskingPrice"].ToString();
var mail = new Email();
mail.IsBodyHtml = true;
mail.MailAddresses = email;
mail.MailSubject = "Test";
mail.HtmFileName = "Email.htm";
var dict = new Dictionary<string, string>
{
{"<%PrimaryImage%>", primaryImage },
{"<%PostTitle%>", postTitle},
{"<%Model%>", model},
{"<%AskingPrice%", askingPrice}
};
mail.Dict = dict;
MailMessage mailMessage;
mailMessage = mail.CreateMailMessage();
Email.Send(mailMessage, 3, 3000, true);
}
}
Create Mail Message:
public MailMessage CreateMailMessage()
{
MailMessage mail = new MailMessage();
mail.IsBodyHtml = IsBodyHtml;
mail.From = new MailAddress("xxx#yahoo.com", "xxx");
mail.Bcc.Add(MailAddresses);
mail.Subject = MailSubject;
string body = "";
string filePath =
HttpContext.Current.Server.MapPath("~/" + ConfigurationManager.AppSettings["TEMPLATES"] + "/");
if (File.Exists(filePath + HtmFileName))
{
FileStream f = new FileStream(filePath + HtmFileName, FileMode.Open);
StreamReader sr = new StreamReader(f);
body = sr.ReadToEnd();
foreach (var pair in Dict)
{
body = body.Replace(pair.Key, pair.Value);
}
f.Close();
}
mail.Body = body;
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnSuccess |
DeliveryNotificationOptions.OnFailure;
return mail;
}
Portion of the Email.htm template:
<body>
<form id="form1" runat="server">
<div style="border: thin solid #E1E1E1; background-color: #F0F0F0; margin-bottom: 10px; padding-top: 3px; padding-bottom: 3px; padding-left:5px;">
Postings
</div>
<div>
<a><img src="<%PrimaryImage%>"/></a>
<br/><br/>
Sell Post Title: <%PostTitle%>
<br/><br/>
Model: <%Model%>
<br/><br/>
Asking Price: <%AskingPrice%>
</div>
</form>
</body>
#M.S : There must be some condition on the basis of which you will decide which attribute goes to which td. You can wrap up this logic in some method and generate a class name. Below is a way how you generate a classname on the basis of rownum.
var className="" ;
var rowNum=0;
foreach (var entry in dataTable)
{
className=GetClassName(rowNum)
innerHtml += "<tr>";
innerHtml += "<td class='"+ className +"'>" + entry.PrimaryImage + "</td> ";
innerHtml += "</tr>";
rowNum++;
}
public static string GetClassName(int rowCount)
{
switch (rowCount)
{
case 1:
return "class1";
case 2:
return "class2";
case 3:
return "class3";
default:
return "unassignedClass";
}
}
I have always used HtmlAgilityPack to prepare htmlcontent and achieve things like this.
private string PrepareHtmlContent(List<DataRow> dataTable)
{
var htmlDocument = new HtmlDocument();
var html = EmailTemplates.GetTemplate("yourTemplate");
htmlDocument.LoadHtml(html);
var recordsContainerNode = htmlDocument.GetElementbyId("dataTable");
if (recordsContainerNode != null)
{
var innerHtml = "";
foreach (var entry in dataTable)
{
innerHtml += "<tr>";
innerHtml += "<td>" + entry.PrimaryImage + "</td> ";
innerHtml += "<td>" + entry.Model + "</td> ";
innerHtml += "<td>" + entry.AskingPrice + "</td> ";
innerHtml += "</tr>";
}
recordsContainerNode.InnerHtml = innerHtml;
}
using (var stringWriter = new StringWriter())
{
htmlDocument.Save(stringWriter);
return stringWriter.GetStringBuilder().ToString();
}
}
And your template should be sth like this
<body>
<form id="form1" runat="server">
<div style="border: thin solid #E1E1E1; background-color: #F0F0F0; margin-bottom: 10px; padding-top: 3px; padding-bottom: 3px; padding-left:5px;">
Postings
</div>
<table>
<thead> </thead>
<tbody id="dataTable">
</tbody>
</table>
</form>
</body>
I have a variable str which is having some text. I just show this text on the my UI.
But I have a condition, suppose this variable is having 5oo words, so I need to put a tag after every 50 words.
How can I do that?
below is my c# code through which I am sending a mail as html
Emailbody += " <tr>";
Emailbody += " <td align='left' valign='Top' nowrap><span class=style17>Purpose of travel</span></td>";
Emailbody += "<td align='center' valign='Top'>:</td>";
Emailbody += " <td align='left' valign='Top'><span class=style17> " + TextBox1.Text + "</span></td>";
Emailbody += " <td> </td>";
Emailbody += " <td align='left' nowrap'><span class=style17>Advance</span></td>";
Emailbody += " <td align='center'>:</td>";
Emailbody += "<td align='left' nowrap><span class=style17>"+TextBox2.Text+"</td>";
Emailbody += " </tr>";
I need the the solution for mt TextBox1.Text
If you are using C#, then you can do so like :
public string SplitLine(string input)
{
var wordList = input.Split(' ');
var sb = new StringBuilder();
for (int index = 0; index < wordList.Length; index++)
{
if(index % 50 == 0 && index > 0)
sb.Append("<br/>" + wordList[index]);
else
sb.Append(wordList[index] + ' ');
}
return sb.ToString();
}
Use javascript as follows:
var count=0;
for(var i=0;i<str.length;i++)
{
if((str[i])=="")
{
count++;
if(count==50)
{
str[i]="<br/>"
count=0;
}
}
}
Hope its helpful.
I assume you want to do that in c#?
Have a look at possible duplicate. The given function allows you do specify rather than a number of characters or words a line width in pixels and with the font and font size it calculates a proper length. You have to adapt it to your HTML output, but the rest stays the same.
You can use the List then like this:
List<string> lines = WrapText(TextBox1.Text, 300, "Calibri", 11);
string longText = string.Empty
foreach (var item in lines)
{
longText += item + "</br>";
}
Emailbody += " <tr>";
Emailbody += " <td align='left' valign='Top' nowrap><span class=style17>Purpose of travel</span></td>";
Emailbody += "<td align='center' valign='Top'>:</td>";
Emailbody += " <td align='left' valign='Top'><span class=style17>" + longText + "</span></td>";
Emailbody += " <td> </td>";
Emailbody += " <td align='left' nowrap'><span class=style17>Advance</span></td>";
Emailbody += " <td align='center'>:</td>";
Emailbody += "<td align='left' nowrap><span class=style17>"+TextBox2.Text+"</td>";
Emailbody += " </tr>";
I'm trying to read a text file containing the name of the image, and display it opon pageload.
Let's say that the content in the text file is
Australia Picture101
Singapore Picture201
Following is the code i tried and it does not display the image.
tableString += "<table class='content_background' cellpadding='0' cellspacing='0'>";
foreach (string line in lines)
{
string[] country = line.Split(token2);
string[] image = country[1].Split(token);
string row = "<tr><td class='left_content'>" + country[0] + "</td>" +"<td><table><tr>";
tableString += row;
for (int i = 0; i < image.Length; i++)
{
---> string row2 = "<td class='right_content'> <asp:ImageButton ImageUrl='~/img/missing children pictures/" + "image[i]" + ".jpg'/>" + "</td>";
tableString += row2;
}
tableString += "</tr></table></td>";
}
tableString += "</tr></table>";
container.InnerHtml = tableString;
Is there any other way to do this ? Thanks in advance.
the screen shot is as follow
That's no button ! You're outputting non-parsed HTML - the ASP.NET engine does not parse that, it just sends the data as HTML to the client.
Instead, use
var btn = new ImageButton();
btn.ImageUrl = "~/img/missing children pictures/" + "image[i]" + ".jpg";
Panel1.Controls.Add(btn);
As an easy hack, you can use
string row2 = "<td class=\"right_content\"> <input type=\"button\" style=\"background:url('/img/missing%20children%20pictures/" + image[i] + ".jpg')\"/></td>";
If you want to generate HTML directly, then use HTML tags:
<a href="[Img_CLick Link]"><img src="[image path]"
alt="Click" border="0" /></a>
Put appropriate values in the square brackets.
Otherwise consider using asp:Table control and add rows/cells at run time.