iTextSharp XMLWorkerHelper HTML to PDF Table Alignment - asp.net

Using the following ASP.net/iTextSharp code to parse the contents of an HTML file into a PDF and dump it into the response stream:
Response.Clear();
Response.ContentType = "application/pdf";
using (Document doc = new Document())
{
PdfWriter writer = PdfWriter.GetInstance(doc, Response.OutputStream);
doc.Open();
using (TextReader reader = File.OpenText(Server.MapPath("~/Test.htm")))
{
XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, reader);
}
doc.Close();
}
Response.End();
This works, but the resulting PDF isn't styled anything like the original HTML page. For starters, the built-in css parser appears to only be able to work with direct tag styles and classes (no chaining like: thead th { background-color:#999; }).
Second, it appears borders are an all-or-nothing deal. It has no concept of border-top, border-bottom, etc, and border-collapse doesn't collapse the borders of adjoining cells so the borders end up being twice as thick as I want them.
Last, I cannot figure out how to align a table to the left- or right-side of the document. It is always centered. I tried wrapping in a div with text-align, tried setting the align attribute, tried setting text-align directly on the table. Can't figure that one out?
Here is my demo document I'm trying to use as a proof-of-concept:
<!DOCTYPE html>
<html>
<head>
<title>This is the title</title>
<meta name="description" content="This is the description" />
<meta name="keywords" content="abc, 123, xyz" />
<style type="text/css">
body { font-family:Arial, Verdana, Sans-Serif; font-size:9pt; }
.dataGrid { font-family:Arial, Verdana, Sans-Serif; font-size:9pt; border-collapse: collapse; border:1px solid #000; width:80%; margin:0; text-align:left; }
th { padding:3px 4px; font-weight:bold; border:1px solid #000; }
td { padding:3px 4px; border:1px solid #000; }
.head { border-bottom:2px solid #000; background-color:#9BBA1F; font-weight:bold; }
.odd { background-color:#fff; }
.even { background-color:#D6EB87; }
.foot { border-top:2px solid #000; background-color:#BAB0C4; font-weight:bold; }
h1 { font-size:14pt; color:#FFA200; text-align:center; }
.right { text-align:right; }
.center { text-align:center; }
.left { text-align:left; }
</style>
</head>
<body>
<h1>Sample Document</h1>
<div style="text-align:left;">
<table class="dataGrid" align="left">
<thead>
<tr class="head">
<th width="70%">Name</th>
<th width="15%" class="center">Qty</th>
<th width="15%" class="center">Price</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>ABC</td>
<td class="center">2</td>
<td class="right">$5.00</td>
</tr>
<tr class="even">
<td>XYZ</td>
<td class="center">1</td>
<td class="right">$10.00</td>
</tr>
<tr class="odd">
<td>123</td>
<td class="center">3</td>
<td class="right">$2.00</td>
</tr>
<tr class="even">
<td>789</td>
<td class="center">1</td>
<td class="right">$4.00</td>
</tr>
</tbody>
<tfoot>
<tr class="foot">
<td class="right">Totals</td>
<td class="center">7</td>
<td class="right">$30.00</td>
</tr>
</tfoot>
</table>
</div>
</body>
</html>

After spending a bunch of time on this I couldn't get it to work properly. As such, I ended up switching to another tool: wkHtmlToPdf. I used the Codaxy wrapper class available in Nuget to help create the calls, and am seeing much better results than I saw with iTextSharp. It mostly understands CSS selectors, and automatically handles things like images and links.

Related

using two css styles for table td

Here's what I want to do (simplified example):
<table>
<tr>
<td style = "border:2px solid green">stuff1 </td>
<td style = "border:2px solid green">stuff2 </td>
<td style = "border:2px solid green">stuff3 </td>
</tr>
<tr>
<td style = "border:1px solid red">stuff4 </td>
<td style = "border:1px solid red">stuff5 </td>
<td style = "border:1px solid red">stuff6</td>
This gives precisely the right result, one row bordered in green, the next in red, but I'd like to get rid of all those "style" statements.
I tried several ways to cascade css for this, but couldn't figure out one that would work. The closest I got was:
<head>
<style>
.test {
font-size: 15px;
}
.test td {
border: 2px solid green
}
.test td a{
border: 1px solid red
}
</style>
</head>
<body>
<table class = "test">
<tr>
<td>stuff1 </td>
<td>stuff2 </td>
<td>stuff3 </td>
</tr>
<tr>
<td><a>stuff4</a> </td>
<td><a>stuff5</a> </td>
<td><a>stuff6</a> </td>
</tr>
</table>
</body>
This almost worked. The top row was bordered in green. But the bottom row was bordered in both red and green.
Could someone explain to me how to set up my css so that I can get the result I want.
**************Well, I found a solution using .test th { for the second color. But this does not solve anything if I want a third color.
You can just add a class to the second set of tds. See below for the code or check the Codepen for a working example.
<html>
<head>
<style>
.test {
font-size: 15px;
}
td {
border: 2px solid green;
}
td.red {
border: 1px solid red;
}
</style>
</head>
<body>
<table class="test">
<tr>
<td>stuff1</td>
<td>stuff2</td>
<td>stuff3</td>
</tr>
<tr>
<td class="red">stuff4</td>
<td class="red">stuff5</td>
<td class="red">stuff6</td>
</tr>
</table>
</body>
</html>
Codepen: https://codepen.io/anon/pen/NzygNV
you can do like this as well, Like keeping css classes in a separate css file and then just adding a link tag pointing towards the css file in the html where you have your table.Refer link below for same.
.tbl {
font-size: 15px;
}
td {
border: 2px solid green;
}
td.red {
border:1px solid red;
}
<html>
<head>
<!-- you can ad link to css here -->
</head>
<body>
<table class="tbl">
<tr>
<td>column1</td>
<td>column2</td>
<td>column3</td>
</tr>
<tr>
<td class="red">data1</td>
<td class="red">data2</td>
<td class="red">data3</td>
</tr>
</table>
</body>
</html>
https://codepen.io/anon/pen/PaQJNK

responsive css vertical divider

Im creating a responsive table which contains a vertical divider. I want that divider to move along with the text according to all screen sizes. left and right td are responsive just the divider is creating problem.
The CSS is
.divider{
position: absolute;
left:30.5%;
top:6%;
bottom:25%;
border-left:2px solid #333;
overflow:hidden;
}
and the related html is
<table width="100%">
<tr>
<td>
this is test
</td>
<td><div class="divider"></div></td>
<td>
This is test2
</td>
</tr>
</table>
The problem is when I change the position from absolute to anything else in css it hides the divider.
In your case....its happening because i feel that your are giving position only to the div and not the containing <td>....give this parent td a position first
add height, width to html,body and your are good to go...
solution
CSS
html, body {
height:100%; /* added */
width:100%;/* added */
}
.divider {
position: relative; /* changed*/
left:30.5%;
top:6%;
bottom:25%;
border-left:2px solid #333;
overflow:hidden;
}
td.r {
position:absolute;/* added */
height:100%;/* added */
width:100%;/* added */
}
HTML
<table width="100%" border=1>
<tr>
<td>this is test</td>
<td class="r"> <!-- notice the added class-->
<div class="divider"></div>
</td>
<td>This is test2</td>
</tr>
</table>
EDIT
A much simpler and cleaner way to create divider is to use td only for divider, not the div....check this demo
Remove the div creating the divider and instead, add the divider class to td itself!
<table width="100%" border=0>
<tr>
<td>this is test</td>
<td class="divider"></td>
<td>This is test2</td>
</tr>
</table>
CSS
td {
text-align:center
}
td.divider {
position:absolute;
height:100%;
width:1px;
border:1px solid #000;
background:#000;
}

Make a Table take up 100% of containing td

<style>
.topTable
{
border-top:1px solid #333333;
border-right:1px solid #333333;
}
.topTable td, th
{
border-left:1px solid #333333;
border-bottom:1px solid #333333;
}
.topTable .inner
{
border-width:0px;
position:relative;
top:0px;
left:0px;
height:100%;
width:100%;
}
.topTable .container
{
padding:0px;
border-width:0px;
position:relative;
}
</style>
<table cellpadding="4" class="topTable" cellspacing="0" style="background-color:#f0f0f0;">
<tr>
<th>Option A</th>
<td class="container">
<table cellpadding="4" class="inner" cellspacing="0" style="background-color:#f0a0a0;">
<tr>
<td>Part 1</td>
<td>Part 2</td>
</tr>
</table>
</td>
<td class="container">
<table cellpadding="4" class="inner" cellspacing="0" style="background-color:#a0f0a0;">
<tr>
<td>Part 3</td>
</tr>
<tr>
<td>Part 3</td>
</tr>
</table>
</td>
<td>Done</td>
</tr>
</table>
I need those tables within the TDs to be height:100% and nothing seems to work. I can't use rowspan in this case as the data will be dynamic in each sub table. I need some CSS that will force those tables to take up the full height of the td they're stored in. I thought this would be easy as I'm dealing with block elements but I must be missing something because it's simply not working no matter what tricks I try.
This is the best I could do:
http://jsfiddle.net/jc5qf/2/
Hope it gets you going down the right path.
Found a workaround using jQuery.
Someone had posted something similar to this and I modified it to meet these needs:
$(function () {
$('td.container').each(function () {
var $this = $(this);
var panelheight = $this.height();
$this.children('table.inner').height(panelheight);
})
});
Just have to make the class on each containing td be 'container' and the table inside it that needs to stretch to match the height of that container to 'inner' This jQuery will take over from there.

Class on Table?

Is it not possible to style a <table> and its <tr> <td> using css classes?
For example:
<table class="calendar_table">
<tr>
<td>
<h2>Datum</h2>
</td>
<td>
<h2>Event</h2>
</td>
<td>
<h2>Type</h2>
</td>
</tr>
</table>
Then using something like this CSS:
.calendar_table {
width:880px;
}
.calendar_table tr {
margin:0;
padding:4px;
}
It is possible, it should work properly!
Here is an example
Have fun, you can do whatever you want! I don't recommend using <table>though, unless it is used to present structured data that is meant to be in a table. If it is to draw a layout, use <div> and CSS!
As Aleks wrote, I would define css for the table itself too. But no nested brackets in css definition like: table.custom_class { ... td, th { ... } }.
<table class="custom_class">
<tr>
<th>First name</th>
<th>Last name</th>
</tr>
<tr>
<td>Giovanni</td>
<td>Rovelli</td>
</tr>
<tr>
<td>Roland</td>
<td>Mendel</td>
</tr>
</table>
The following CSS example can be used:
table.custom_class {
border:solid 5px #006CFF;
margin:0px;
padding:0px;
border-spacing:0px;
border-collapse:collapse;
line-height:22px;
font-size:13px;
font-family:Arial, Verdana, Tahoma, Helvetica, sans-serif;
font-weight:400;
text-decoration:none;
color:#0018ff;
white-space:pre-wrap;
}
table.custom_class th {
padding: 20px;
background-color:#98dcff;
border:solid 2px #006CFF;
}
table.custom_class td {
padding: 20px;
border:solid 1px #006CFF;
}
table.custom_class tr {
margin:0;
padding:4px;
}
You can see it in action https://jsfiddle.net/16L9h2ft/
Yes, it's possible. What you have is working to some extent (with tweaks).
To style the td, use:
.calendar_table td {
}
Or:
.calendar_table tr td {
}
will also work.
For setting attributes such as borders, colors, and sizes this is the cleaner way to do it, over embedding that information in HTML.
This approach is great with data tables where the information naturally should be presented in a table. If you are laying out data use more semantically correct tags such as <div> and <span>.
The answers above are either old, or not answered properly, as they are ignoring the styling of the table itself and not just td or th etc. elements.
If we would have a table like this:
<table class="custom_class">
<thead>
<tr>
<th>header 1</th>
<th>header 2</th>
</tr>
</thead>
<tbody>
<tr>
<td>row value 1</td>
<td>row value 2</td>
</tr>
</tbody>
</table>
Then in .css we should put:
table.custom_class {
border: 1px solid black;
td, th {
color: blue;
}
}
Table rows don't take padding, TDs do.
Change your style to:
.calendar_table td {
margin:0;
padding:4px;
}
Tables expand if necessary to let content fit
As far as I know, table rows do not have margin or padding
These layout rules apply no matter how you set it.
Nice looking green table theme :
https://jsfiddle.net/sujayun/qwsLk3aL/
table.namTblCls
{
color:purple;
border: #004400 4px solid;
border-collapse: collapse;
font-size:16px;
}
table.namTblCls th
{
text-align: center;
color:yellow;
background-color:#008800;
border: #004400 2px solid;
padding: 20px;
}
table.namTblCls td
{
text-align: center;
padding: 20px;
border: #004400 1px solid ;
border-right-width: 2px;
border-left-width: 2px;
}
table.namTblCls tr:nth-child(odd)
{
background-color: #DDFFDD;
}
table.namTblCls tr:nth-child(even)
{
background-color: #BBFFBB;
}

CSS Make a block element fill the entire space of a parent element in CHROME

This question has been asked (and answered) previously at: CSS: Make a block element fill the entire space of a parent element?
However, the accepted solution does not work in CHROME (as noted in the comments by mercator). The fix suggesting to add a height:100 to the <tr> element doesn't work either. Does anyone know how to achieve this effect with webkit-based browsers? The link http://dl.getdropbox.com/u/26620/stackoverflow1.html (provided by the original poster) shows this issue. It works in FF/IE but not chrome.
Thanks.
I tried this in Chrome and it seems to work great: http://apptools.com/examples/tdcolor.php
Here's the css (call it test.css):
table.navbar {
border-collapse: collapse;
}
table.navbar td {
border: 1px solid #ccc;
}
table.navbar td a{
display: block;
width: 9em;
padding: 3px;
text-decoration: none;
}
table.navbar td a:link, table.navbar td a:visited {
color: #000;
background-color: #fff;
}
table.navbar td a:hover, table.navbar td a:active {
color: #fff;
background-color: #666;
}
And a sample html file (remember to change the path to the test.css file):
<html>
<head>
<link rel='stylesheet' href='CHANGE PATH TO YOUR test.css' type='text/css' media='all' />
</head>
<body>
<p><strong>Example:</strong></p>
<table border=0 cellspacing=0 cellpadding=0>
<tr>
<td><table border=0 cellspacing=0 cellpadding=0 class=navbar>
<tr>
<td class=navbar><a href="javascript:void(0);">First that is very, very, long to make sure that everything is working correctly <b
style="color:black;background-color:#a0ffff">Link</b></a></td>
</tr>
<tr>
<td class=navbar>Another <b style="color:black;background-color:#a0ffff">Link</b> </td>
</tr>
<tr>
<td class=navbar>A Third <b style="color:black;background-color:#a0ffff">Link</b> </td>
</tr>
</table></td>
<td valign=top class=othercontent><p>Other content goes here.</p></td>
</tr>
</table>
</body>
</html>
Does that work for you?

Resources