How to add a table as a header? - c#

I am working with iTextSharp trying to add an header and a footer to my generated PDF but, if I try to add an header that have width of 100% of my page I have some problem.
So I have do the following things:
1) I have create a class named PdfHeaderFooter that extends the iTextSharp PdfPageEventHelper class
2) Into PdfHeaderFooter I have implemented the OnStartPage() method that generate the header:
// write on start of each page
public override void OnStartPage(PdfWriter writer, Document document)
{
base.OnStartPage(writer, document);
PdfPTable tabHead = new PdfPTable(new float[] { 1F });
PdfPCell cell;
//tabHead.TotalWidth = 300F;
tabHead.WidthPercentage = 100;
cell = new PdfPCell(new Phrase("Header"));
tabHead.AddCell(cell);
tabHead.WriteSelectedRows(0, -1, 150, document.Top, writer.DirectContent);
}
If I use sometning like tabHead.TotalWidth = 300F; insted tabHead.WidthPercentage = 100; it work well but if I try to set as 100% the width of the tabHead table (as I do in the previous example) when it call the tabHead.WriteSelectedRows(0, -1, 150, document.Top, writer.DirectContent) method it throw the following exception:
The table width must be greater than zero.
Why? What is the problem? How is it possible that the table have 0 size if I am setting it to 100%?
Someone can help me to solve this issue?
Tnx

When using writeSelectedRows(), it doesn't make sense to set the width percentage to 100%. Setting the width percentage is meant for when you add a document using document.add() (which is a method you can't use in a page event). When using document.add(), iText calculates the width of the table based on the page size and the margins.
You are using writeSelectedRows(), which means you are responsible to define the size and the coordinates of the table.
If you want the table to span the complete width of the page, you need:
table.TotalWidth = document.Right - document.Left;
You're also using the wrong X-coordinate: you should use document.Left instead of 150.
Additional info:
The first two parameters define the start row and the end row. In your case, you start with row 0 which is the first row, and you don't define an end row (that's what -1 means) in which case all rows are drawn.
You omitted the parameters for the columns (there's a variation of the writeSelectedRows() that expects 7 parameters).
Next you have the X and Y value of start coordinate for the table.
Finally, you pass a PdfContentByte instance. This is the canvas on which you're drawing the table.

Related

How to get MigraDoc to produce PDF with dynamic page width?

I have a PDF doc that I am trying to create, with about 20 columns, varying width. It gets about half of the columns on the first page and then cuts off the rest.I would like it to determine the page width and move the remaining columns onto the second page. Is there a way to specify this in rendering or PageSetup? I think I'll have to calculate the width, create the first page and then create the second.
Table table = new Table();
PdfDocumentRenderer renderer = new PdfDocumentRenderer(true, PdfSharp.Pdf.PdfFontEmbedding.Always);
renderer.Document = doc;
doc.DefaultPageSetup.Orientation = MigraDoc.DocumentObjectModel.Orientation.Landscape;
//create the columns
for (int i = 1; i < tripReportGrid.Columns.Count; i++)
{
col = table.AddColumn(tripReportGrid.Columns[i].Width);
col.Format.Alignment = ParagraphAlignment.Center;
}
...fill the content same way
renderer.RenderDocument();
The width of the page is what you set - or A4 if you set nothing.
You can set the width of the page to any value. That will probably be OK when viewing the PDF file on the screen.
Or you can only add as many columns to one table as fit on one page. A4 in landscape format is 29.7 cm. Default margins are 2.5 cm left and right.
And BTW: you should never modify the DefaultPageSetup. Assign a Clone() of the DefaultPageSetup to the PageSetup of your Section and change that as needed.

How to define the page size based on the content?

I'm generating a PDF document with iTextSharp. This document must have only one page. In other words the content must fit the page size.
Is it possible to achieve this with iTextSharp?
I tried to get the height of the content before adding it to the document, so I can calculate the total size before creating the document,
but some content types (tables for example) don't have height until they are added to the document.
If you create a PdfPTable and if you define the width of the table, for instance like this:
table.TotalWidth = 400f;
table.LockedWidth = true;
Then you can use ask the table for its height like this:
Float h = table.TotalHeight;
You can use h to define your page size, for instance:
Document document = new Document(400, h, 0, 0, 0, 0);
Note that all measurements are done in user units and that one user unit equals 1 pt by default. The getTotalHeight() method will return 0 if you don't define the width, because the height depends on the width and the table doesn't know the width before it is rendered.

How to put a table in the center of the page?

With MigraDoc I'm trying to put a table in the center of the page.
I'm using this code (c#, VS).
Section secondPage = new Section();
Table table = new Table();
AddColumns(table);
AddFirstRow(table);
AddSecondRow(table);
table.Format.Alignment=ParagraphAlignment.Center;
secondPage.Add(table);
I get a table aligned to the right of the page; how can I obtain a table in the center of the page?
To center a table in the center of a section.
table.Rows.Alignment = RowAlignment.Center;
You can set table.Rows.LeftIndent to indent the table. To get a centered table, calculate the indent based on paper size, page margins, and table width.
Example: Paper size is A4 (21 cm wide), left and right margins are 2.5 cm each. Thus we have a page body of 16 cm.
To center a table that is 12 cm wide, table.Rows.LeftIndent must be set to 2 cm (16 cm body width minus 12 cm table width gives 4 cm remaining space - half of the remaining space must be set as the LeftIndent).
From the code snippet in the original question, remove table.Format.Alignment=ParagraphAlignment.Center; and replace it with table.Rows.LeftIndent="2cm";.
Note that this will also work if the table is slightly wider than the body, but still within page edges. Using the page setup from the previous example, a table that is 18 cm wide can be centered with a LeftIndent of -1 cm.
Sample code (the table has just a single column):
var doc = new Document();
var sec = doc.AddSection();
// Magic: To read the default values for LeftMargin, RightMargin &c.
// assign a clone of DefaultPageSetup.
// Do not assign DefaultPageSetup directly, never modify DefaultPageSetup.
sec.PageSetup = doc.DefaultPageSetup.Clone();
var table = sec.AddTable();
// For simplicity, a single column is used here. Column width == table width.
var tableWidth = Unit.FromCentimeter(8);
table.AddColumn(tableWidth);
var leftIndentToCenterTable = (sec.PageSetup.PageWidth.Centimeter -
sec.PageSetup.LeftMargin.Centimeter -
sec.PageSetup.RightMargin.Centimeter -
tableWidth.Centimeter) / 2;
table.Rows.LeftIndent = Unit.FromCentimeter(leftIndentToCenterTable);
table.Borders.Width = 0.5;
var row = table.AddRow();
row.Cells[0].AddParagraph("Hello, World!");
The sample code uses Centimeter for calculations. You can also use Inches, Millimeter, Picas or Points.
Default page size is A4 and in the sample the LeftIndent will be 4 cm.

How can I control table column width in Word documents using DocX?

I am trying to recreate a table like this:
I am using the DocX library to manipulate Word files, but I'm having trouble getting the widths right. Trying to set the widths of cells only seems to work when it's not set to the window autofit mode, and it only seems to resize when the specified width is greater than half of the table width, or rather, I can make a cell bigger than half the width but not smaller.
What would be the simplest way to reproduce the intended table?
I found the answer to this myself. In order to properly set the width, you have to loop through each cell in a column and set every width. This will not work with any autofit options selected.
Try this :
Table table = doc.AddTable(2, 2);
table.SetColumnWidth(0, 500);
//first is column index, the second is column width
Bit of an old post to tag to, but after having the same issue it would appear that none of the widths on either the cells or columns actually work, so as a dirty workaround, you can loop through each column and cell adding text to each of the cells, make the text white and finally use the autofit option to autofit to contents eg.
Table t2 = doc.AddTable(2, 8);
for (int i = 0; i < t2.RowCount; i ++)
{
for(int x = 0; x < t2.ColumnCount; x++)
{
t2.Rows[i].Cells[x].Paragraphs.First().Append("12").Color(Color.White);
}
}
t2.AutoFit = AutoFit.Contents;
doc.InsertTable(t2);
This is the way:
Table t = doc.AddTable(1, 5);
t.SetWidthsPercentage(new[] { 20f, 20f, 40f, 10f, 10f }, 500);
The float array sets width percentage for each of the columns, second parameter is the total width of the table.

How to generate text box with max height in iTextSharp (auto-grow?)

We have a vehicle "Description" that could be anywhere from a few words to a few paragraphs. It needs to not go beyond a certain height (like 100px or whatever). Perfect solution would allow the text box to auto-grow (i.e. be as small as possible, but be able to grow up to a max height). There doesn't seem to be a way to restrict the height of a Paragraph or Phrase or anything. I have been messing with ColumnText but I can't seem to figure out how to make a ColumnText go into the flow of the document, so the next element after the Description goes below it and not on top of it. I have also seen ct.SetTextMatrix(xPos, yPos), but that still doesn't get me a max height box. Have I just not found what I'm needing yet, or does it not exist in iTextSharp?
Thank you so much, #Chris Haas! My solution was eventually found by the link he posted.
First, at the top of the page, we do the table height calculation:
PdfPTable tempTable = new PdfPTable(1);
tempTable.SetTotalWidth(new float[] { 540 }); //540 is width of PageSize.LETTER minus 36*2 for margins
string itemDescription = item.Description;
tempTable.AddCell(itemDescription);
float descriptionTableHeight = CalculatePdfPTableHeight(tempTable);
Then, the code for actually generating the PDF:
using (MemoryStream ms = new MemoryStream())
{
using (Document document = new Document(PageSize.LETTER))
{
using (PdfWriter writer = PdfWriter.GetInstance(document, ms))
{
document.Open();
//document properties
float margin = 36f;
document.SetMargins(margin, margin, margin, margin);
document.NewPage();
//description
customFont = FontFactory.GetFont("Helvetica", 10);
Phrase description = new Phrase(itemDescription, customFont);
table = new PdfPTable(1);
table.WidthPercentage = 100;
cell = new PdfPCell(description);
cell.Border = 0;
float maxHeight = 98f;
if (descriptionTableHeight > maxHeight)
cell.FixedHeight = maxHeight;
table.AddCell(cell);
document.Add(table);
}
}
}
So since we now have the table's height, we can check to see if it is greater than a maximum value and set the FixedHeight of the cell if so. And since we are able to add the table to the document, it goes in the normal flow of the page.
Thanks to the commenters for the leads!

Categories