Show/Hide AcroFields in iTextSharp - c#

I have the following code:
PdfStamper pst = null;
try
{
PdfReader reader = new PdfReader(GetTemplateBytes());
pst = new PdfStamper(reader, Response.OutputStream);
var acroFields = pst.AcroFields;
pst.FormFlattening = true;
pst.FreeTextFlattening = true;
pst.SetFullCompression();
SetFieldsInternal(acroFields);
pst.Close();
}
protected override void SetFieldsInternal(iTextSharp.text.pdf.AcroFields acroFields)
{
acroFields.SetFieldProperty("txtForOffer", "setflags", PdfAnnotation.FLAGS_PRINT, null);
}
How do I show / hide the acrofields in the SetFieldsInternal function ?
The point is that the user may want to download 2 versions of the PDF, one with some text showing, one without text showing.
The template PDF is generated using OpenOffice. I just fill in the acrofields.

You can set an AcroField as readonly like this:
form.setFieldProperty("companyFld", "setfflags", PdfFormField.FF_READ_ONLY, null);
It is "setfflags" BTW not "setflags"
EDIT: MY BAD!!! You asked to make a field visible or not. You would use the "setflags" argument in this case and you can pass any of the PdfAnnotation FLAGS_ constants to adjust visibility.

Related

Fields on pdf form are invisible

I'm using PDFSharp on .net core 2.2 C#. I'm reading PDF form in my application, than I'm extract form fields and fill them with values. When I save document fields are invisible until I put focus on them (click on them).
Here is code:
PdfDocument document = PdfReader.Open(#"locationOnPC", PdfDocumentOpenMode.Modify);
// Get the root object of all interactive form fields
PdfAcroForm form = document.AcroForm;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
var enc1252 = Encoding.GetEncoding(1252);
PdfTextField field = (PdfTextField)(form.Fields["myField"]);
field.Value = new PdfString("12345");
field.ReadOnly = true;
document.Save(#"myLocation");
Here is picture before focus:
And here is picture after focus:
Anyone know what is problem?
This should be inserted after:
PdfAcroForm form = document.AcroForm;
if (form.Elements.ContainsKey("/NeedAppearances"))
form.Elements["/NeedAppearances"] = new PdfBoolean(true);
else
form.Elements.Add("/NeedAppearances", new PdfBoolean(true));

c# wpf export RichTextBox formatting to xml document

so in WPF i've created a RichTextBox and implemented the functionality to be able to format selected text (bold, undelined, font, etc...), but now i would like to export all of the formatting to a XML file, so when i would load it the loaded file would give me the same text with the same formatting.
I think that the best way to do this would be, if i could find each place where there is formatting in the RTB and then save it as a text range, but i dont know if RTB has a method for finding if a part of text is formatted.
Here is what i've got:
xaml:
<Button Name = "export" Click = "export_Click"/>
<RichTextBox x:Name="RTB"/>
and the c#:
private void export_Click(object sender, RoutedEventArgs e){
TextRange range = new TextRange();
//here is where i want to access the formatted areas
//something like: range = RTB.document.getBoldArea();
//and then i could export what i got in the text range to a xml file
}
thanks in advance to anyone willing to help!
You can actually access XAML content directly, which is itself obviously XML. You could either save this directly or manipulate/translate it into your own schema.
To get the XAML for a RichTextBox :
static string GetXaml(RichTextBox rt)
{
TextRange range = new TextRange(rt.Document.ContentStart, rt.Document.ContentEnd);
MemoryStream stream = new MemoryStream();
range.Save(stream, DataFormats.Xaml);
string xamlText = Encoding.UTF8.GetString(stream.ToArray());
return xamlText;
}
To set the XAML content for a RichTextBox :
static void SetXaml(RichTextBox rt, string xamlString)
{
StringReader stringReader = new StringReader(xamlString);
XmlReader xmlReader = XmlReader.Create(stringReader);
Section sec = XamlReader.Load(xmlReader) as Section;
FlowDocument doc = new FlowDocument();
while (sec.Blocks.Count > 0)
doc.Blocks.Add(sec.Blocks.FirstBlock);
rt.Document = doc;
}

underline portion of text using iTextSharp

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

Check if "Continued" or "New" page

I would like to know if there is a way to check if the "New Page" happened because of exceeded table or programmatically (by using doc.NewPage();)?
If the new page caused because of exceeded table or text, I need to hide the header table and show a text instead, else if the new page caused programmatically I need to display the header table normally.
I tried to find a flag or something like this in the "OnStartPage" event that show me if the page exceeded or not, but I found nothing.
I hope that some one can help me here.
Thanks!
I would look at the IPdfPTableEventSplit interface that you can implement and assign to a PdfPTable.TableEvent property. It has two methods, SplitTable and TableLayout. The first method is called whenever a table split happens, the second is called whenever the table actually gets written to the canvas. In the first method you could set a flag and disable the header rows if a split happened and in the second method you could write your content out.
The SplitTable method is fired before the new page is added so you need to keep track of a trinary state, "no split", "draw on next page" and "draw on this page". I've packaged these up as an enum:
[Flags]
public enum SplitState {
None = 0,
DrawOnNextPage = 1,
DrawOnThisPage = 2
}
The implemented interface would look like this:
public class SplitTableWatcher : IPdfPTableEventSplit {
/// <summary>
/// The current table split state
/// </summary>
private SplitState currentSplitState = SplitState.None;
public void SplitTable(PdfPTable table) {
//Disable header rows for automatic splitting (per OP's request)
table.HeaderRows = 0;
//We now need to split on the next page, so append the flag
this.currentSplitState |= SplitState.DrawOnNextPage;
}
public void TableLayout(PdfPTable table, float[][] widths, float[] heights, int headerRows, int rowStart, PdfContentByte[] canvases) {
//If a split happened and we're on the next page
if (this.currentSplitState.HasFlag(SplitState.DrawOnThisPage)) {
//Draw something, nothing too special here
var cb = canvases[PdfPTable.TEXTCANVAS];
cb.BeginText();
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, false), 18);
//Use the table's widths and heights to find a spot, this probably could use some tweaking
cb.SetTextMatrix(widths[0][0], heights[0]);
cb.ShowText("A Split Happened!");
cb.EndText();
//Unset the draw on this page flag, it will be reset below if needed
this.currentSplitState ^= SplitState.DrawOnThisPage;
}
//If we previously had the next page flag set change it to this page
if (currentSplitState.HasFlag(SplitState.DrawOnNextPage)) {
this.currentSplitState = SplitState.DrawOnThisPage;
}
}
}
And finally the actual implementation of that class with some simple test data:
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
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();
var t = new PdfPTable(1);
//Implement our class
t.TableEvent = new SplitTableWatcher();
//Add a single header row
t.HeaderRows = 1;
t.AddCell("Header");
//Create 100 test cells
for (var i = 1; i < 100; i++) {
t.AddCell(i.ToString());
}
doc.Add(t);
doc.Close();
}
}
}

pop-up a window from itextsharp annotation to display images and text

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

Categories