Itextsharp problem stroke is applying to cell text - c#

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();

Related

Adding new page in itextsharp will overlap with header

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.

Rotate multiline text with Columntext ITextSharp

How do i rotate multiline text in itextsahrp?
I have tried:
float x = 200;
float y = 100;
PdfContentByte cb = stamper.GetOverContent(i);
ColumnText ct = new ColumnText(cb);
ct.SetSimpleColumn(new Phrase(new Chunk("Test \n new", FontFactory.GetFont(FontFactory.HELVETICA, 18, iTextSharp.text.Font.NORMAL))),
x, reader.GetCropBox(i).Height -( y+400),500+x, y, 10, Element.ALIGN_LEFT | Element.ALIGN_TOP);
ct.Go();
ColumnText.ShowTextAligned(
cb, Element.ALIGN_CENTER,
new Phrase(new Chunk("Test \n new", FontFactory.GetFont(FontFactory.HELVETICA, 18, iTextSharp.text.Font.NORMAL))), x, reader.GetCropBox(i).Height-y, 12);
ct.SetSimpleColumn shows multilie text but how do I rotate it?
ColumnText.ShowTextAligned does not show multiline.
I don't have a C# environment on my machines, so I've written an example in Java, named AddRotatedTemplate. I have taken an existing PDF file with the words "Hello World", I've created a template/XObject with some text, and I've added that template/XObject twice using the addTemplate() method (once using only x, y coordinates and once using parameters that rotate the text with PI / 4 grades). As a result, the text added to the template is added twice; see hello_template.pdf).
This is the code:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
// Get canvas for page 1
PdfContentByte cb = stamper.getOverContent(1);
// Create template (aka XOBject)
PdfTemplate xobject = cb.createTemplate(80, 120);
// Add content using ColumnText
ColumnText column = new ColumnText(xobject);
column.setSimpleColumn(new Rectangle(80, 120));
column.addElement(new Paragraph("Some long text that needs to be distributed over several lines."));
column.go();
// Add the template to the canvas
cb.addTemplate(xobject, 36, 600);
double angle = Math.PI / 4;
cb.addTemplate(xobject,
(float)Math.cos(angle), -(float)Math.sin(angle),
(float)Math.cos(angle), (float)Math.sin(angle),
150, 600);
stamper.close();
reader.close();
}
There may be easier ways to define the rotation in other variations of the addTemplate() method, but I'm an engineer and I am so used to using the transformation matrix that I never feel the need or desire to use any other type of method.

How to handle the case in which an iText\iTextSharp table is split into two pages?

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.

Using iTextSharp, is there a way to keep text from staying in a rectangle

I have an existing PDF (not with form fields - more of a scanned document), and am using PdfReader to load the PDF "template" so that I write text on it.
For position simple fields I am using:
PdfReader reader = new PdfReader(templatePath);
Chunk chunk = new Chunk(text, fontToUse);
Phrase phrase = new Phrase();
phrase.Add(chunk);
PdfContentByte canvas = this.PdfWriter.DirectContent;
ColumnText.ShowTextAligned(this.PdfContentByte, alignment, phrase, left, top, 0);
I also need to write some text to a specific area which is a 400 x 200 rectangle. Since the size of the text varies, it may or may not fit into the rectangle.
Is there a way to write text to the rectangle, and if the text is too large for it to simply not appear (like overflow hidden would work in HTML)?
Got it!
Phrase myText = new Phrase(text);
PdfPTable table = new PdfPTable(1);
table.TotalWidth = 300;
table.LockedWidth = true;
PdfPCell cell = new PdfPCell(myText);
cell.Border = 0;
cell.FixedHeight = 40;
table.AddCell(cell);
table.WriteSelectedRows
(
0,
-1,
300,
700,
writer.DirectContent
);

itextsharp pdf page border?

I am using itext sharp for creating reports in PDF format.
I want page borders. I tried some ways. I am not successful.
How can I get a page border for top, bottom, left, right using iText for .NET?
I added one image 1. I want borders like described in the image.
You can try this code for adding the image for the header manually.
//Step 1: Add the Image file
strImgPath is refer the directory Info..
Image imgLogo = Image.GetInstance(strImgPath.ToString()+"\\abcdur compe.Jpg");
imgLogo.Alignment = Image.ALIGN_CENTER;
imgLogo.ScalePercent(50f);
// Step 2:
Add this ImgLogo to the PdfPTable by use of this
PdfPCell pdfcellImage = new PdfPCell(imgLogo, true);
pdfcellImage.FixedHeight = 40f;
pdfcellImage.HorizontalAlignment = Element.ALIGN_CENTER;
pdfcellImage.VerticalAlignment = Element.ALIGN_CENTER;
pdfcellImage.Border = Rectangle.NO_BORDER;
pdfcellImage.Border = Rectangle.NO_BORDER;
pdftblImage.AddCell(pdfcellImage);
// Step 3:
Create Chunck to add Text for address or others
fntBoldComHd is a Base Font Library Object
Chunk chnCompany = new Chunk("Your CompanyName\nAddress", fntBoldComHd);
//Step 4:
Create Phrase For add the Chunks and PdfPTables
Phrase phHeader = new Phrase();
phHeader.Add(pdftblImage);
phHeader.Add(chnCompany);
// Step 5:
Assign the Phrase to PDF Header
HeaderFooter header = new HeaderFooter(phHeader, false);
header.Border = Rectangle.NO_BORDER;
header.Alignment = Element.ALIGN_CENTER;
docPDF.Header = header;
I am using one hacky way of workaround but it will create the border.Use this method.
private void CreateBorder(PdfContentByte cb, PdfWriter writer, Document doc)
{
iTextSharp.text.Rectangle r = doc.PageSize;
float left = r.Left + 30;
float right = r.Right - 30;
float top = r.Top - 30;
float bottom = r.Bottom + 30;
float width = right - left;
float height = top - bottom;
PdfPTable tab = new PdfPTable(1);
tab.TotalWidth = width;
tab.LockedWidth = true;
PdfPCell t = new PdfPCell(new Phrase(String.Empty));
t.BackgroundColor = new BaseColor(250, 235, 215);
t.FixedHeight = height;
t.BorderWidth = 3;
tab.AddCell(t);
Paragraph pa = new Paragraph();
pa.Add(tab);
float h = tab.TotalHeight;
PdfTemplate temp = cb.CreateTemplate(tab.TotalWidth, h);
tab.WriteSelectedRows(0, -1, 0.0F, h, temp);
iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(temp);
img.SetAbsolutePosition(30, 30);
cb.AddImage(img);
}
If u want one more section for header create table width two rows.I hope this helps.
Are you referring to the document margins? If yes, use the Document object's ctor to specify them:
public Document(Rectangle pageSize, float marginLeft, float marginRight, float marginTop, float marginBottom);

Categories