itextsharp : Adding multiple pages - c#

I'm using the DirectContent method of absolutely positioning elements on my PDF.
I need to iterate over a list of records and build one page per record in my PDF.
How do I tell itextsharp to insert a new page and "draw" to that page?
// 72point per inch
// we want 7x10
iTextSharp.text.Rectangle pageSize = new iTextSharp.text.Rectangle(504, 720);
Document doc = new Document(pageSize);
PdfWriter writer = PdfWriter.GetInstance(doc, new FileStream(#"C:\temp\backPages.pdf", FileMode.Create));
doc.Open();
PdfContentByte cb = writer.DirectContent;
// "DRAW" IMAGES AND TEXT
...
//various .Add's called here
...
// Done with drawing images & text
doc.Close();

Easily enough its the Document.NewPage() function.
I saw some really odd "solutions" on other sites, hope this helps someone else.

Related

How to place paragraphs in specific place using iTextSharp

How do I place text at a specific location on the pdf? I did a little bit of searching but didn't find anything too good. I have document.Add(new Paragraph("Date:" + DateTime.Now)); and I wanted to place that on a specific area on the pdf file.
My code:
private void savePDF_Click(object sender, EventArgs e)
{
FileStream fileStream = new FileStream(nameTxtB.Text + "Repair.pdf", FileMode.Create, FileAccess.Write, FileShare.None);
Document document = new Document();
document.Open();
iTextSharp.text.Rectangle rectangle = new iTextSharp.text.Rectangle(PageSize.LETTER);
PdfWriter pdfWriter = PdfWriter.GetInstance(document, fileStream);
iTextSharp.text.Image r3tsLogo = iTextSharp.text.Image.GetInstance("rt3slogo.PNG"); //creates r3ts logo
iTextSharp.text.Image r3Info = iTextSharp.text.Image.GetInstance("R3 Information.PNG"); //creates r3 information text below r3ts logo
r3tsLogo.SetAbsolutePosition(document.PageSize.Width - 375 - 0f, document.PageSize.Height - 130 - 0f);
r3Info.SetAbsolutePosition(document.PageSize.Width - 365 - 0f, document.PageSize.Height - 170 - 0f); //higher the number in height the lower the place of text on paper
//less number will result in text more to right in width
//increase size of picture
r3tsLogo.ScalePercent(120);
r3Info.ScalePercent(65);
//---------------adds all images to pdf file ---------------------------------
document.Add(r3tsLogo);
document.Add(r3Info);
document.Add(new Paragraph("Date:" + DateTime.Now));
document.Close();
}
Assuming that you know how to add images at an absolute position (see Joris' answer), but looking at how to add text, then the answer to your question is: use ColumnText.
If you only need to add a single line that doesn't need to be wrapped, you can use the ShowTextAligned() method:
ColumnText.showTextAligned(writer.DirectContent,
Element.ALIGN_CENTER, new Phrase("single line"), x, y, rotation);
In this line of code, x and y are the coordinates for the middle of the text (other possible alignment values are ALIGN_LEFT and ALIGN_RIGHT). The rotation parameter defines a rotation in degrees. Note that the text "single line" won't be wrapped. You can add text that "falls off the page" this way if the text you're adding is too long.
If you want to add text inside a specific rectangle, then you need to define the column using a Rectangle object:
ColumnText ct = new ColumnText(writer.DirectContent);
ct.setSimpleColumn(new Rectangle(0, 0, 523, 50));
ct.addElement(new Paragraph("This could be a very long sentence that needs to be wrapped"));
ct.go();
If you provide more text than fits the rectangle, that text will not be rendered. However, it will still be available in the ct object so that you can add that remaining text at another position.
All of this has been asked and answered before:
Single line:
http://stackoverflow.com/questions/16370428/how-to-write-in-a-specific-location-the-zapfdingbatslist-in-a-pdf-document-using
http://stackoverflow.com/questions/17998306/rotating-text-using-center-in-itext
Multiple lines:
http://stackoverflow.com/questions/33609447
http://stackoverflow.com/questions/31152874/how-to-add-text-in-pdfcontentbyte-rectangle-using-itextsharp
http://stackoverflow.com/questions/15414923/rotate-paragraphs-or-cells-some-arbitrary-number-of-degrees-itext
Did I have to search long for these examples? No, I found them on the official web site under Absolute Positioning of text.
Wisdom is there for those who search...
This concept is thoroughly explained in the book 'iText in action'. Which can be found on the website.
http://developers.itextpdf.com/examples/itext-action-second-edition/chapter-3
Short code sample (check the site for other examples):
// step 1
Document document = new Document(PageSize.POSTCARD, 30, 30, 30, 30);
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
// step 3
document.open();
// step 4
// Create and add a Paragraph
Paragraph p = new Paragraph("Foobar Film Festival", new Font(FontFamily.HELVETICA, 22));
p.setAlignment(Element.ALIGN_CENTER);
document.add(p);
// Create and add an Image
Image img = Image.getInstance(RESOURCE);
img.setAbsolutePosition(
(PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,
(PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);
document.add(img);

How to save a stackpanel as an XPS document in multiple pages in WPF?

I need to save a large stackpanel to an XPS document. Since the stackpanel is lengthy, it cannot be accommodated in a single page while printing. Is there a way to save the stackpanel in XPS expanding multiple pages?
Below is my code that saves a single page:
Transform transform = stkpnlMain.LayoutTransform;
stkpnlMain.LayoutTransform = null;
Size size = new Size(stkpnlMain.ActualWidth, stkpnlMain.ActualHeight);
stkpnlMain.Measure(size);
stkpnlMain.Arrange(new Rect(size));
Package package = Package.Open(destination.LocalPath, FileMode.Create);
XpsDocument doc = new XpsDocument(package);
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
writer.Write(stkpnlMain);
doc.Close();
package.Close();
Here, stkpnlMain is a very lengthy block.

Why doesn't an Image show up when I add it to a Document using iTextSharp?

Contextt: I am opening an existing, interactive PDF form containing AcroForm fields. I tried to add an image to a rectangle field in the PDF form like this:
string path = HttpContext.Current.Server.MapPath("includes");
string newFile = HttpContext.Current.Server.MapPath("Tmp") + "/completed_gray" +".pdf";
string imagepath = HttpContext.Current.Server.MapPath("Tmp");
Document doc = new Document();
try {
PdfWriter.GetInstance(doc, new FileStream(newFile, FileMode.Open));
doc.Open();
iTextSharp.text.Image gif = iTextSharp.text.Image.GetInstance(imagepath + "/CUstomRep_Eng_Col_1_V1.png");
iTextSharp.text.Rectangle rect = pdfStamper.AcroFields.GetFieldPositions("img_1_space")[0].position;
gif.ScaleAbsolute(rect.Width, rect.Height);
gif.SetAbsolutePosition(rect.Left, rect.Bottom);
doc.Add(gif);
}
catch (Exception ex) {
//Log error;
}
finally {
doc.Close();
}
The image doesn't show up in the resulting PDF.
You're creating a document using the "5 steps to create a PDF document" as documented in my books.
create a Document object.
create a PdfWriter instance.
open the document.
add content to the document.
close the document.
This contradicts with what you actually want to do: I want to add an Image in a placeholder defined by an AcroForm field.
Why are you saying you want one thing, and doing something else? Beats me. Probably because you didn't want to read the documentation.
You need something like this:
Create a PdfReader instance.
Create a PdfStamper instance.
Ask the stamper for information about the fields.
Add content to a page using the stamper instance.
Close the stamper.
In answer to your question: why doesn't my image show up in my document?
Support the coordinates of the field in the existing document are lower-left corner x = 600, y = 600 and upper-right corner x = 700, y = 700, then you are adding the image outside the visible area of the page you're creating. When you use new Document();, you're creating a document where the lower-left corner is x = 0, y = 0 and the upper-right corner is x = 595, y = 842.
In that case, you're adding the image to the document, but it's not visible because you've added it outside the rectangle that defines the page.

ITextSharp Defining a Pages Background Image: Whats the correct way?

Is it possible to set a background image for a pdf page in ITextSharp?
Whats the correct way to define a background image for a pdf page? Is there a property of the document I set?
Or is it just like creating another image(my image has the dimensions of a A4 page)? If I add the background image as a normal image will I be able to place paragraphs over the top of the background image?
var document = new Document(PageSize.A4, 50, 50, 25, 25);
// Create a new PdfWrite object, writing the output to a MemoryStream
var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, output);
var logo = iTextSharp.text.Image.GetInstance(Server.MapPath("~/Images/test.jpg"));
logo.SetAbsolutePosition(0,0);
document.Add(logo);
// Will the following paragraph be ON TOP or below the background image?
// I am aiming for on top
document.Add( new Paragraph("sjfkkjdsfk") );
document.Close();
The logo is fine - it's just a regular image content on the page, not backgound img (like in HTML). To put content on top of that, you need to use Direct Content:
PdfContentByte over = writer.DirectContent;
over.SaveState();
over.BeginText();
over.SetFontAndSize(BaseFont.CreateFont(), 9);
over.ShowTextAligned(Element.ALIGN_LEFT, "Your Text", x, y, 0);
over.SetLineWidth(0.3f);
over.EndText();
over.RestoreState();
Please note the x and y cord are from the bottom left corner. The last parameter is for rotation.
Another tip: do a doc.NewPage(); if you want to start a new page with the image background, so the the text cord is on the new page.

Creating PDF with overflow layout via iTextSharp

I'm successfully creating a PDF document from a DataTable via iTextSharp, but I can't get the layout in a desireable format.
Though unlikely, the DataTable has the potential for dozens of columns. Imagine the following DataTable - each number represents the area that can fit on a page:
|------------|
| 1 : 2 : 3 |
|------------|
| 4 : 5 : 6 |
|------------|
This should export as a 6 page PDF document in the order I've numbered the sections. Instead, it's currently generating as a two page document with 40-some columns squished on each page with a font so small it literally has no detail.
The simplest way to explain what I want is: When a generated PDF prints, I want it to print like a very wide Excel sheet rather than squishing all the content together.
My code is as follows:
public static void ExportAsPDF(DataTable Table, IList<string> Columns, string filename)
{
int ColumnCount = Table.Columns.Count;
int RowCount = Table.Rows.Count;
iTextSharp.text.Table BodyTable = new iTextSharp.text.Table(ColumnCount, RowCount);
BodyTable.AutoFillEmptyCells = true;
foreach (string s in Columns)
{
BodyTable.AddCell(s);
}
foreach (object o in from DataRow row in Table.Rows from o in row.ItemArray select o)
{
BodyTable.AddCell(o.ToString());
}
Document doc = new Document();
PdfWriter.GetInstance(doc, HttpContext.Current.Response.OutputStream);
doc.Open();
doc.Add(BodyTable);
doc.Close();
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.pdf", filename));
HttpContext.Current.Response.End();
}
All input and help is much appreciated. Thanks
Okay, two options.
Draw everything yourself by hand with PdfContentByte and ColumnText for the text layout part.
Convince the normal iText Layout code that your page is wide enough to hold an entire row, then split those pages into pieces later. Not Pretty, but probably easier than the alternative.
First you need to define a page that is 3 times wider than normal.
Rectangle triplePageRect = new Rectangle(PageSize.LETTER);
float origWidth = triplePageRect.getWidth();
triplePageRect.setWidth(origWidth * 3f);
Document doc = new Document(triplePageRect);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(doc, baos);
Then you draw your table pretty much the way you are now... BUT you must be sure that a column edge lines up with your two page edges so you can easily break up the pages later. Bonus points if you can create an empty row centered on where the page break will be so you have a margin.
//Your Code Here
Finally, you need to save your PDF, open it again, and chop it to ribbons. I'm thinking PdfStamper.
// write everything out to the baos.
doc.close();
// and suck it right back up again. Hurray for efficiency. Or something.
PdfReader reader = new PdfReader(baos.toByteArrayOrWhateverItsCalled());
PdfStamper stamper = new PdfStamper( reader, new FileOutputStream(outputPath));
// duplicate the pages. I'll assume only one page, but you'll get the idea.
PdfDictionary origPage = reader.getPageN(1);
for (int i = 0; i < 2; ++i) {
// initial size is irrelevant, we're going to change it, but !null
stamper.insertPage(2+i, PageSize.LETTER);
PdfDictionary newPageDict = reader.getPage(2 + i);
// copy the original page... note that this is a shallow copy
newPageDict.putAll(origPageDict);
// duplicate the page rect so each page will have its own copy
PdfArray pageRect = newPageDict.getAsArray(PdfName.MEDIABOX);
// also a shallow copy, but changes to this array will be localized to the page.
PdfArray newRect = new PdfArray(pageRect);
// page rects are defined as [llx lly urx ury], so we need to change 0 and 2.
newRect.set(0, new PdfNumber(origWidth * (i+1));
newRect.set(2, new PdfNumber(origWidth * (i+2));
}
//Smoke'em if you've got 'em folks, we're done.
stamper.close();
Damn I'm good. Oooh ooh! And modest! Let's not forget good looking, brave, courteous, witty...

Categories