I am using iTextSharp version 5.4.5.0.
I have a problem while adding new page using document.NewPage() method.
When I will use above method to add new page, the content of this new page will overlap with my header section. I have created my header table in OnEndPage() method of PdfPageEventHelper class.
Here is the code for my header in OnEndPage event:
PdfPTable table = new PdfPTable(1);
table.TotalWidth = document.PageSize.Width - document.LeftMargin - document.RightMargin;
PdfPTable headerTable = new PdfPTable(1) { TotalWidth = document.PageSize.Width };
PdfPCell cImage = new PdfPCell(ImageHeader, true);
cImage.HorizontalAlignment = Element.ALIGN_RIGHT;
cImage.Border = iTextSharp.text.Rectangle.NO_BORDER;
cImage.FixedHeight = 45f;
cImage.PaddingTop = 0f;
headerTable.AddCell(cImage);
PdfPCell cell = new PdfPCell(headerTable) { Border = Rectangle.NO_BORDER };
table.AddCell(cell);
table.WriteSelectedRows(0, -1, document.LeftMargin, document.Top, writer.DirectContent); // Here the document.Top value is 45
And I have also assign margin top as 45 while creating document object as below:
MemoryStream workStream = new MemoryStream();
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, workStream);
document.SetMargins(30, 30, 45, 30);
Can anyone help me to not overlap document content with header table while adding new page ?
Thanks.
When you do this:
table.WriteSelectedRows(0, -1, document.LeftMargin, document.Top, writer.DirectContent);
You claim // Here the document.Top value is 45 but that is not correct!
You create your document like this:
Document document = new Document();
This means that the lower-left coordinate of your document is (0, 0) and the upper-right coordinate is (595, 842).
Then you define margins for the document:
document.SetMargins(30, 30, 45, 30);
This means that:
Document.Left = 0 + 30 = 30
Document.Right = 595 - 30 = 565
Document.Top = 842 - 45 = 797
Document.Bottom = 0 + 30 = 30
So when you have this line:
table.WriteSelectedRows(0, -1, document.LeftMargin, document.Top, writer.DirectContent);
You actually have:
table.WriteSelectedRows(0, -1, 30, 797, writer.DirectContent);
This is totally wrong because that makes your table overlap with whatever content you are adding inside the margins.
To solve this, you need to calculate the height of the table. See for instance the answer to the question How to define the page size based on the content?
table.LockedWidth = true;
Float h = table.TotalHeight;
Now you can use h to define the top margin:
document.SetMargins(30, 30, 20 + h, 30);
And you can use Document.Top to define the y position of the table:
table.WriteSelectedRows(0, -1,
document.LeftMargin,
document.Top + h + 10,
writer.DirectContent);
With this code, the table will be added inside the margin, leaving 10 user units of white space under the top of the page and 10 user units of white space above the top margin.
Related
So I'm applying a canvas stroke to my pdf, but the stroke is applying to the cell text. But only the first cell.
Here is the method to draw the page border:
protected void DrawPageBorder(PdfWriter writer, Document document, PdfContentByte canvas)
{
var pageBorderRect = new Rectangle(document.PageSize);
var content = writer.DirectContent;
pageBorderRect.Left += document.LeftMargin - BorderDifference;
pageBorderRect.Right -= document.RightMargin - BorderDifference;
pageBorderRect.Top -= document.TopMargin - BorderDifference;
pageBorderRect.Bottom += document.BottomMargin - BorderDifference;
content.SetLineDash(3f, 3f);
content.SetRGBColorStroke(236, 236, 236);
//canvas.SetLineWidth(FillOpacity);
//canvas.SetRGBColorStroke(0, 0, 0);
//canvas.SetRGBColorStroke(236, 236, 236);
//canvas.SetLineDash(3f, 3f);
content.Rectangle(pageBorderRect.Left, pageBorderRect.Bottom, pageBorderRect.Width, pageBorderRect.Height);
content.Stroke();
}
this is the code which adds the pdf table with the border:
var docTable = new PdfPTable(1);
docTable.WidthPercentage = 100f;
PdfContentByte canvas = new PdfContentByte(pdfWriter);
DrawPageBorder(pdfWriter, doc, canvas);
This is the code to add the first table cell:
titleFont.Size = 24.0f;
var text1 = new PdfPCell(new Phrase("To:", titleFont))
{
HorizontalAlignment = Element.ALIGN_LEFT,
Border = Rectangle.NO_BORDER,
PaddingTop = 20f,
PaddingLeft = 9f,
PaddingRight = 9f
};
docTable.AddCell(text1);
Anyone know where I'm going wrong here?
Thanks
Whenever you mix high level api content creating (like you do with the table) and low level api drawing (like you do in DrawPageBorder), make sure your low level code does not leave behind any change to graphics state parameters.
Your code leaves changes to the LineDash and the stroking color.
You can do so by wrapping your code drawing on content in a safe-graphics-state / restore-graphics-state envelop.
In your case:
content.SaveState();
content.SetLineDash(3f, 3f);
content.SetRGBColorStroke(236, 236, 236);
//canvas.SetLineWidth(FillOpacity);
//canvas.SetRGBColorStroke(0, 0, 0);
//canvas.SetRGBColorStroke(236, 236, 236);
//canvas.SetLineDash(3f, 3f);
content.Rectangle(pageBorderRect.Left, pageBorderRect.Bottom, pageBorderRect.Width, pageBorderRect.Height);
content.Stroke();
content.RestoreState();
I have the following problem using iTextSharp.
I am putting some tables into my document. The problem is that if a table content not fit on a page and go into another page I have that it overwrite the second page header, so I have the following situation:
As you can see I am inserting a table at the end of a page and this is split into two pages and the second page header is overwrite by the table content.
I want to avoid this situation but I don't know how have I to do.
I am thinking that maybe I can do one of the following things:
Maybe I can check if an element completely enter into a page. If not create a new page and put it into this new page (but this can be a problem if a single table need more then one page, in the case if I have a very big table)
I allow that a table is split across 2 pages but in this case I left some margin spacing in the upper of the second page so the header is correctly shown.
Or what can I do to solve this situation?
Tnx
EDIT:
I have add the header in the following way:
I have implement create a class named PdfHeaderFooter that extends the PdfPageEventHelper class and that implements its methods.
At this time its class contains the following methods:
// write on start of each page
public override void OnStartPage(PdfWriter writer, Document document)
{
base.OnStartPage(writer, document);
PdfPTable tabHead = new PdfPTable(3);
tabHead.SetWidths(new int[] { 165, 205, 125 });
//tabHead.TotalWidth = 460F;
tabHead.TotalWidth = document.Right - document.Left; // TotalWidth = 495
tabHead.WidthPercentage = 98;
PdfPCell cell1 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "logoEarlyWarning.png"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell1);
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 1:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15, });
tabHead.AddCell(new PdfPCell(new Phrase("")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
if(_sourceId == "NVD")
{
iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png");
logo.ScalePercent(48f);
//PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png"), true) { Border = PdfPCell.BOTTOM_BORDER, PaddingBottom = 25 };
PdfPCell cell3 = new PdfPCell(logo) { Border = PdfPCell.BOTTOM_BORDER, PaddingLeft = 50 };
tabHead.AddCell(cell3);
}
else if(_sourceId == "DeepSight")
{
PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "DSLogo.jpg"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell3);
}
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 3:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
}
// write on end of each page
public override void OnEndPage(PdfWriter writer, Document document)
{
base.OnEndPage(writer, document);
int pageN = writer.PageNumber; // numero della pagina corrente OK
String text = "Page " + pageN + " of ";
float len = bf.GetWidthPoint(text, 8);
Rectangle pageSize = document.PageSize;
cb.SetRGBColorFill(100, 100, 100);
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30));
cb.ShowText(text);
cb.EndText();
cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30));
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
"Printed On " + PrintTime,
pageSize.GetRight(40),
pageSize.GetBottom(30), 0);
cb.EndText();
}
So ad you can see, the OnStartPage() method add the header at the beginning of each pages and the OnEndPage() add the footer at the end of each pages.
So from what I understand from your response I have to do the followings steps:
Move the header insertion from OnStartPage() to OnEndPage()
Use an absolute position for place it in the upper part of the pages.
In the document creation use the header height to set the top margin.
Is it right?
EDIT 2:
I tried to do as you say to me and now I have the following situations:
Into my PdfHeaderFooter that extends PdfPageEventHelper I have deleted the OnStartPage() method
I have moved the header table creation into the OnEndPage() method that now it this one:
// write on end of each page
public override void OnEndPage(PdfWriter writer, Document document)
{
base.OnEndPage(writer, document);
// HEADER:
PdfPTable tabHead = new PdfPTable(3);
tabHead.SetWidths(new int[] { 165, 205, 125 });
//tabHead.TotalWidth = 460F;
tabHead.TotalWidth = document.Right - document.Left; // TotalWidth = 495
tabHead.WidthPercentage = 98;
PdfPCell cell1 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "logoEarlyWarning.png"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell1);
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 1:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15, });
tabHead.AddCell(new PdfPCell(new Phrase("")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
if (_sourceId == "NVD")
{
iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png");
logo.ScalePercent(48f);
//PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png"), true) { Border = PdfPCell.BOTTOM_BORDER, PaddingBottom = 25 };
PdfPCell cell3 = new PdfPCell(logo) { Border = PdfPCell.BOTTOM_BORDER, PaddingLeft = 50 };
tabHead.AddCell(cell3);
}
else if (_sourceId == "DeepSight")
{
PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "DSLogo.jpg"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell3);
}
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 3:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
float headerHeight = tabHead.CalculateHeights();
// FOOTER:
int pageN = writer.PageNumber; // numero della pagina corrente OK
String text = "Page " + pageN + " of ";
float len = bf.GetWidthPoint(text, 8);
Rectangle pageSize = document.PageSize;
cb.SetRGBColorFill(100, 100, 100);
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30));
cb.ShowText(text);
cb.EndText();
cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30));
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
"Printed On " + PrintTime,
pageSize.GetRight(40),
pageSize.GetBottom(30), 0);
cb.EndText();
}
As you can see now the OnEndPage() method contains the header and footer creation.
It seems to me that tabHead (my header table) use the absolute positioning because I have:
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
In the other class where I create the document I have this line:
document = new iTextSharp.text.Document(iTextSharp.text.PageSize.A4, 50, 50, 30, 65);
so the pages are A4 and have 30px as upper margin.
But I still have the same problem.
If I change the 30 value with 80 it simply moves down the header leaving a white top but does not solve the problem.
What am I missing? What is wrong?
I assume that you are adding page headers correctly. That is: you have implemented the onEndPage() method in a page event (not the onStartPage() method) and you're adding the header at an absolute position. As you are adding the header at an absolute position, you know exactly how much space it takes.
When you create a document object, you define a page size. If you don't, the page size will be A4 (595 x 842 user units). You also define margins. If you don't, the margins will be half an inch (36 user units) on either side.
When a table splits, the page size and its margins are respected: iText won't put any part of the table in that area.
Hence the solution is simple: as you know the space needed by the header, all you have to do is to define the margin in a way that the header fits into the margin.
Update after the question was updated:
1.
This is wrong:
// write on start of each page
public override void OnStartPage(PdfWriter writer, Document document)
{
...
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
}
You should never add any content in the OnStartPage() method. Move the code that writes the header to the OnEndPage() method.
2.
You are already using an absolute position to add tabHead: you are adding it at the coordinate x = document.left; y = document.Top.
You define a width percentage for a file that is added at an absolute position. That doesn't make any sense, remove the following line:
tabHead.WidthPercentage = 98;
However, you are wasting resources. For instance: you create the logo in the page event: iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png"). This means that you are adding the image bytes as many times as you have pages, resulting in redundant info in the PDF file (you have a bloated file).
You can optimize the process by creating the images outside the onEndPage() method. You can even create the table outside that method. For instance: create a member variable tabHead in the event class and create the table either in the constructor of your event implementation or in the OnOpenDocument() method (that method only gets called once). Reuse the table (and the images) in the onEndPage() method.
Now the image bytes will be present in the PDF file only once (you'll gain plenty of KBytes) and you'll only have to create the table once (less CPU-time wasted).
3.
An even better solution is to create the tabHead object outside the page event and before you open the document. As you define a total width, you can ask the table for its height:
float h = tabHead.TotalHeight;
Now you can use h to define the top margin:
document.SetMargins(36f, 36f, h, 36f);
Note that it is important to set the margins before you open your document. You'll also have to adapt the coordinate at which you add the table. For instance:
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top + h, writer.DirectContent);
Your comment regarding the position of the header revealed a serious lack of insight.
I have a class named PdfHeaderFooter that extends PdfPageEventHelper class.
In this class I have implemented the OnEndPage() method in this way. How you can see this method create the header and the footer of each pages of the document.
Now I have to add the PdfPTable tabHead in absolute position at the beginning of the page.
What can I have to do? I am going crazy trying to do it
// write on end of each page
public override void OnEndPage(PdfWriter writer, Document document)
{
base.OnEndPage(writer, document);
// HEADER:
PdfPTable tabHead = new PdfPTable(3);
tabHead.SetWidths(new int[] { 165, 205, 125 });
//tabHead.TotalWidth = 460F;
tabHead.TotalWidth = document.Right - document.Left; // TotalWidth = 495
tabHead.WidthPercentage = 98;
PdfPCell cell1 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "logoEarlyWarning.png"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell1);
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 1:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15, });
tabHead.AddCell(new PdfPCell(new Phrase("")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
if (_sourceId == "NVD")
{
iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png");
logo.ScalePercent(48f);
//PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "nvdLogo.png"), true) { Border = PdfPCell.BOTTOM_BORDER, PaddingBottom = 25 };
PdfPCell cell3 = new PdfPCell(logo) { Border = PdfPCell.BOTTOM_BORDER, PaddingLeft = 50 };
tabHead.AddCell(cell3);
}
else if (_sourceId == "DeepSight")
{
PdfPCell cell3 = new PdfPCell(iTextSharp.text.Image.GetInstance(folderImages + "DSLogo.jpg"), true) { Border = PdfPCell.BOTTOM_BORDER };
tabHead.AddCell(cell3);
}
//tabHead.AddCell(new PdfPCell(new Phrase("CELL 3:")) { Border = PdfPCell.BOTTOM_BORDER, Padding = 5, MinimumHeight = 50, PaddingTop = 15 });
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top, writer.DirectContent);
float headerHeight = tabHead.CalculateHeights();
// FOOTER:
int pageN = writer.PageNumber; // numero della pagina corrente OK
String text = "Page " + pageN + " of ";
float len = bf.GetWidthPoint(text, 8);
Rectangle pageSize = document.PageSize;
cb.SetRGBColorFill(100, 100, 100);
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30));
cb.ShowText(text);
cb.EndText();
cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30));
cb.BeginText();
cb.SetFontAndSize(bf, 8);
cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
"Printed On " + PrintTime,
pageSize.GetRight(40),
pageSize.GetBottom(30), 0);
cb.EndText();
}
Tnx
This question has already been answered here: How to handle the case in wich an iText\iTextSharp table is splitted in two pages?
You are adding the header at the beginning of the page, taking into account the margin. You want to add the table inside the margin. hence you need to add the height of the table to the Y-coordinate of the upper margin.
For instance: if the height of the table is h, then you need:
tabHead.WriteSelectedRows(0, -1, document.Left, document.Top + h, writer.DirectContent);
What's the point in asking questions if you don't read people's answers? You're still generating a bloated PDF file! Fix that!
I use itextsharp and i need to draw a dotted linebreak from left to right of the page(100% width) but don't know how. The doc always has a margin left right. Please help
var pageSize = PageSize.A4;
if (_pdfSettings.LetterPageSizeEnabled)
{
pageSize = PageSize.LETTER;
}
var doc = new Document(pageSize);
PdfWriter.GetInstance(doc, stream);
doc.Open();
//fonts
var titleFont = GetFont();
titleFont.SetStyle(Font.BOLD);
titleFont.Color = BaseColor.BLACK;
titleFont.Size = 16;
var largeFont = GetFont();
largeFont.SetStyle(Font.BOLD);
largeFont.Color = BaseColor.BLACK;
largeFont.Size = 18;
int ordCount = orders.Count;
int ordNum = 0;
foreach (var order in orders)
{
var addressTable = new PdfPTable(3);
addressTable.WidthPercentage = 100f;
addressTable.SetWidths(new[] { 25, 37, 37 });
// sender address
cell = new PdfPCell();
//cell.Border = Rectangle.NO_BORDER;
cell.AddElement(new Paragraph("Người Gửi", titleFont));
cell.AddElement(new Paragraph(_localizationService.GetResource("admin.orders.pdfinvoice.sender", lang.Id), smallFont));
cell.AddElement(new Paragraph(_localizationService.GetResource("admin.orders.pdfinvoice.senderaddress", lang.Id), smallFont));
cell.AddElement(new Paragraph(_localizationService.GetResource("PDFInvoice.Hotline", lang.Id), smallFont));
cell.AddElement(new Paragraph("TAKARA.VN", largeFont));
addressTable.AddCell(cell);
......
Chunk linebreak = new Chunk(new DottedLineSeparator());
doc.Add(linebreak);
doc.Add(new Paragraph(""));
....
}
Please take a look at the example FullDottedLine.
You're creating a DottedLineSeparator of which the width percentage is 100% by default. This 100% is the full available width withing the margins of the page. If you want the line to exceed the available width, you need a percentage that is higher than 100%.
In the example, the default page size (A4) and the default margins (36) are used. This means that the width of the page is 595 user units and the available width equals 595 - (2 x 36) user units. The percentage needed to span the complete width of the page equals 100 x (595 / 523).
Take a look at the resulting PDF file full_dotted_line.pdf and you'll see that the line now runs through the margins.
I want to create a PDF file with Icard showing in it.
Following is the code:
iTextSharp.text.Font custFont = new iTextSharp.text.Font() { Size=6f};
int borderSize = 1;
Document IcardDoc = new Document(PageSize.HALFLETTER);
PdfWriter.GetInstance(IcardDoc, Response.OutputStream);
IcardDoc.Open();
PdfPTable icardTable = new PdfPTable(2);
iTextSharp.text.Image logoImage = iTextSharp.text.Image.GetInstance(Server.MapPath("~/images/logo.jpg"));
logoImage.WidthPercentage = 15f;
PdfPCell cell = new PdfPCell(logoImage, false);
cell.PaddingLeft = 10f;
cell.PaddingTop = 10f;
cell.PaddingBottom = 10f;
cell.PaddingRight = 10f;
cell.Colspan = 2;
cell.Border = 0;
cell.HorizontalAlignment = 1;
icardTable.AddCell(cell);
icardTable.AddCell(new PdfPCell(new Phrase("Name:", custFont)) { Border = borderSize });
icardTable.AddCell(new PdfPCell(new Phrase(student.firstname + " " + student.lastname, custFont)) { Border = borderSize });
The print document size will be 8.5 cm in height and 5.4 cm in width.
So need to fit it that way, is there any solution to this because the above code is not fitting the table on page and in proper size?
Any other format will also do like word etc.
figured out the solution :
Document IcardDoc = new Document(new Retangele(200f, 315f),35f,35f,0f,0f);
and adjust the width of the table accordingly:
PdfPTable icardTable = new PdfPTable(2);
icardTable.WidthPercentage = 140f;
to fit table exactly on page, if decrease rectangle width then increase table WidthPercentage and vice versa.
You also need to care of left and right margins defined as 35f in Document class constructor
This worked for me.
var pgSize = new iTextSharp.text.Rectangle(1042, 651);
var doc = new iTextSharp.text.Document(pgSize, 0, 0, 0, 0);