I want to add and pop-up window in C# project to display an image and text by clicking on itextsharp annotation.
iTextSharp.text.pdf.PdfAnnotation annot = iTextSharp.text.pdf.PdfAnnotation.CreateLink(stamper.Writer, c.rect, PdfAnnotation.HIGHLIGHT_INVERT, PdfAction.JavaScript("app.alert('action!')", stamper.Writer));
above code is used to display the alert and i want to customize it to my needs can someone please give me an option.i'm not familiar with javascript. or can i use any other options ?
You need a couple of annotations to achieve what you want.
Let me start with a simple text annotation:
Suppose that:
writer is your PdfWriter instance,
rect1 and rect2 are rectangles that define coordinates,
title and contents are string objects with the content you want to show in the text annotation,
Then you need this code snippet to add the popup annotations:
// Create the text annotation
PdfAnnotation text = PdfAnnotation.CreateText(writer, rect1, title, contents, false, "Comment");
text.Name = "text";
text.Flags = PdfAnnotation.FLAGS_READONLY | PdfAnnotation.FLAGS_NOVIEW;
// Create the popup annotation
PdfAnnotation popup = PdfAnnotation.CreatePopup(writer, rect2, null, false);
// Add the text annotation to the popup
popup.Put(PdfName.PARENT, text.IndirectReference);
// Declare the popup annotation as popup for the text
text.Put(PdfName.POPUP, popup.IndirectReference);
// Add both annotations
writer.AddAnnotation(text);
writer.AddAnnotation(popup);
// Create a button field
PushbuttonField field = new PushbuttonField(wWriter, rect1, "button");
PdfAnnotation widget = field.Field;
// Show the popup onMouseEnter
PdfAction enter = PdfAction.JavaScript(JS1, writer);
widget.SetAdditionalActions(PdfName.E, enter);
// Hide the popup onMouseExit
PdfAction exit = PdfAction.JavaScript(JS2, writer);
widget.SetAdditionalActions(PdfName.X, exit);
// Add the button annotation
writer.AddAnnotation(widget);
Two constants aren't explained yet:
JS1:
"var t = this.getAnnot(this.pageNum, 'text'); t.popupOpen = true; var w = this.getField('button'); w.setFocus();"
JS2:
"var t = this.getAnnot(this.pageNum, 'text'); t.popupOpen = false;"
This is, of course, explained in my book, more specifically in chapter 7. You can find a full example here. If you need a C# example, please look for the corresponding example here.
If you also want an image, please take a look at this example: advertisement.pdf
Here you have an advertisement that closes when you click "close this advertisement". This is also done using JavaScript. You need to combine the previous snippet with the code of the Advertisement example.
The key JavaScript methods you'll need are: getField() and getAnnot(). You'll have to change the properties to show or hide the content.
I solved this problem by using an attachment instead of a popup. Below code will place an image in your pdf, and on click of image, it will open image with full resolution.
PdfReader reader = new PdfReader(ClassLoader.getSystemClassLoader().getResourceAsStream("source.pdf"));
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("target.pdf"));
PdfAnnotation imgAttach = PdfAnnotation.createFileAttachment(stamper.getWriter(), new Rectangle(100, 100, 200, 200), "", null, "PATH/TO/image.jpeg", "image.jpeg");
PdfAppearance app = stamper.getOverContent(1).createAppearance(100, 100);
Image img = Image.getInstance("PATH/TO/image.jpeg");
img.scaleAbsolute(100, 100);
img.setAbsolutePosition(100, 100);
app.addImage(img);
imgAttach.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, app);
stamper.addAnnotation(imgAttach, 1);
stamper.getOverContent(1).addImage(img);
stamper.close();
Related
I'm creating a simple PDF file with some text and an hyperlink attached to the that text:
Document pdfDocument = new Document();
Page pdfPage = pdfDocument.Pages.Add();
TextFragment textFragment = new TextFragment("My Text");
Table table = new Table();
Row row = table.Rows.Add();
Cell cell = row.Cells.Add();
cell.Paragraphs.Add(textFragment);
pdfPage.Paragraphs.Add(table);
LinkAnnotation link = new LinkAnnotation(pdfPage, textFragment.Rectangle); //[Before Save]textFragment.Rectangle: 0,0,35.56,10
link.Action = new GoToURIAction("Link1 before save");
pdfPage.Annotations.Add(link);
pdfDocument.Save(dataDir + "SimplePDFWithLink.pdf");
The problem is that the link annotation is being assign to the before save rectangle [0,0,33.56,10] at the bottom of the screen where's the textFragment is being added to a different rectangle (I can't set here the Position property because I don't know it, it is relative to the cell's table).
In order to solve this I've tried saving the page and only then searching the textFragment using TextFragmentAbsorber
pdfDocument.Save(dataDir + "SimplePDFWithLink.pdf");
//[After Save]textFragment.Rectangle: 0,0,90,770
TextFragmentAbsorber textFragmentAbsorber = new TextFragmentAbsorber();
pdfPage.Accept(textFragmentAbsorber);
foreach (TextFragment absorbedTextFragment in textFragmentAbsorber.TextFragments)
{
link = new LinkAnnotation(pdfPage, absorbedTextFragment.Rectangle);
link.Action = new GoToURIAction("Link 2 after save");
pdfPage.Annotations.Add(link);
}
pdfDocument.Save(dataDir + "SimplePDFWithLink.pdf");
My Question:
Is is possible to add a simple link to a TextFragment (which is BaseParagraph not StructureElement) without saving the document first?
Here is a simple demo of the outcome, you can see that before saving the document the link is added to the left bottom of the document instead of the text rectangle:
Update:
If I specify the TextFragment's Position value with some arbitrary values, the link is then added exactly to the text, but I don't know what will be the Position value of the element because it being built dynamically using a Table.
Working with TextFragment and TextSegment does work and adds the link without pre-saving the file:
TextFragment textFragment = new TextFragment("My Text");
TextSegment textSegment = new TextSegment("Link to File");
textSegment.Hyperlink = new Aspose.Pdf.WebHyperlink("www.google.com");
textFragment.Segments.Add(textSegment);
It is worth to mention it is works well when linking to a file on the user's file-system like:
textSegment.Hyperlink = new Aspose.Pdf.WebHyperlink("Files\foo.png");
I'm trying to generate a PDF report using SelectPDF. The report is multi-page long, and as such I need pagebreaks. Whenever these pagebreaks show up, I need top and bottom margins so the report won't look ugly, but I can only find the option to add margins for every page or no pages, but not "every page except the first one".
The source of the report is HTML/CSS that I have set up. The contents are dynamic, so I cannot manually control the text... The greatest granularity I have is controlling the CSS.
HtmlToPdf converter = new HtmlToPdf();
converter.Options.PdfPageSize = PdfPageSize.A4;
converter.Options.PageBreaksEnhancedAlgorithm = true;
converter.Options.MarginTop = 20;
converter.Options.MarginBottom = 20;
The "MarginTop" option adds the top margin to every single page. It works excellently for every page except for the first one, where I need it to be 0, but I can't find any options to do that. Does it exist?
It's not possible to do that using margins. You can however workaround this using headers/footers:
HtmlToPdf converter = new HtmlToPdf();
converter.Options.PdfPageSize = PdfPageSize.A4;
converter.Options.PageBreaksEnhancedAlgorithm = true;
converter.Options.DisplayHeader = true;
converter.Header.Height = 20;
converter.Header.DisplayOnFirstPage = false;
converter.Options.DisplayFooter = true;
converter.Footer.Height = 20;
I have an application that uses itextsharp to fill PDF form fields.
One of these fields has some text with tags. For example:
<U>This text should be underlined</>.
I'd like that the text closed in .. has to be underlined.
How could I do that?
How could I approch it with HTMLWorker for example?
Here's the portion of code where I write my description:
for (int i = 0; i < linesDescription.Count; i++)
{
int count = linesDescription[i].Count();
int countTrim = linesDescription[i].Trim().Count();
Chunk cnk = new Chunk(linesDescription[i] + GeneralPurpose.ReturnChar, TextStyle);
if (firstOpe && i > MaxLinePerPage - 1)
LongDescWrapped_dt_extra.Add(cnk);
else
LongDescWrapped_dt.Add(cnk);
}
Ordinary text fields do not support rich text. If you want the fields to remain interactive, you will need RichText fields. These are fields that are flagged in a way that they accept an RV value. This is explained here: Set different parts of a form field to have different fonts using iTextSharp (Note that I didn't succeed in getting this to work, but you may have better luck.)
If it is OK for you to flatten the form (i.e. remove all interactivity), please take a look at the FillWithUnderline example:
public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
stamper.setFormFlattening(true);
AcroFields form = stamper.getAcroFields();
FieldPosition pos = form.getFieldPositions("Name").get(0);
ColumnText ct = new ColumnText(stamper.getOverContent(pos.page));
ct.setSimpleColumn(pos.position);
ElementList elements = XMLWorkerHelper.parseToElementList("<div>Bruno <u>Lowagie</u></div>", null);
for (Element element : elements) {
ct.addElement(element);
}
ct.go();
stamper.close();
}
In this example, we don't fill out the field, but we get the fields position (a page number and a rectangle). We then use ColumnText to add content at this position. As we are inputting HTML, we use XML Worker to parse the HTML into iText objects that we can add to the ColumnText object.
This is a Java example, but it should be easy to port this to C# if you know how to code in C# (which I don't).
You can trythis
Chunk chunk = new Chunk("Underlined TExt", FontFactory.GetFont(FontFactory.TIMES_ROMAN, 12.0f, iTextSharp.text.Font.BOLD | iTextSharp.text.Font.UNDERLINE));
Paragraph reportHeadline = new Paragraph(chunk);
reportHeadline.SpacingBefore = 12.0f;
pdfDoc.Add(reportHeadline);
Is there way creating automatically calculating fields with iTextsharp? I have tried doing this with javascript but the problem is that field values only get updated during certain events (ex. mouseover, mouseup). If I use events the field values only update when I move mouse cursor. They don't get updated if I write a value to field, then move mouse cursor somewhere else and then press enter. They get updated when I move cursor back to the field. Afaik there is no event like "field value changed" or something similiar?
There is no "on changed" event like there is in HTML, however there are "on focus" and "on blur" events so you can pretty easily write your own. The code below shows this off. It first creates a global JavaScript variable (which is not needed, you can discard that line, it just helps me think). Then it creates a standard text field and sets two actions, the Fo (focus) event and the Bl (blur) event. You can find these events and others in the PDF standard section 12.6.3 table 194.
In the focus event I'm just storing the current text field's value. In the blur event I'm comparing the store value with the new value and then just alerting if they are the same or different. If you have a bunch of fields you'll probably want to use a global array instead of individual variables, too. See the code comments for more information. This was tested against iTextSharp 5.4.2.0.
//Our test file
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Test.pdf");
//Standard PDF creation, nothing special
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Add a global variable. This line is 100% not needed but it helps me think more clearly
writer.AddJavaScript(PdfAction.JavaScript("var first_name = '';", writer));
//Create a text field
var tf = new TextField(writer, new iTextSharp.text.Rectangle(50, 50, 300, 100), "first_name");
//Give it some style and default text
tf.BorderStyle = PdfBorderDictionary.STYLE_INSET;
tf.BorderColor = BaseColor.BLACK;
tf.Text = "First Name";
//Get the underlying form field object
var tfa = tf.GetTextField();
//On focus (Fo) store the value in our global variable
tfa.SetAdditionalActions(PdfName.FO, PdfAction.JavaScript("first_name = this.getField('first_name').value;", writer));
//On blur (Bl) compare the old value with the entered value and do something if they are the same/different
tfa.SetAdditionalActions(PdfName.BL, PdfAction.JavaScript("var old_value = first_name; var new_value = this.getField('first_name').value; if(old_value != new_value){app.alert('Different');}else{app.alert('Same');}", writer));
//Add our form field to the document
writer.AddAnnotation(tfa);
doc.Close();
}
}
}
I have taken the link values from PDF file like http://google.com
but I need to take the anchor text value, for example click here.
How to to take the anchor link value text?
I have taken the URL value of the PDF file by using the below URL: Reading hyperlinks from pdf file
for example.
Anchor a = new Anchor("Test Anchor");
a.Reference = "http://www.google.com";
myParagraph.Add(a);
Here I get the http://www.google.com but I need to get anchor value i.e. Test Anchor
Need your suggestions.
From the PDF file you need to identify the region where the link is placed and then read the text below the link using iTextSharp.
This way you can extract the text underneath the link. The limitation of this approach is that if the link region is wider than the text, the extraction will read the full text under that region.
private void GetAllHyperlinksFromPDFDocument(string pdfFilePath)
{
string linkTextBuilder = "";
string linkReferenceBuilder = "";
PdfDictionary PageDictionary = default(PdfDictionary);
PdfArray Annots = default(PdfArray);
PdfReader R = new PdfReader(pdfFilePath);
List<BinaryHyperlink> ret = new List<BinaryHyperlink>();
//Loop through each page
for (int i = 1; i <= R.NumberOfPages; i++)
{
//Get the current page
PageDictionary = R.GetPageN(i);
//Get all of the annotations for the current page
Annots = PageDictionary.GetAsArray(PdfName.ANNOTS);
//Make sure we have something
if ((Annots == null) || (Annots.Length == 0))
continue;
//Loop through each annotation
foreach (PdfObject A in Annots.ArrayList)
{
//Convert the itext-specific object as a generic PDF object
PdfDictionary AnnotationDictionary = (PdfDictionary)PdfReader.GetPdfObject(A);
//Make sure this annotation has a link
if (!AnnotationDictionary.Get(PdfName.SUBTYPE).Equals(PdfName.LINK))
continue;
//Make sure this annotation has an ACTION
if (AnnotationDictionary.Get(PdfName.A) == null)
continue;
//Get the ACTION for the current annotation
PdfDictionary AnnotationAction = (PdfDictionary)AnnotationDictionary.GetAsDict(PdfName.A);
if (AnnotationAction.Get(PdfName.S).Equals(PdfName.URI))
{
//Get action link URL : linkReferenceBuilder
PdfString Link = AnnotationAction.GetAsString(PdfName.URI);
if (Link != null)
linkReferenceBuilder = Link.ToString();
//Get action link text : linkTextBuilder
var LinkLocation = AnnotationDictionary.GetAsArray(PdfName.RECT);
List<string> linestringlist = new List<string>();
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(((PdfNumber)LinkLocation[0]).FloatValue, ((PdfNumber)LinkLocation[1]).FloatValue, ((PdfNumber)LinkLocation[2]).FloatValue, ((PdfNumber)LinkLocation[3]).FloatValue);
RenderFilter[] renderFilter = new RenderFilter[1];
renderFilter[0] = new RegionTextRenderFilter(rect);
ITextExtractionStrategy textExtractionStrategy = new FilteredTextRenderListener(new LocationTextExtractionStrategy(), renderFilter);
linkTextBuilder = PdfTextExtractor.GetTextFromPage(R, i, textExtractionStrategy).Trim();
}
}
}
}
Unfortunately I don't think you're going to be able to do this, at least not without a lot of guess-work. In HTML this would be easy because a hyperlink and its text are stored together as:
Click here
However, in a PDF these two entities are not stored with any form of relationship. What we think of as a "hyperlink" within a PDF is technically a PDF Annotation that just happens to be sitting on top of text. You can see this by opening a PDF in an editing program such as Adobe Acrobat Pro. You can change the text but the "clickable" area doesn't change. You can also move and resize the "clickable" area and put it anywhere in the document.
When creating PDFs, iText/iTextSharp abstract this away so you don't have to think about this. You can create a "hyperlink" with clickable text but when it generates a PDF it ultimately will create the text as normal text, calculate the rectangle coordinates and then put an annotation at that rectangle.
I did say that you could try to guess at this, and it might or might not work for you. To do this you'd need to get the rectangle for annotation and then find the text that's also at those coordinates. It won't be an exact match, however, because of padding issues. If you absolutely have to get the text under a hyperlink then this is the only way that I know of for doing this. Good luck!