c# - itext7 - How to add text to new page? - c#

I'm creating Pdfs using itext7. It allows me to add paragraphs to first page but I'm not sure how can I add content to second page. If I create Canvas after calling AddNewPage() then it works fine, but it doesn't work when I use a paragraph and I add it to the document. Thanks for help. In my example, firstPageText and secondPageText will be displayed on first page:
protected void CreatePdf(string filePath, string firstPageText, string secondPageText)
{
PdfWriter writer = new PdfWriter(filePath);
PdfDocument pdfDocument = new PdfDocument(writer);
Document doc = new Document(pdfDocument);
doc.Add(new Paragraph(firstPageText));
pdfDocument.AddNewPage();
doc.Add(new Paragraph(secondPageText));
doc.Close();
}

This is explained in chapter 2 of the iText 7: Building Blocks. Allow me to copy a snippet of that tutorial:
If we had used an AreaBreak of type NEXT_PAGE, a new page would have been started; see figure 2.11.
In the
JekyllHydeV5
example, we changed a single line:
AreaBreak nextPage = new AreaBreak(AreaBreakType.NEXT_PAGE);
Instead of skipping to the next column, iText now skips to the next
page.
By default, the newly created page will have the same page size as
the current page. If you want iText to create a page of another
size, you can use the constructor that accepts a PageSize object as
a parameter. For instance: new AreaBreak(PageSize.A3).
There's also an AreaBreak of type LAST_PAGE. This AreaBreakType
is to be used when switching between different renderers.
It surprises me that you'd do this:
doc.Add(new Paragraph(firstPageText));
pdfDocument.AddNewPage();
doc.Add(new Paragraph(secondPageText));
While the documented way is to do it like this:
doc.Add(new Paragraph(firstPageText));
doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
doc.Add(new Paragraph(secondPageText));

Related

Copying the whole content of the PDF File to the temporary file?

Basically, I did ask already a question regarding on how to edit PDF File. But it seems that I need to pay a lot of money to achieve what I want. But here is the problem first,
I have a PDF Template containing a plain text like this {{Fullname}} like a placeholder and should be replaced with a certain value. Now, as I've said earlier, Editing the PDF File is a mess and tough because if it's not, I already saw a solution online for free.
Now, here is my Idea, What if I get the whole content of this template file and replace the placeholder with a certain value then create a new PDF File with the same content but the placeholder is already replaced?
I am trying to figure out this problem and here is my solution:
string destinationFile = Path.GetTempFileName();
string text = File.ReadAllText(sourceFile);
text = text.Replace("{{Fullname}}", "John Doe");
// Create a new PDF document
Document document = new Document();
PdfWriter.GetInstance(document, new FileStream(destinationFile, FileMode.Create));
document.Open();
// Add the text to the document
document.Add(new Paragraph(text));
// Close the document
document.Close();
Currently, I am using iTextSharp and does not meet what I expected. So, my question is, Is it possible to get all the content of the PDF File and modify it to create a new one? If yes, How?

Set line spacing when using XMLWorker to parse HTML to PDF - ITextSharp C#

I am using XMLWorker to parse an HTML string into a PDF Document, and cannot find a way to control the line spacing of the PDF being generated.
Document document = new Document(PageSize.LETTER, 72f, 72f, 108f, 90f);
MemoryStream stream1 = new MemoryStream();
PdfWriter pdfWriter = PdfWriter.GetInstance(document, stream1);
document.Open();
//parse HTML into document
XMLWorkerHelper.GetInstance().ParseXHtml(pdfWriter, document, new StringReader(summary.Content));
The "summary.Content" is an HTML string that comes from a database field.
Now, I recently upgraded our ITextSharp library to 5.5.5.0, and upgraded to the new XMLWorker library. Using the code above, the line spacing ("leading" in PDF-speak) is much smaller than the PDF's being generated previously. I am required to make sure the line spacing looks the same as it used to.
I read that I can set the leading on the Paragraphs I build, but that doesn't help me when simply calling ParseXHtml(). I read that ITextSharp defaults to a leading size of 1.5 times the font size.
I read here itextsupport documentation that I can use this line to use the default.css that ships with XML Worker.
CSSResolver cssResolver = XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
I thought the default CSS might generate the PDF with the same leading as my old PDF's, but the following code resulted in the same output PDF's as when I just use ParseXHtml().
var sr = new StringReader(summary.Content);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
ICSSResolver cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true);
IPipeline pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(document, pdfWriter)));
XMLWorker worker = new XMLWorker(pipeline, true);
XMLParser xmlParse = new XMLParser(true, worker);
document.Open();
xmlParse.Parse(sr);
I need to control the line height (line-spacing, leading) in the PDF document I generate. Can anyone help point me in the right direction? I am trying to work through some options. Do either of these make sense?
Create a CSS file in a directory that defines line-height for different HTML tags, read that in with a stream, and pass that to parseXHtml(PdfWriter writer, Document doc, InputStream in, InputStream inCssFile).
Define a font for my document that specifies a line-height? I looked but didn't find a way to do this.
If you want to have a different line-height for different paragraphs, you have to define a different value for the line-height attribute in your CSS. I have made a very simple example with some very simple inline CSS:
As you can see, the line-height of the paragraph starting with Non eram nescius is 16pt. As I use the default font which is 12 pt Helvetica. The paragraph looks fine.
For the paragraph that starts with Contra quos omnis, I use a line-height of 25pt and you see that there are big gaps between the lines.
For the paragraph that starts with Sive enim ad, I use a line-height of 13pt which is only 1 pt more than the font height. The lines are very close together for this paragraph.
It doesn't matter where you define the line-height. Your options are to define it inline in the tag, in the <head> section of your HTML or in an external CSS file that is either referenced from the header of your HTML or loaded into XML Worker separately. Whatever you like most is OK.

Appending PDFs to generated PDF using iTextSharp

I am generating a pdf using iTextSharp. If certain properties are true then I also want to insert an existing pdf with static content.
private byte[] GeneratePdf(DraftOrder draftOrder)
// create a pdf document
var document = new Document();
// set the page size, set the orientation
document.SetPageSize(PageSize.A4);
// create a writer instance
var pdfWriter = PdfWriter.GetInstance(document, new FileStream(file, FileMode.Create));
document.Open();
if(draftOrder.hasProperty){
//add these things to the pdf
var textToBeAdded = "<table><tr>....</table>";
}
FormatHtml(document, textToBeAdded , css);
if(someOtherProperty){
//add static pdf from file
document.NewPage();
var reader = new PdfReader("myPath/existing.pdf");
PdfImportedPage page;
for(var i = 0; i < reader.NumberOfPages; i++){
//It's this bit I don't really understand
//**how can I add the page read to the document being created?**
}
I can load the pdf from the source but when I iterate over the pages I can't seem to be able to add them to the document I am creating.
Cheers
Please read http://manning.com/lowagie2/samplechapter6.pdf
If you don't mind losing all interactivity, you can get the template from the writer object with the GetImportedPage() method and add it to the document with AddTemplate ().
This question has been answered many times on StackOverflow and you'll notice that I always warn about some dangers: you need to realize that the dimensions of the imported page can be different from the page size you initially defined. Because of this invisible parts of the imported page can become visible; visible parts can become invisible.
I'd prefer adding the extra page in a second ho using PdfCopy, but maybe that's just me.

Fill PDF Form with Itextsharp

I am trying to fill up a form with ITextsharp, and trying out the following code to get all the fields in the pdf:
string pdfTemplate = #"c:\Temp\questionnaire.pdf";
PdfReader pdfReader = new PdfReader(pdfTemplate);
StringBuilder sb = new StringBuilder();
foreach (var de in pdfReader.AcroFields.Fields)
{
sb.Append(de.Key.ToString() + Environment.NewLine);
}
But the foreach loop is always null count. Do I need to do something to file itself as I have tried the example from here and it works fine... this is an example of pdf I am trying to fill
any ideas?
Edit ::
As it turned out, the PDF "form" to fill in actually wasn't a form (in PDF terms) at all. Thus, your have two choices:
You add the text to the page contents directly using hardcoded or configured "field" positions and dimensions as described by #tschmit007 in comments to his answer.
You add actual PDF form fields to your PDF to generate a true PDF form which you take as template to fill in later.
You can add actual form fields either using some graphical tool allowing that, e.g. Adobe Acrobat, or you can use iText(Sharp). Have a look at chapter 8 of iText in Action — 2nd Edition and the samples available here for Java and here for .Net.
Those samples mostly add form fields to newly generated PDF documents. You can virtually use the same code, though, for adding form fields to a PdfStamper which exposes its inner PdfWriter using stamper.getWriter() in Java and the stamper.Writer in C#. Instead of writer.addAnnotation(field) you have to use stamper.addAnnotation(field, page), though.
try:
using (FileStream outFile = new FileStream("result.pdf", FileMode.Create)) {
PdfReader pdfReader = new PdfReader("file.pdf");
PdfStamper pdfStamper = new PdfStamper(pdfReader, outFile);
AcroFields fields = pdfStamper.AcroFields;
//rest of the code here
//fields.SetField("n°1", "value");
//...
pdfStamper.Close();
pdfReader.Close();
}

Print PDF from ASP.Net without preview

I've generated a pdf using iTextSharp and I can preview it very well in ASP.Net but I need to send it directly to printer without a preview. I want the user to click the print button and automatically the document prints.
I know that a page can be sent directly to printer using the javascript window.print() but I don't know how to make it for a PDF.
Edit: it is not embedded, I generate it like this;
...
FileStream stream = new FileStream(Request.PhysicalApplicationPath + "~1.pdf", FileMode.Create);
Document pdf = new Document(PageSize.LETTER);
PdfWriter writer = PdfWriter.GetInstance(pdf, stream);
pdf.Open();
pdf.Add(new Paragraph(member.ToString()));
pdf.Close();
Response.Redirect("~1.pdf");
...
And here I am.
Finally I made it, but I had to use an IFRAME, I defined an IFrame in the aspx and didn't set the src property, in the cs file I made generated the pdf file and set the src property of the iFrame as the generated pdf file name, like this;
Document pdf = new Document(PageSize.LETTER);
PdfWriter writer = PdfWriter.GetInstance(pdf,
new FileStream(Request.PhysicalApplicationPath + "~1.pdf", FileMode.Create));
pdf.Open();
//This action leads directly to printer dialogue
PdfAction jAction = PdfAction.JavaScript("this.print(true);\r", writer);
writer.AddJavaScript(jAction);
pdf.Add(new Paragraph("My first PDF on line"));
pdf.Close();
//Open the pdf in the frame
frame1.Attributes["src"] = "~1.pdf";
And that made the trick, however, I think that i should implement your solution Stefan, the problem is that I'm new to asp.net and javascript and if I don't have a complete source code I could not code your suggestion but at least is the first step, I was very surprised how much code in html and javascript i need to learn. Thnx.
Is the pdf embedded in the page with embedd-tag or just opened in a frame or how are you showing it?
If its embedded, just make sure that the object is selected and then do a print().
Get the ref to the embedded document.
var x = document.getElementById("mypdfembeddobject");
x.click();
x.setActive();
x.focus();
x.print();
It's a little more tricky if you're using pdfsharp but quite doable
PdfDocument document = new PdfDocument();
PdfPage page = document.AddPage();
XGraphics gfx = XGraphics.FromPdfPage(page);
XFont font = new XFont("Verdana", 20, XFontStyle.BoldItalic);
// Draw the text
gfx.DrawString("Hello, World!", font, XBrushes.Black,
new XRect(0, 0, page.Width, page.Height),
XStringFormats.Center);
// real stuff starts here
// current version of pdfsharp doesn't support actions
// http://www.pdfsharp.net/wiki/WorkOnPdfObjects-sample.ashx
// so we got to get close to the metal see chapter 12.6.4 of
// http://partners.adobe.com/public/developer/pdf/index_reference.html
PdfDictionary dict = new PdfDictionary(document); //
dict.Elements["/S"] = new PdfName("/JavaScript"); //
dict.Elements["/JS"] = new PdfString("this.print(true);\r");
document.Internals.AddObject(dict);
document.Internals.Catalog.Elements["/OpenAction"] =
PdfInternals.GetReference(dict);
document.Save(Server.MapPath("2.pdf"));
frame1.Attributes["src"] = "2.pdf";
ALso, try this gem:
<link ref="mypdf" media="print" href="mypdf.pdf">
I havent tested it, but what I have read about it, it can be used in this way to let the mypdf.pdf be printed instead of page content whatever method you are using to print the page.
Search for media="print" to check out more.
You can embed javascript in the pdf, so that the user gets a print dialog as soon as their browser loads the pdf.
I'm not sure about iTextSharp, but the javascript that I use is
var pp = this.getPrintParams();
pp.interactive = pp.constants.interactionLevel.automatic;
this.print(pp);
For iTextSharp, check out http://itextsharp.sourceforge.net/examples/Chap1106.cs

Categories

Resources