Kfir
Kfir

Reputation: 105

AutoFit Table Column Widths using iTextSharp and C#

I've exported DataGridView data to PDF using iTextSharp. The column widths are all exactly the same, and some of the header column words are broken up incorrectly. What I'm trying to do is autofit the header columns widths to adjust to each header text length.

Here's my code :

 PdfPTable table = new PdfPTable(dgv.Columns.Count);
        for (int j = 0; j < dgv.Columns.Count; j++)
        {
            Font font = new Font(Font.FontFamily.COURIER, 14, Font.ITALIC);
            font.Color = BaseColor.BLUE;

            if (j == 0)
            {
                Phrase p1 = new Phrase(dgv.Columns[j].HeaderText, font);
                table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
                table.WidthPercentage = 100;
                table.AddCell(p1);
            }

            else
            {
                string header = dgv.Columns[j].HeaderText;
                header = Regex.Replace(dgv.Columns[j].HeaderText, "[A-Z]", " $0").Trim();
                Phrase p = new Phrase(header, font);
                table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
                table.WidthPercentage = 100;
                table.AddCell(p);
            }
        }
        table.HeaderRows = 1;

        for (int i = 0; i < dgv.Rows.Count; i++)
            for (int k = 0; k < dgv.Columns.Count; k++)
                if (dgv[k, i].Value != null)
                {
                    Phrase p = new Phrase(dgv[k, i].Value.ToString());
                    table.DefaultCell.HorizontalAlignment = Element.ALIGN_CENTER;
                    table.AddCell(p);
                }


        doc.Add(table);

And this is the PDF output:

enter image description here

Upvotes: 4

Views: 12294

Answers (1)

goTo-devNull
goTo-devNull

Reputation: 9372

To auto-fit column sizes, you need to calculate the width of the header strings yourself, then set the table column widths.

First a simple helper method to get the column widths from an arbitrary collection of strings:

public float[] GetHeaderWidths(Font font, params string[] headers)
{ 
    var total = 0;
    var columns = headers.Length;
    var widths = new int[columns];
    for (var i = 0; i < columns; ++i)
    {
        var w = font.GetCalculatedBaseFont(true).GetWidth(headers[i]);
        total += w;
        widths[i] = w;
    }
    var result = new float[columns];
    for (var i = 0; i < columns; ++i) 
    {
        result[i] = (float)widths[i] / total * 100;
    }
    return result;
}

Then set the table column widths:

string[] headers = new string[]
{ 
    "Order Id", "Customer Id", "Customer Name", "Product Id",
    "Product Description", "Quantity", "Product Received"
};
Font font = new Font(Font.FontFamily.COURIER, 14, Font.ITALIC);
font.Color = BaseColor.BLUE;
var table = new PdfPTable(headers.Length) { WidthPercentage = 100 };
table.SetWidths(GetHeaderWidths(font, headers));

using (var stream = new MemoryStream())
{
    using (var document = new Document(PageSize.A4.Rotate()))
    {
        PdfWriter.GetInstance(document, stream);
        document.Open();
        for (int i = 0; i < headers.Length; ++i)
        {
            table.AddCell(new PdfPCell(new Phrase(headers[i], font)));
        }
        document.Add(table);
    }
    File.WriteAllBytes(OUT_FILE, stream.ToArray());
}

The output:

enter image description here

Upvotes: 7

Related Questions