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.
Related
transform pdf points to pixels, worked correctly:
point-to-pixel = 1/72*300(DPI)
getting each text chunk positions (X,Y) in PDF the Y is calculated from
bottom-to-top, not as in standard html or java Script.
to get the Y value from top-to-down , cause not accurate Y position as in
html style , or win Form style.
how to get the correct Y top-to-down using any Page height, or rect mediaBox
or cropBox or rect textMarging finder ?
the code I used is your example of :
public class LocationTextExtractionStrategyClass : LocationTextExtractionStrategy
{
//Hold each coordinate
public List<RectAndText> myPoints = new List<RectAndText>();
/*
//The string that we're searching for
public String TextToSearchFor { get; set; }
//How to compare strings
public System.Globalization.CompareOptions CompareOptions { get; set; }
public MyLocationTextExtractionStrategy(String textToSearchFor, System.Globalization.CompareOptions compareOptions = System.Globalization.CompareOptions.None)
{
this.TextToSearchFor = textToSearchFor;
this.CompareOptions = compareOptions;
}
*/
//Automatically called for each chunk of text in the PDF
public override void RenderText(TextRenderInfo renderInfo)
{
base.RenderText(renderInfo);
//See if the current chunk contains the text
var startPosition = 0;// System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(renderInfo.GetText(), this.TextToSearchFor, this.CompareOptions);
//If not found bail
if (startPosition < 0)
{
return;
}
//Grab the individual characters
var chars = renderInfo.GetCharacterRenderInfos().ToList();//.Skip(startPosition).Take(this.TextToSearchFor.Length)
var charsText = renderInfo.GetText();
//Grab the first and last character
var firstChar = chars.First();
var lastChar = chars.Last();
//Get the bounding box for the chunk of text
var bottomLeft = firstChar.GetDescentLine().GetStartPoint();
var topRight = lastChar.GetAscentLine().GetEndPoint();
//Create a rectangle from it
var rect = new iTextSharp.text.Rectangle(
bottomLeft[Vector.I1],
bottomLeft[Vector.I2],
topRight[Vector.I1],
topRight[Vector.I2]
);
BaseColor curColor = new BaseColor(0f, 0f, 0f);
if (renderInfo.GetFillColor() != null)
curColor = renderInfo.GetFillColor();
//Add this to our main collection
myPoints.Add(new RectAndText(rect, charsText, curColor));//this.TextToSearchFor));
}
}//end-of-txtLocation-class//
You are asking many different questions in one post.
First let's start with the coordinate system in the PDF standard. Observe that I am talking about a standard, more specifically about ISO 32000. The coordinate system on a PDF page is explained in my answer to the Stack Overflow question How should I interpret the coordinates of a rectangle in PDF?
As you can see, a rectangle drawn in a PDF using a coordinate (llx, lly) for the lower-left corner and a coordinate (urx, ury) for the upper-right corner, assumes that the X-axis points to the right, and the Y-axis points upwards.
As for the width and the height of a page, that's explained in my answer to the Stack Overflow question How to Get PDF page width and Height?
For instance: you could have a /MediaBox that is defined as [0 0 595 842], and therefore measures 595 x 842 points (an A4 page), but that has a /CropBox that is defined as [5 5 590 837], which means that the visible area is only 585 x 832 points.
You also shouldn't assume that the lower-left corner of a page coincides with the (0, 0) coordinate. See Where is the Origin (x,y) of a PDF page?
When you create a document from scratch, a default margin of half an inch is used if you don't define a margin yourself. If you want to change the default, see Fit content on pdf size with iTextSharp?
Now for the height of a Chunk or, if you're using iText 7 (which you should, but —for some reason unknown to me— don't) the height of a Text object, this depends on the font size. The font size is an average size of the different glyphs in a font. If you look at the letter g, and you compare it with the letter h, you see that g takes more space under the baseline of the text than h, whereas h takes more space above the baseline than g.
If you want to calculate the exact space that is taken, read my answer to the question How to calculate the height of an element?
If the text snippet is used in the context of lines in a paragraph, you also have to take the leading into account: Changing text line spacing (Maybe that's not relevant in the context of your question, but it's good to know.)
If you have Chunk objects in iText 5, and you want to do specific things with these Chunks, you might benefit from using page events. See How to draw a line every 25 words?
If you want to add a colored background to a Chunk, it's even easier: How to set the paragraph of itext pdf file as rectangle with background color in Java
Update 1: All of the above may be irrelevant if you are looking to convert HTML to PDF. In that case, it's easy: use iText 7 + pdfHTML as described in Converting HTML to PDF using iText and all the Math is done by the pdfHTML add-on.
Update 2: There seems to be some confusion regarding the measurement units. The differences between user units, points and pixels is explained in the FAQ page How do the measurement systems in HTML relate to the measurement system in PDF?
Summarized:
1 in. = 25.4 mm = 72 user units by default (but it can be changed).
1 in. = 25.4 mm = 72 pt.
1 in. = 25.4 mm = 96 px.
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.
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.
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.
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.