Ovis
Ovis

Reputation: 391

iTextSharp PdfPCell align image to bottom of cell

I'm trying to align an image to the bottom-right of a cell. I'm basically creating a table with two cells for each row. The cell contains text and an image, which I want to be aligned to the right bottom of the cells. Please refer to image

This is my code

 PdfPTable table = new PdfPTable(2);
 table.TotalWidth = 400f;
 table.LockedWidth = true;

 float[] widths = new float[] { 1.5f, 1.5f };
 table.SetWidths(widths);
 table.HorizontalAlignment = 0;

 table.SpacingBefore = 50f;
 table.SpacingAfter = 30f;

 iTextSharp.text.Image logoImage = iTextSharp.text.Image.GetInstance(HttpContext.Current.Server.MapPath("~/Images/MyImage.png"));
 logoImage.ScaleAbsolute(40, 40);
 logoImage.Alignment = iTextSharp.text.Image.ALIGN_BOTTOM;
 logoImage.Alignment = iTextSharp.text.Image.RIGHT_ALIGN;

 foreach (EmployeeModel employee in employees)
 {
    PdfPCell cell = new PdfPCell();
    cell.FixedHeight = 140f;

    cell.PaddingLeft = 30f;
    cell.PaddingRight = 10f;
    cell.PaddingTop = 20f;
    cell.PaddingBottom = 5f;

    Paragraph p = new Paragraph(GetLabelCellText(Employee), NormalFont);
    p.Alignment = Element.ALIGN_LEFT;
    p.Alignment = Element.ALIGN_TOP;
    cell.AddElement(p);

    cell.AddElement(logoImage);

    table.AddCell(cell);
 }

How do I place the image at the bottom right of each cell (without affecting the position of the text of course).

Upvotes: 1

Views: 2338

Answers (1)

goTo-devNull
goTo-devNull

Reputation: 9372

The question is a bit ambiguous because you create a Table with two columns, but add cells without verifying the employees collection has an even number of elements, which will throw if not....

Assuming you really do want both the text and the image in a single cell, probably the simplest way to get the layout you want is to implement IPdfPCellEvent:

public class BottomRightImage : IPdfPCellEvent
{
    public Image Image { get; set;  }

    public void CellLayout(
        PdfPCell cell, 
        Rectangle position, 
        PdfContentByte[] canvases)
    {
        if (Image == null) throw new InvalidOperationException("image is null");

        PdfContentByte canvas = canvases[PdfPTable.TEXTCANVAS];
        Image.SetAbsolutePosition(
            position.Right - Image.ScaledWidth - cell.PaddingRight, 
            position.Bottom + cell.PaddingBottom
        );
        canvas.AddImage(Image);
    }
}

Then set the CellEvent property on the PdfPCell. Here's a simple working example:

using (var stream = new MemoryStream())
{
    using (var document = new Document())
    {
        PdfWriter.GetInstance(document, stream);
        document.Open();
        var table = new PdfPTable(2)
        {
            HorizontalAlignment = Element.ALIGN_LEFT,
            TotalWidth = 400f,
            LockedWidth = true                        
        };

        var image = Image.GetInstance(imagePath);
        image.ScaleAbsolute(40, 40);
        var cellEvent = new BottomRightImage() { Image = image };

        var testString =
@"first name: {0}
last name: {0}
ID no: {0}";
        for (int i = 0; i < 2; ++i)
        {
            var cell = new PdfPCell()
            {
                FixedHeight = 140f,
                PaddingLeft = 30f,
                PaddingRight = 10f,
                PaddingTop = 20f,
                PaddingBottom = 5f
            };
            cell.CellEvent = cellEvent;

            var p = new Paragraph(string.Format(testString, i))
            {
                Alignment = Element.ALIGN_TOP | Element.ALIGN_LEFT
            };
            cell.AddElement(p);
            table.AddCell(cell);
        }
        document.Add(table);
    }
    File.WriteAllBytes(outputFile, stream.ToArray());
}

And PDF output:

enter image description here

An all-black square image is used to show the PdfPCell padding is taken into account.

Upvotes: 0

Related Questions