Right aligning text in PdfPCell - c#

I have a C# application that generates a PDF invoice. In this invoice is a table of items and prices. This is generated using a PdfPTable and PdfPCells.
I want to be able to right-align the price column but I cannot seem to be able to - the text always comes out left-aligned in the cell.
Here is my code for creating the table:
PdfPTable table = new PdfPTable(2);
table.TotalWidth = invoice.PageSize.Width;
float[] widths = { invoice.PageSize.Width - 70f, 70f };
table.SetWidths(widths);
table.AddCell(new Phrase("Item Name", tableHeadFont));
table.AddCell(new Phrase("Price", tableHeadFont));
SqlCommand cmdItems = new SqlCommand("SELECT...", con);
using (SqlDataReader rdrItems = cmdItems.ExecuteReader())
{
while (rdrItems.Read())
{
table.AddCell(new Phrase(rdrItems["itemName"].ToString(), tableFont));
double price = Convert.ToDouble(rdrItems["price"]);
PdfPCell pcell = new PdfPCell();
pcell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT;
pcell.AddElement(new Phrase(price.ToString("0.00"), tableFont));
table.AddCell(pcell);
}
}
Can anyone help?

I'm the original developer of iText, and the problem you're experiencing is explained in my book.
You're mixing text mode and composite mode.
In text mode, you create the PdfPCell with a Phrase as the parameter of the constructor, and you define the alignment at the level of the cell. However, you're working in composite mode. This mode is triggered as soon as you use the addElement() method. In composite mode, the alignment defined at the level of the cell is ignored (which explains your problem). Instead, the alignment of the separate elements is used.
How to solve your problem?
Either work in text mode by adding your Phrase to the cell in a different way.
Or work in composite mode and use a Paragraph for which you define the alignment.
The advantage of composite mode over text mode is that different paragraphs in the same cell can have different alignments, whereas you can only have one alignment in text mode. Another advantage is that you can add more than just text: you can also add images, lists, tables,... An advantage of text mode is speed: it takes less processing time to deal with the content of a cell.

private static PdfPCell PhraseCell(Phrase phrase, int align)
{
PdfPCell cell = new PdfPCell(phrase);
cell.BorderColor = BaseColor.WHITE;
// cell.VerticalAlignment = PdfCell.ALIGN_TOP;
//cell.VerticalAlignment = align;
cell.HorizontalAlignment = align;
cell.PaddingBottom = 2f;
cell.PaddingTop = 0f;
return cell;
}

Here is my derivation of user2660112's answer - one method to return a cell for insertion into a bordered and background-colored table, and a similar, but borderless/colorless variety:
private static PdfPCell GetCellForBorderedTable(Phrase phrase, int align, BaseColor color)
{
PdfPCell cell = new PdfPCell(phrase);
cell.HorizontalAlignment = align;
cell.PaddingBottom = 2f;
cell.PaddingTop = 0f;
cell.BackgroundColor = color;
cell.VerticalAlignment = PdfPCell.ALIGN_CENTER;
return cell;
}
private static PdfPCell GetCellForBorderlessTable(Phrase phrase, int align)
{
PdfPCell cell = new PdfPCell(phrase);
cell.HorizontalAlignment = align;
cell.PaddingBottom = 2f;
cell.PaddingTop = 0f;
cell.BorderWidth = PdfPCell.NO_BORDER;
cell.VerticalAlignment = PdfPCell.ALIGN_CENTER;
return cell;
}
These can then be called like so:
Font timesRoman9Font = FontFactory.GetFont(FontFactory.TIMES_ROMAN, 9, BaseColor.BLACK);
Font timesRoman9BoldFont = FontFactory.GetFont(FontFactory.TIMES_BOLD, 9, BaseColor.BLACK);
Phrase phrasesec1Heading = new Phrase("Duckbills Unlimited", timesRoman9BoldFont);
PdfPCell cellSec1Heading = GetCellForBorderedTable(phrasesec1Heading, Element.ALIGN_LEFT, BaseColor.YELLOW);
tblHeadings.AddCell(cellSec1Heading);
Phrase phrasePoisonToe = new Phrase("Poison Toe Toxicity Level (Metric Richter Scale, adjusted for follicle hue)", timesRoman9Font);
PdfPCell cellPoisonToe = GetCellForBorderlessTable(phrasePoisonToe, Element.ALIGN_LEFT);
tblFirstRow.AddCell(cellPoisonToe);

I ended up here searching for java Right aligning text in PdfPCell. So no offense if you are using java please use given snippet to achieve right alignment.
private PdfPCell getParagraphWithRightAlignCell(Paragraph paragraph) {
PdfPCell cell = new PdfPCell(paragraph);
cell.setBorderColor( BaseColor.WHITE);
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
return cell;
}
In getParagraphWithRightAlignCell pass paragraph
Thanks

Perhaps its because you are mixing the different ways to add the cells? Have you tried explicitly creating a cell object, massaging it however you want then adding it for every cell?
Another thing you could try is setting the vertical alignment as well as the horizontal.

cell.HorizontalAlignment = Element.ALIGN_RIGHT;

Related

Setting margins, or cell spacing, between a grid of images in iTextSharp PdfPTable

I am trying to render a PDF with a grid of images, using iTextSharp (v5.5.10). The images will all have the same dimensions and should be evenly distributed on one page.
However, with the code mentioned below, I'm having difficulty in setting the appropriate margins, or spacing between the cells.
Visually this means that the expected result is this:
The yellow highlighted lines are the problem where I'm getting the following result instead:
Notice how there are no spaces between the images? This is based on my following code:
public void CreateGridOfImages(string outputFilePath)
{
// note: these constants are in millimeters (mm),
// which are converted using the ToPoints() helper later on
const float spacingBetweenCells = 7;
const float imageWidth = 80;
const float imageHeight = 80;
const string[] images = new [] { "a.jpg", "b.jpg", "c.jpg" };
using (var stream = new FileStream(outputFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None))
{
var document = new iTextSharp.text.Document(PageSize.B2, 0f, 0f, 0f, 0f);
var writer = PdfWriter.GetInstance(document, stream);
try
{
document.Open();
var table = new PdfPTable(5);
table.DefaultCell.Border = Rectangle.NO_BORDER;
foreach (var imagePath in images)
{
var img = iTextSharp.text.Image.GetInstance(imagePath);
img.ScaleToFit(ToPoints(imageWidth), ToPoints(imageHeight));
var cell = new PdfPCell();
// THIS IS THE PROBLEM... HOW TO SET IMAGE SPACING?
var cellMargin = ToPoints(spacingBetweenCells);
cell.AddElement(img);
table.AddCell(cell);
}
document.Add(table);
}
catch (Exception ex)
{
throw ex;
}
finally
{
document.Close();
}
}
}
private float ToPoints(float millimeters)
{
// converts millimeters to points
return iTextSharp.text.Utilities.MillimetersToPoints(millimeters);
}
Now this seems trivial. And it problably is, but I've tried several options and could none of them to work properly (or at all):
Adding Paragraph() objects with paddings between each
Adding Padding to PdfPCell does not seem to work for me
Looked into custom IPdfPCellEvent samples
Absolutely positioning the images alltogether (forgetting the PdfPTable)
My hunch is that the IPdfPCellEvent seems the right approach. But all the iText options and variations are simply overwhelming.
Summarized, does anyone know how can I properly set the margins/spacing between the cells?
I assume you want to have the second table in this image:
The only way to create white spacing between cells in an iText table is to set the relevant borders to the background colour and play with the padding of the cell. My pivotal code for creating the cells is:
for(int i = 0; i < nrCols* nrRows;i++) {
var img = Image.GetInstance(imagePath);
img.ScaleToFit(ToPoints(imageWidth), ToPoints(imageHeight));
//Create cell
var imageCell = new PdfPCell();
imageCell.Image = img;
imageCell.Border = Rectangle.BOX;
imageCell.BorderColor = useColor? BaseColor.YELLOW : BaseColor.WHITE;
//Play with this value to change the spacing
imageCell.Padding = ToPoints(spacingBetweenCells/2);
imageCell.HorizontalAlignment = Element.ALIGN_CENTER;
grid.AddCell(imageCell);
}
As to why adding padding to the PdfPCell didn't seem to worrk:
The reason why borders are still drawn in your example, despite
table.DefaultCell.Border = Rectangle.NO_BORDER;
Is because you never use the default cell because you create a custom one with var cell = new PdfPCell(); and pass the custom one to table.AddCell(cell);. If you'd have used table.addCell(img), the border would not have been there (although your padding would still not be your desired spacing, since it isn't set on the default cell).

How to sort a table in a pdf using itextsharp

I am creating a table in PDF by using iTextsharp. I want to sort that table by its columns.
.
When I click on first column it must be sort in alphabetical order,second column must sort in date wise order (Ascending order),and Third/fourth columns must sort in numbers order (Ascending order). Here is my code:
public void createPdf(string filestream)
{
FileStream outputStream = new FileStream(filestream, FileMode.Create,FileAccess.Write);
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.GetInstance(document, outputStream);
document.Open();
PdfPTable table = createtable();
document.Add(table);
document.Close();
}
public PdfPTable createtable()
{
PdfPTable table = new PdfPTable(4);
float[] widths = new float[] { 2f, 1f,1f, 1f};
table.SetTotalWidth(widths);
PdfPCell cell;
//First Row
cell = new PdfPCell(new Phrase("Title"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("Date"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("Time"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("Year"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
//Second Row
cell = new PdfPCell(new Phrase("The Counterfeiters"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("01/01/2007"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("09:30"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("2007"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
//Third Row
cell = new PdfPCell(new Phrase("Requiem for a Dream"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("02/01/2000"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("11:30"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("2000"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
//Fourth Row
cell = new PdfPCell(new Phrase("Cinema Paradiso"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("12/01/1988"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("20:00"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("1988"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
//Fifth Row
cell = new PdfPCell(new Phrase("About Last Night"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("15/10/1986"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("27:00"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("1986"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
//Sixth Row
cell = new PdfPCell(new Phrase("Sixteen Candles"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("11/09/1984"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("22:30"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("1984"));
cell.HorizontalAlignment = Element.ALIGN_CENTER;
table.AddCell(cell);
return table;
}
I dont know any idea about how to implement this.
You are trying to do something that is impossible in PDF.
There are three possible workarounds, two of which are not valid options:
Use a RichMedia annotation with an embedded .swf component. In this workaround, you don't create a table in PDF, but you visualize the table in Flex/Flash. This workaround isn't a valid option because (1) this functionality is deprecated (it won't be in ISO-32000-2), (2) there is very little support for Flash components, (3) even Adobe has abandoned Flash.
Create a PDF that is actually an XFA form. Change the table by using JavaScript. This can't be done using iText(Sharp) and this isn't a valid option because (1) XFA will be deprecated in ISO-32000-2, (2) many PDF viewers don't support XFA and (3) Adobe has informed the world that they would never support XFA on mobile.
Add the table as many times as there are columns at the same coordinates. Use Optional Content to hide/show specific tables. Make the cells in the header clickable and use JavaScript to trigger an action that makes one specific table visible and all the other tables invisible. Caveat: PDF viewers that don't support PDF 1.5 will show all the tables at the same time. Fortunately, there aren't many of those stone-age PDF viewers around anymore.
Basically, it boils down to this:
Tell your employer that he's asking something that is impossible in PDF. If he doesn't believe you, say that you won't do a thing until he shows you an example of a PDF that meets his requirements.
Use the workaround that involves OCG. Start by looking at different examples that involve optional content groups. If you don't understand my answer, please don't post a comment "give me an example please", but adapt your code and post a new question explaining what it is that you don't understand about OCG. Looking at your output table, I see that you have been reading my book "iText in Action - Second Edition" (you're using one of my examples). OCG is explained in chapter 15 of that book.
Update: a sample was sent to my personal mail address. I don't know if this is allowed by StackOverflow, but please note that I don't allow this. I answer questions on StackOverflow on a voluntary basis, but I do not answer questions for free that are sent to my personal e-mail address.
The mail that was sent to me contained a PDF document that was different than what was described in the question. That PDF document consists of 5 pages. Each page has a header that looks like a sequence of five tabs. On top of these visual tabs, an annotation is added. Clicking on such an annotation triggers a "local Goto" action. Examples for such annotations can be found in chapter 7 of the official documentation.

ITextSharp 4.1.6. PDF Table - how to remove whitespace on top of each cell? [padding and leading already set to 0]

I'm having a problem with ITextSharp's tables. I'd like to have cells without top & bottom padding, so that they are placed closer to each other.
Although I have set the padding and the leading of the cell to 0, the white-space still remains.
Does anyone please know how to remove the whitespace ?
EDIT:
Thanx to prompt answer from Dylan, I've managed to resolve my issue. Here's the source snippet if someone gets across similar issue
Document document = new Document(PageSize.A4, 5, 5, 10, 10);
using (FileStream fs = new FileStream("C:\\Users\\brum\\Desktop\\untitled.pdf", FileMode.Create))
{
iTextSharp.text.pdf.PdfWriter.GetInstance(document, fs);
document.Open();
PdfPTable table = new PdfPTable(2);
PdfPCell cell = new PdfPCell(new Phrase("Spanning 2 cols"));
cell.Colspan = 2;
cell.HorizontalAlignment = 1;
cell.Padding = 0f;
cell.UseAscender = true;
table.AddCell(cell);
table.AddCell("Next row 1");
table.AddCell("Next row 2");
document.Add(table);
document.Close();
}
cell.UseAscender = true; // This is the line that did the trick for me
Set the top padding to something small or even negative. Another option is
PdfPCell.setUseAscender().
ex:
cell.setPaddingTop(0f); // No padding on top cell
or
cell.UseAscender = true;
Please paste the code you have.

ITextSharp full page height layout

I want to create th following PDF layout with ITextSharp:
I use the following code to generate my table:
Document document = new Document(PageSize.A4);
MemoryStream memoryStream = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(document, memoryStream);
document.Open();
PdfPCell cell;
PdfPTable table = new PdfPTable(2);
table.SetWidths(new float[] { 450, 100 });
table.WidthPercentage = 100;
cell = new PdfPCell(new Phrase("Item cod werwerwer"));
table.AddCell(cell);
cell = new PdfPCell(new Phrase("100"));
table.AddCell(cell);
cell = new PdfPCell(new Phrase(string.Empty));
table.AddCell(cell);
cell = new PdfPCell(new Phrase("100"));
table.AddCell(cell);
document.Add(table);
writer.CloseStream = false;
document.Close();
memoryStream.Position = 0;
return memoryStream.ToArray();
How can I force table to cover full page height without use fixed height value?
you can use table.ExtendLastRow = true;
Tables flow, that's just what they do. If you want to change the height then you're going to need to use fixed values. You could calculate these fixed values at runtime by trying to figure out what the height of some text will be in a given cell at a given width using a given font. Or you could just fix it at a magic number which is what the code below does.
At the top is the magic constant. When we create the document we specify 0 for all margins so that we fill the entire page. You can change this but you'll have to adjust the calculations below. Then in the first row we set one of the cell's MinimumHeight to the page's height minus the constant and in the second row we set one of the cell's height to the constant.
//Fixed height of last cell
float LAST_CELL_HEIGHT = 50f;
//Create our document with zero margins
Document document = new Document(PageSize.A4, 0, 0, 0, 0);
FileStream fs = new FileStream(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "A4.pdf"), FileMode.Create, FileAccess.Write, FileShare.Read);
PdfWriter writer = PdfWriter.GetInstance(document, fs);
document.Open();
PdfPCell cell;
PdfPTable table = new PdfPTable(2);
table.SetWidths(new float[] { 450, 100 });
table.WidthPercentage = 100;
cell = new PdfPCell(new Phrase("Item cod werwerwer"));
//Set the first cell's height to the document's full height minus the last cell
cell.MinimumHeight = document.PageSize.Height - LAST_CELL_HEIGHT;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("100"));
table.AddCell(cell);
cell = new PdfPCell(new Phrase(string.Empty));
//Set the last cell's height
cell.MinimumHeight = LAST_CELL_HEIGHT;
table.AddCell(cell);
cell = new PdfPCell(new Phrase("100"));
table.AddCell(cell);
document.Add(table);
writer.CloseStream = false;
document.Close();
fs.Close();

Problem using tables in itextsharp

i am trying to generate a pdf file using itextsharp in asp.net c#.
I came across table concept in itextsharp n i am trying to use it ie my application. I am having the following problem while using tables.
The pdf cell which contains Name of treasery the word treasery comes on next line. I am setting width for each cell. if i increase the width than also no changes come. The gap which is shown using arrow in below image remain as it is al the time. Why is that gap?How to remove that gap?
I want a dotted line as a border to only one cell. how to do that?here is my code
PdfPTable line6table = new PdfPTable (3);
float[] width = new float[] { 2.5F, 1.5F, 3.0F };
line6table.SetWidths(width);
line6table.HorizontalAlignment = 0;
line6table.WidthPercentage = 100.0f;
line6table.SpacingBefore = 6.0f;
PdfPCell a1 = new PdfPCell(new Phrase("Head Of Account"));
a1.Border = 1;
a1.Indent = 2.2f;
a1.PaddingTop = 5.0f;
line6table.AddCell(a1);
PdfPCell a2 = new PdfPCell(new Phrase("CHARGED"));
a2.Border = 1;
a2.PaddingTop = 5.0f;
line6table.AddCell(a2);
PdfPCell a3 = new PdfPCell(new Phrase("Name of the treasry"));
a3.Border = 0;
a3.Indent = 15.0f;
a3.RightIndent = 0.0f;
a3.HorizontalAlignment = 1;
line6table.AddCell(a3);
pdfDocument.Add(line6table);
Please help me to resolve my problem.
line6table.WidthPercentage = 100.0f;
This did it for me.
Increase the width of the column.

Categories