I generated a PDF file starting from an HTML page using iTextSharp.
But tables are rendered with the last column not justified, as you can see in the image.
What can I do to fix this?
Here's part of the code:
StyleSheet ss = new StyleSheet();
TextReader htmlReader = new StringReader(strHTML);
ArrayList htmlarraylist = HTMLWorker.ParseToList(htmlReader, ss);
foreach (IElement el in htmlarraylist)
{
document.Add(el);
}
In strHTML there is this HTML code:
<TABLE style="WIDTH: 100%" border=1 cellSpacing=1 cellPadding=1><BR><TBODY><BR><TR><BR><TD>1</TD><BR><TD>2</TD><BR><TD>4</TD><BR><TD>4</TD><BR><TD>5</TD></TR><BR><TR><BR><TD>6</TD><BR><TD>7</TD><BR><TD>8</TD><BR><TD>9</TD><BR><TD>0</TD></TR><BR><TR><BR><TD>0</TD><BR><TD>98</TD><BR><TD>7</TD><BR><TD>5</TD><BR><TD>4</TD></TR><BR><TR><BR><TD>3</TD><BR><TD>2</TD><BR><TD>3</TD><BR><TD>4</TD><BR><TD>5</TD></TR><BR><TR><BR><TD>76</TD><BR><TD>7</TD><BR><TD>9</TD><BR><TD>0</TD><BR><TD>4</TD></TR></TBODY></TABLE>
Ciao
do you use a loop to produce your pdf,? are you sure for each cell you make the appropriate aactions...
int howManyCell = ....
for (int i = 0; i < howManyCell + 1; i++) {
PdfPCell cell = new PdfPCell();
cell.HorizontalAlignment = Element.ALIGN_RIGHT;
cell.VerticalAlignment = Element.ALIGN_TOP;
table.AddCell(cell);
}
Maybe do you use an automatic transformation, without any use of pdf class elements ? In thi case show us the header of your html table and a sample of the first table row, to check out if that is normal
I found the problem!
All those BR tags were messing up my tables! Those were added by a replace hided in another class:
Replace("\r\n", "<BR>");
Thank you guys for your help!
Related
Good evening, recently i was trying to update cell's value in .xls file, using NPOI library(C#), but, when i do that with cell.SetCellValue("anyvalue");,
I am able to see the changes only in some cells. Other cell are just empty.
Tried to save cell's style and re-write it using cell.CellStyle, but still the same.
Generally speaking, i get only half of the values that have to be filled in places.
Using that code, where nameAndValues[0] contains cell name, and nameAndValues[1] contains its value.
using (FileStream rstr = new FileStream(currentPath + $"/{excelName}", FileMode.Open, FileAccess.Read))
{
var workbook = new HSSFWorkbook(rstr);
var sheet = workbook.GetSheetAt(0);
using (FileStream wstr = new FileStream(currentPath + $"/{excelName}", FileMode.Open, FileAccess.Write))
{
for (int i = 0; i < values.Count; i++)
{
var cr = new CellReference(namesAndValue[i, 0]);
var row = sheet.CreateRow(cr.Row);
var cell = row.CreateCell(cr.Col);
cell.SetCellValue(namesAndValue[i, 1]);
}
workbook.Write(wstr);
wstr.Close();
}
rstr.Close();
}
When you call sheet.CreateRow(0), the first row of the sheet will be wiped out and an empty row will be inserted with no style. The same goes with row.CreateCell().
So you are calling CreateRow over and over again, making only the last value of the row survive.
I think this might be the problem.
I need to add <thead> tags to my loop somehow. The tableHEaderRow class only uses <tr><th> tags, and I need them nested in a <thead> tag for styling purposes.
I have tried using a variety of methods including string writer, and literal controls but I can't seem to get it to work.
TableHeaderRow thr = new TableHeaderRow();
tbl.Controls.Add(new LiteralControl("<thead>")); // This is the line I need to add
foreach (DataColumn col in dt.Columns)
{
TableHeaderCell th = new TableHeaderCell();
th.Text = col.Caption;
thr.Controls.Add(th);
}
tbl.Controls.Add(new LiteralControl("</thead>")); // This is the line I need to add
tbl.Controls.Add(thr);
...
...
tbl.RenderControl(w);
tableString = sw.ToString();
// Then my aspx page displays my tableString variable.
What other ways Can I try to add the <thead> tags into my loop manually?
I am using System.Web.UI.WebControls.
You set a TableRow control as being in a <thead> with the TableSelection property.
For example: <asp:TableRow TableSection="TableHeader"/> will generate a TableRow control in the <thead> section of the table.
Dynamically, you can also set rowControl.TableSection = TableRowSection.TableHeader;
The three options are TableHeader, TableBody and TableFooter.
I am using iTextsharp (version 4.1.6 - an LGPL fork) to generate a PDF that contains simply a table. My project is a .net 4 application.
The table can have lots of columns and lots of rows and the PDF will not contain anything else (so I want to use landscape layout on an A4 page).
I, therefore, knocked up this (I cut it down to the code that interacts with iTextSharp, you can guess what the columns, data, val and ms variables are):
// Create a landscape A4 page...
var doc = new Document(new Rectangle(297, 210), 10, 10, 10, 10);
PdfWriter.GetInstance(doc, ms);
doc.Open();
var table = new PdfPTable(columns.Count()) {HeaderRows = 1};
var titleFont = FontFactory.GetFont(BaseFont.COURIER_BOLD, 10);
var bodyFont = FontFactory.GetFont(BaseFont.COURIER, 10);
// Add the column headings...
foreach (var c in columns)
{
var cell = new PdfPCell(new Phrase(c.Title, titleFont))
{
NoWrap = true
};
table.AddCell(cell);
}
// Add the data...
foreach (var o in data)
{
foreach (var c in columns)
{
var cell = new PdfPCell(new Phrase(val, bodyFont))
{
NoWrap = true
};
table.AddCell(cell);
}
}
doc.Add(table);
doc.Close();
Lovely except that creates a 1 page document where all the cells are overlapping and is completely unreadable.
What I want to achieve is something that looks like this:
So the columns never overlap, they just expand out onto the next page and the column headings are repeated as the rows extend down.
I've tried fiddling with KeepTogether etc but I am flummoxed as to how to achieve this result.
I am adding list inside pdfcell.But the identation of this list is not coming properly.
its coming like this:
• One
• Two
• Three
But the same list if add directly to the document,the identation is coming properly.Like below:
• One
• Two
• Three
here is the code :
list = new List(false, 14.4F);
list.ListSymbol = new Chunk("\u2022", FontFactory.GetFont(FontFactory.HELVETICA, 10,iTextSharp.text.Font.BOLD));
ListItem listItem;
listItem = new ListItem(lstrBullets.Trim(), FontFactory.GetFont(FontFactory.HELVETICA, 10, iTextSharp.text.Font.NORMAL));
list.IndentationLeft = lftBulletIndent;
listItem.SetLeading(10.0F, 1.0F);
listItem.Alignment = Element.ALIGN_JUSTIFIED;
list.Add(listItem);
PdfCell cell = new PdfCell();
cell.AddElement(list);
pobjTable.AddCell(cell);
where lftBulletIndent gives the indentation values for list.Please help what i am missing here.How can i retain the indentaion inside a cell?
This how I solved this. I know this is not a proper one.But it worked for me.
I am adding a table with variable width in the first cell of the parent table i.e here pobjTable
PdfPTable DummyTable = new PdfPTable(2);
//Here the floatSpace value changes according to the lftBulletIndent values
float[] headerwidths = { 2f + floatSpace, 98f - floatSpace};
DummyTable.SetWidths(headerwidths);
Pcell = new PdfPCell();
Pcell.Border = Rectangle.NO_BORDER;
DummyTable.AddCell(Pcell);
Pcell = new PdfPCell();
Pcell.AddElement(list);
Pcell.Border = Rectangle.NO_BORDER;
DummyTable.AddCell(Pcell);
pobjTable.AddCell(DummyTable);//Inserting a new table here
pobjTable.AddCell("");
My code is below. I want to add space between cells in tableCell()
something the equivalent of
<td></td> <td></td>
I am NOT looking for cellpadding or cellspacing because they both add space between the left cell border and the left table border (wall); I want to add space between two CELLS, not the table and the cell;
protected void Page_Init(object sender, EventArgs e)
{
Table tb = new Table();
tb.ID = "tb1";
for (int i = 0; i < iCounter; i++)
{
TableRow tr = new TableRow();
TextBox tbox = new TextBox();
tbox.ID = i.ToString();
TableCell tc = new TableCell();
tc.Controls.Add(tbox);
tr.Cells.Add(tc);
tb.Rows.Add(tr);
}
pnlScheduler.Controls.Add(tb);
}
Any ideas?
Try this:
TableCell tc = new TableCell();
HtmlGenericControl div = new HtmlGenericControl("div");
div.Style.Add("padding-left", "5px");
div.Style.Add("padding-right", "5px");
div.Controls.Add(tbox);
tc.Controls.Add(div);
tr.Cells.Add(tc);
tb.Rows.Add(tr);
An alternative might be this (I modified your code and added a label, which you can add alternate to every "tc.Controls.Add(tbox);"
protected void Page_Init(object sender, EventArgs e)
{
Table tb = new Table();
tb.ID = "tb1";
for (int i = 0; i < iCounter; i++)
{
TableRow tr = new TableRow();
TextBox tbox = new TextBox();
TextBox tLabel = new Label();
tbox.ID = i.ToString();
tLabel.width = 10;
TableCell tc = new TableCell();
tc.Controls.Add(tbox);
tc.Controls.Add(tLabel);
tc.Controls.Add(tbox);
tc.Controls.Add(tLabel);
tc.Controls.Add(tbox);
tc.Controls.Add(tLabel);
tr.Cells.Add(tc);
tb.Rows.Add(tr);
}
pnlScheduler.Controls.Add(tb);
}
*edit
My apologies for the margin, I don't think it is possible with margins, however I was able to create a css that can be applied to the middle cells give them padding on both the left and right sides.
but to get around the fact that the first and last elements don't push out against the wall of the table you have to apply the class to only the middle td's
example of css code
table
{
border:1px solid black;
border-collapse: collapse;
table-layout: fixed;
}
td.middle
{
border:1px solid black;
padding-left: 20px;
padding-right: 20px;
}
and then your middle td's would be created with the <td class="middle"></td>
however to convert this type of code to c# I'm not entirely sure. I will keep looking on how to apply this class to only specific elements, but your best bet would be to create a flag that checks the element to make sure that they aren't the first or last ones in the table, unless you are adding them manually then you just add the class manually as needed.
However might I suggest that if this is for page layout, your better off having css do the work for you instead of using table design. But if it's to show data in a table format then never mind, I said nothing.
Hope this helps. will post if I find anything else.
you could always add "empty" cells of the desired with.
For giving space between the table cells we have to use table's cellpadding and cellspacing property.
<table cellspacing="1" cellpadding="2">
</table>
<TABLE CELLSPACING="X">
The X in the line, is replaced with the number of pixels you want between the cells.
<TABLE CELLPADDING="X">
The X in the line, is replaced with the number of pixels you want between the text and cell edge.
When you're ready to add two cells with this spacing, create a table instead; with one row and two td's like:
<table cellspacing="2"><tr><td>stuff</td><td>more stuff></td></tr></table>
Apply a left margin to the table's td (except the last one in each row).
You can do it by assigning a common class, or by applying a class that reset the margin only to the last td.
You can use jQuery either and inject margin, but doing it via css only is cleaner.