tags:

views:

855

answers:

3

I was wondering what would be the best approach for creating tables in a pdf that have rounded corners using the iTextSharp library.

Thanks

A: 

I assume that if you are wanting a table with rounded corners, you're looking for some flashy (or at least pretty) formatting on your table. If that is the case, I would recommend turning off all the borders in your iTextSharp table, and using a graphic image as the background on your page. You can then make the graphic background as intricate and fancy as you want (shading, gradients, rounded corners, etc.) with very little trouble. Then, just line up your table with the background image.

If your data format will change often, you will not want to use this approach.

Stewbob
+2  A: 

There's no way to create an iTextSharp PdfPTable with rounded corners but what you could do is draw a table border with rounded corners using the PdfContentByte.RoundRectangle() method.

Here's a snippet that demonstrates this:

Document doc = new Document();
using (FileStream fs = new FileStream("RoundRectangle Demo.pdf", FileMode.Create)) {
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
    doc.Open();
    PdfContentByte cb = writer.DirectContent;

    // Bottom left coordinates x & y, followed by width, height and radius of corners.
    cb.RoundRectangle(100f, 500f, 200f, 200f, 2f);
    cb.Stroke();

    doc.Close();
}

This snippet is a condensed version of code I found in the article iTextSharp - Drawing shapes and Graphics on www.mikesdotnetting.com. You'll want to take a close look at his other articles if you haven't already.

Jay Riggs
That worked great. Do you know how I could find the positioning of the table so that I can accurately draw the rounded corners.
Rick Make
+1  A: 

If you have iTextSharp source code, add the following to PdfContentByte class:

/// <summary>
        /// Enumuration for defining corners you want rounded.
        /// </summary>
        [Flags()]
        public enum Corners {None = 0,All=15,Top=3,Bottom=12, TopLeft = 1, TopRight=2, BottomLeft=4, BottomRight=8};

        /// <summary>
        /// Adds a round rectangle to the current path, with rounded conrners as specified by roundCorners.
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="w"></param>
        /// <param name="h"></param>
        /// <param name="r"></param>
        /// <param name="roundCorners"></param>
        public void RoundRectangle(float x, float y, float w, float h, float r,Corners roundCorners)
        {
            if (w < 0)
            {
                x += w;
                w = -w;
            }
            if (h < 0)
            {
                y += h;
                h = -h;
            }
            if (r < 0)
                r = -r;
            float b = 0.4477f;
            if((roundCorners & Corners.BottomLeft) == Corners.BottomLeft)
                MoveTo(x + r, y);
            else
                MoveTo(x, y);

            if ((roundCorners & Corners.BottomRight) == Corners.BottomRight)
            {
                LineTo(x + w - r, y);
                CurveTo(x + w - r * b, y, x + w, y + r * b, x + w, y + r);
            }
            else
                LineTo(x + w, y);

            if ((roundCorners & Corners.TopRight ) == Corners.TopRight)
            {
                LineTo(x + w, y + h - r);
                CurveTo(x + w, y + h - r * b, x + w - r * b, y + h, x + w - r, y + h);
            }
            else
                LineTo(x + w, y + h);

            if ((roundCorners & Corners.TopLeft)  == Corners.TopLeft)
            {
                LineTo(x + r, y + h);
                CurveTo(x + r * b, y + h, x, y + h - r * b, x, y + h - r);
            }
            else
                LineTo(x , y + h);

            if ((roundCorners & Corners.BottomLeft) == Corners.BottomLeft)
            {
                LineTo(x, y + r);
                CurveTo(x, y + r * b, x + r * b, y, x + r, y);
            }else
                LineTo(x, y);
        }        

Next step is to implment IPdfPCellEvent interface:

public class myCellEvent : IPdfPCellEvent
    {
        #region members
        PdfContentByte.Corners _roundedCorners;
        float _roundness;
        #endregion

        #region ctor
        public myCellEvent()
            :this( PdfContentByte.Corners.All,2f)
        {

        }

        public myCellEvent(PdfContentByte.Corners roundedCorners)
            : this(roundedCorners, 2f)
        {

        }

        public myCellEvent(PdfContentByte.Corners roundedCorners,float roundness)
        {
            _roundedCorners = roundedCorners;
            _roundness = roundness;

        } 
        #endregion

        #region IPdfPCellEvent Members
        public void CellLayout(PdfPCell cell, Rectangle position, PdfContentByte[] canvases)
        {
            PdfContentByte cb = canvases[PdfPTable.LINECANVAS];
            cb.RoundRectangle(position.Left, position.Bottom, position.Right - position.Left, position.Top - position.Bottom, this._roundness, this._roundedCorners);
            cb.SetColorStroke(new BaseColor(System.Drawing.Color.Black));
            cb.SetColorFill(new BaseColor(System.Drawing.Color.Beige));            
            cb.FillStroke();
            cb.Stroke();
        }
        #endregion
    }

Then you round what ever corners you want to produce the rounded table of choice:

PdfPTable table = new PdfPTable(1);


                PdfPCell cell = new PdfPCell(new Phrase(10, atext, f2));
                cell.Border = 0;
                cell.Padding = 5f;
                cell.CellEvent = new myCellEvent(PdfContentByte.Corners.Top,2f);
                table.AddCell(cell);

If you like the answer ... give it a vote :)

MK
That is great for individual cells but what about the entire table? How could implement TableCell Events to accomplish this.
Rick Make
Adding another table with one cell that contains my target table works. Thanks again for your answer MK.
Rick Make
I'am glad that you have found the answer, another approach would be by rounding one corner of each table corner cell (TopLeft, TopRight, BottomLeft and BottomRight).
MK