Override pdf fields in new document - c#

I have one pdf template, which I try to override in new document. I need to get some fields from template PDF and re-write their values in new PDF. I do this :
PdfReader templatereader = new PdfReader("Templates//PDF_Template_Empty.pdf");
PdfDocument template = new PdfDocument(templatereader);
var writer = new PdfWriter(OutputFilepath);
PdfDocument newreport = new PdfDocument(writer);
var fields = PdfAcroForm.GetAcroForm(template, true); //!!!
But then i catch the Exception :
iText.Kernel.PdfException: 'There is no associate PdfWriter for making
indirects.'
What i am doing wrong and how to fix it ? iTextsharp 7.

The error explains exactly what goes wrong: you didn't define a PdfWriter instance for the PdfDocument instance named template. You create a PdfWriter instance for newreport, but you never use newreport.
This is how it should be done:
PdfReader templatereader = new PdfReader("Templates//PDF_Template_Empty.pdf");
var writer = new PdfWriter(OutputFilepath);
PdfDocument template = new PdfDocument(templatereader, writer);
var fields = PdfAcroForm.GetAcroForm(template, true);
As you can see, there is no need for the newreport instance. The template instance takes the templatereader as input and will create a new PDF as output using the writer.

Related

itext7 PdfAConformanceException: Maximum array capacity is exceeded

I am converting a text file of approx. 16K lines into a PDF/A-1b file. I get the exception "PdfAConformanceException: Maximum array capacity is exceeded". The document is generated with no problems if it is a normal PDF rather than a PDF/A. It happens only generating a PDF/A. The normal PDF document is about 1150 pages long. Any hint on how to solve this? The exception is generated in the "Doc.Close()" call.
This is the code that I use:
StreamReader str = new StreamReader(file_name);
PdfWriter writer = new PdfWriter(file_name.Replace(".txt", ".pdf"));
PdfDocument pdf = new PdfADocument(writer, PdfAConformanceLevel.PDF_A_1B, new PdfOutputIntent
("Custom", "", "https://www.color.org", "sRGB IEC61966-2.1",
new FileStream(INTENT, FileMode.Open, FileAccess.Read)));
Document doc = new Document(pdf);
pdf.SetTagged();
//Fonts need to be embedded
PdfFont font = PdfFontFactory.CreateFont(FONT, PdfEncodings.WINANSI, true);
Paragraph p = new Paragraph();
p.SetFont(font);
p.Add(str.ReadToEnd());
doc.Add(p);
doc.Close();
Thanks!

C#: How do you create a Document object of custom size using iText 7?

I am trying to create a Document object with a custom page size in C# using iText 7.
So far I have tried passing a rectangle using the documentation's definition for resolution of 72 user units per inch:
Rectangle pageSize = new Rectangle(288, 306);
string fullFilePath = "some string";
PdfWriter pdfwriter = new PdfWriter(fullFileNamePDF);
PdfDocument pdf = new PdfDocument(pdfwriter);
pdf.AddNewPage();
Document Doc = new Document(pdf, rect);
However, the code fails compilation with 'cannot convert from iText.Kernel.Geom.Rectangle to iText.Kernel.Geom.PageSize.'
You need to update your code so that you pass in a PageSize to the document constructor instead of the Rectangle directly.
e.g.
// This:
Document Doc = new Document(pdf, rect);
// Should be this:
Document Doc = new Document(pdf, new PageSize(rect));

How to overwrite an existing bookmark tree in a PDF using iText7

I'm developping an utility that take tab incremented text file as an input to create a bookmark tree (aka outlines) in an existing PDF file, using iText7.
Obvisously this is not the real code, but this is basically how I build the tree:
PdfReader reader = new PdfReader(srcFilePath);
PdfWriter writer = new PdfWriter(targetFilePath);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
PdfOutline rootOutline = pdfDoc.GetOutlines(false);
PdfOutline mainTitleOutline;
(mainTitleOutline = rootOutline.AddOutline("Title 1")).AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(1)));
mainTitleOutline.AddOutline("Sub title 1.1").AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(2)));
mainTitleOutline.AddOutline("Sub title 1.2").AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(3)));
(mainTitleOutline = rootOutline.AddOutline("Title 2")).AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(4)));
mainTitleOutline.AddOutline("Sub title 2.1").AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(5)));
mainTitleOutline.AddOutline("Sub title 2.2").AddDestination(PdfExplicitDestination.CreateFit(pdfDoc.GetPage(6)));
pdfDoc.Close();
This works pretty well when the PDF doesn't already have any bookmark, but when there are (pdfDoc.GetOutlines(false).GetAllChildren().Count > 0), I'd like to delete the whole tree before hand (hence overwrite them), because if I don't, I end up ADDING the new outlines to the old ones.
Is there a way to do it?
This piece of convenient API is indeed something that is missing now but you can still do it on a low level with one line of code:
pdfDocument.GetCatalog().GetPdfObject().Remove(PdfName.Outlines);
Just make sure to remove the outlines before you access them first time, i.e.:
PdfReader reader = new PdfReader(srcFilePath);
PdfWriter writer = new PdfWriter(targetFilePath);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
// Remove outlines before getting PdfOutline object by calling GetOutlines
pdfDocument.GetCatalog().GetPdfObject().Remove(PdfName.Outlines);
PdfOutline rootOutline = pdfDoc.GetOutlines(false);

Flatten dynamic pdf using iTextSharp

I' m using itextsharp to create pdf from template pdf file. But new pdf file is created like dynamic pdf. I want to convert this file to static pdf file, so i tried to use xfaworker. I get "Signature was corrupted" error from itextsharp.licensekey.dll. How can i use xfaworker or another dll for flatten dynamic pdf?
public string Create(FaxPDFModel model, MemoryStream ms)
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string templatePath = Path.GetDirectoryName(Uri.UnescapeDataString(uri.Path));
PdfReader pdfTemplate = new PdfReader(Path.Combine(Path.Combine(templatePath, "Docs"), "fax_template.pdf"));
PdfStamper stamper = new PdfStamper(pdfTemplate, ms);
stamper.Writer.CloseStream = false;
BaseFont bf = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, "ISO-8859-9", BaseFont.EMBEDDED);
var acroFields = stamper.AcroFields;
acroFields.GenerateAppearances = true;
stamper.FormFlattening = true;
acroFields.AddSubstitutionFont(bf);
acroFields.SetField("Name", "Mutabakat test");
acroFields.SetField("Title", "DANIŞMANLIK");
acroFields.SetField("Department", "test");
acroFields.SetField("Phone", "0 (212) 555 55 55");
stamper.Close();
string path = Path.Combine(Path.Combine(templatePath, "Docs"), System.Guid.NewGuid().ToString());
string pdfPath = path + ".pdf";
Document document = new Document();
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(pdfPath, FileMode.Create));
XFAFlattener xfaf = new XFAFlattener(document, writer);
ms.Position = 0;
xfaf.Flatten(new PdfReader(ms));
document.Close();
return pdfPath;
}
If you want to solve your problem, you will have to start by fixing the following errors:
1. You are using code to fill AcroForms instead of code to fill XFA forms:
If you have a dynamic XFA form, your PDF acts as a container for XML. This form doesn't expect data in the form of key value pairs. This form expects data stored as XML.
You can not use this code:
var acroFields = stamper.AcroFields;
acroFields.AddSubstitutionFont(bf);
acroFields.SetField("Name", "Mutabakat test");
acroFields.SetField("Title", "DANIŞMANLIK");
acroFields.SetField("Department", "test");
acroFields.SetField("Phone", "0 (212) 555 55 55");
This code expects that your form is an AcroForm. You need to fill the form like this:
AcroFields form = stamper.AcroFields;
XfaForm xfa = form.Xfa;
xfa.FillXfaForm(new FileStream(xml, FileMode.Open));
In this snippet xml refers to the data stored as XML.
2. You try to flatten the form before flattening the form:
I see this line in the first part of your code:
stamper.FormFlattening = true;
With this line, you remove all interactivity from your PDF. After closing the stamper object, you no longer have a form, hence the second part of your code will never work.
3. You are trying to embed a Standard Type 1 font:
This line doesn't make sense:
BaseFont bf = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, "ISO-8859-9", BaseFont.EMBEDDED);
Times-Roman is a Standard Type 1 font (in the old days, we called this a Base14 font); iText never embeds any of the 14 Standard Type 1 fonts defined for PDF, hence the parameter BaseFont.EMBEDDED will be ignored.
4. The real error:
XFA Worker is a closed source addon for iTextSharp. It requires a valid license key. When you get an error saying "Signature was corrupted", you are using a license key that is corrupt.
Possible causes:
You are not a customer of iText Group. You are using a key that you found somewhere and you changed some of its contents.
You are a customer of iText Group. You received a key, but somehow it got tampered with. In the past, we've had a similar problem where a customer was reading the key as if it was encoded in EBCDIC. Please contact your account manager at iText Group for more info.

How to add new page in pdf for multiple record iTextsharp

I have an xml and mapping to pdf form field using iTextsharp. It works well for single record. But when multiple records are there, it does not add 2nd record in the output pdf. Here is a code
public static void GeneratePdf(string sin, List<XElement> elements)
{
var pdfTemplate = HttpContext.Current.Server.MapPath("~/input.pdf");
var newFile = HttpContext.Current.Server.MapPath("~/output.pdf");
var pdfReader = new PdfReader(pdfTemplate);
var pdfStamper = new PdfStamper(pdfReader, new FileStream(
newFile, FileMode.Create));
foreach (var element in elements)
{
foreach (var elem in elements.Elements())
{
pdfStamper.AcroFields.SetField(elem.Name.ToString(), (string)elem);
}
}
pdfStamper.FormFlattening = false;
pdfStamper.Close();
}
Your question is unclear because you're telling us nothing about the nature of your form.
IF YOU'RE FORM IS BASED ON ACROFORM TECHNOLOGY
Please take a look at this video tutorial: http://itextpdf.com/codenvy_webapp
You can find the examples used in this tutorial here: https://github.com/blowagie/itextsamples
You can also find the standalone examples here: http://itextpdf.com/sandbox/acroforms/reporting
Note that there's an example "HOW NOT TO DO IT". Make sure you use the correct example: FillFlattenMerge2
Document document = new Document();
PdfCopy copy = new PdfSmartCopy(document, new FileOutputStream(dest));
document.open();
ByteArrayOutputStream baos;
PdfReader reader;
PdfStamper stamper;
AcroFields fields;
while (myApp.hasMoreRecords()) {
baos = new ByteArrayOutputStream();
reader = new PdfReader(SRC);
stamper = new PdfStamper(reader, baos);
fields = stamper.getAcroFields();
myApp.processNextRecord(fields);
stamper.setFormFlattening(true);
stamper.close();
reader.close();
// add the PDF to PdfCopy
reader = new PdfReader(baos.toByteArray());
copy.addDocument(reader);
reader.close();
}
document.close();
Note that myApp is an instance of a custom class you could write to loop over a record set. You'd implement a method hasMoreRecords() and processNextRecord() to loop over the records and process them one by one.
IF YOUR FORM IS BASED ON THE XML FORMS ARCHITECTURE
In this case, you're using the wrong methods. You can't fill out a dynamic form using the setField() method. The fact that it works for one record is a sign that your form is either an AcroForm or a hybrid XFA form. In both cases you can NOT achieve what you want without changing your form into a pure, dynamic XFA form.
As soon as you have a pure, dynamic XFA form, you need to use this code:
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader,
new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
XfaForm xfa = form.getXfa();
xfa.fillXfaForm(new FileInputStream(xml));
stamper.close();
reader.close();
I repeat: this code snippet will only work if you have a correct form. Elements in your question indicate that this is not the case. If your form isn't a dynamic XFA form, you won't find any software that can achieve what you want!!!
Watch these movies for more info: http://itextpdf.com/product/xfa_worker

Categories

Resources