I have a requirement,where I can select multiple records,and choose the action to generate zipped report with document each(pdf in my case) for each of the selected entries.
For example Employee1,Employee2,Employee3 would be selected,and when I choose to generate report,3 reports should be generated one each for the employee,and the output has to be zipped and downloaded.
For now what I do is generate the jasperPrint and export the report to ZipOutputstream with a new zipentry for each of the employee.
This means running the queries thrice and adding the outputstream to zip.
Is there a better way of doing it?
Your solution is normally the correct way, the alternatives are if you need to avoid multiple queries.
Load all you data in to a List<Employee> pass a new JRBeanCollectionDataSource(List<Employee>) for each Employee. (This decrease queries but increase memory usage).
If you have control of the pages (example 1 employee per page), you can generate 1 pdf with all employees and then use itext to split it in multiple pdf.
PdfReader reader = new PdfReader("nameOfReport.pdf");
int n = reader.getNumberOfPages();
int i = 0;
while ( i < n ) {
Document document = new Document(reader.getPageSizeWithRotation(1));
PdfCopy writer = new PdfCopy(document, new FileOutputStream("Employee_" + i + ".pdf"));
document.open();
PdfImportedPage page = writer.getImportedPage(reader, ++i);
writer.addPage(page);
document.close();
writer.close();
}
Related
I am able to copy the contents and edit , but i am not getting the same template as the old one, the template is getting changed, and i have a image on my old file and that image is also not getting copied into my new file , rest of the other contents are getting copied,c an someone help me to make my new pdf file template as the old one, here is my code below.
public static void Main(string[] args)
{
var editedText = ExtractTextFromPdf(#"C:\backup_temp\Template.pdf");
string outputfile =#"C:\backup_temp\Result.pdf";
using (var fileStream = new FileStream(outputfile, FileMode.Create,
FileAccess.Write))
{
Document document = new Document(PageSize.A4, 25, 25, 30, 30);
PdfWriter writer = PdfWriter.GetInstance(document, fileStream);
document.Open();
document.Open();
document.Add(new Paragraph(editedText));
document.Close();
writer.Close();
fileStream.Close();
}
}
public static string ExtractTextFromPdf(string path)
{
using (PdfReader reader = new PdfReader(path))
{
StringBuilder text = new StringBuilder();
for (int i = 1; i <= reader.NumberOfPages; i++)
{
text.Append(PdfTextExtractor.GetTextFromPage(reader, i));
text.Replace("[DMxxxxxxx]", "[DM123456]");
}
return text.ToString();
}
}
As Bruno says, if your "template" is another pdf document, you can not achieve this functionality in a trivial way. Pdf documents do not automatically reflow their content. And to the best of my knowledge, there is no pdf library that will allow you to insert/replace/edit content and still produce a nice-looking document.
The best solution in your case would be:
store the template document as an easy to edit format
generate the pdf document based on this easy template
Example use-case:
I have some HTML document that contains the precise layout and images and text, and some placeholders for things I want to fill in.
I use JSoup (or some other library) to edit the DOM structure of my template, this is very easy since I can give elements IDs and simply change the content by ID. I don't need regular expressions.
I use pdfHTML (iText add-on) to convert my html document to pdf
I'm creating adf project and generating reports using itextpdf 5.1.3.
For eg:- My table customer has 3000 rows.In my jspx page has customer table & button has file downloader listner there i'm simply calling the report.
Report is generating for only first 50 rows (maximum 4 pages) are only coming.
Why the remaining rows are not coming in reports?
private void generatePDFFile(FacesContext facesContext, java.io.OutputStream outputStream) {
try {
DCBindingContainer dcBindings = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding iterBind1 = (DCIteratorBinding)dcBindings.get("CustomerView1Iterator");
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(FILE)); \\file path local disk D:\mywork\customer.pdf
document.open();
Row[] rows= iterBind1.getAllRowsInRange();
for(Row row:rows){
custcode = (String) row.getAttribute("CustomerCode");
custname = (String) row.getAttribute("CustomerNameE");
addgroup(document);
}
document.close();
facesContext = facesContext.getCurrentInstance();
ServletContext context = (ServletContext)facesContext.getExternalContext().getContext();
File file = new File(FILE);
FileInputStream fileInputStream;
byte[] b;
System.out.println(file.getCanonicalPath());
System.out.println(file.getAbsolutePath());
fileInputStream = new FileInputStream(file);
int n = fileInputStream.available();
while (n > 0) {
b = new byte[n];
//b = new byte[8192];
int result = fileInputStream.read(b);
outputStream.write(b, 0, b.length);
if (result == -1)
break;
}
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}
}
private static void addgroup(Document document) throws DocumentException{
Paragraph preface1 = new Paragraph();
Paragraph preface2 = new Paragraph();
preface1.add(new Chunk("\n"));
preface1.add(new Chunk("Customer : "+custcode+" "+custname,BlueFont));
preface1.add(new Chunk("\n"));
document.add(preface1);
document.add(preface2);
}
The maximum size of a page in a PDF document is 14,400 by 14,400 user units. See the blog post Help, I only see blank pages in my PDF. This is not a limitation introduced by iText; it's a limitation that exists in PDF viewers such as Adobe Reader. Other viewers (such as Apple Preview) have no problem displaying PDFs with larger pages.
This answers the question in the Subject-line of your post.
The body of your post contains a completely different question. Maybe you aren't asking about the page size, but rather about the file size. That question has also been answered in the past. See What is the size limit of pdf file?
Allow me to summarize that answer:
The maximum size of a PDF with a version older than PDF 1.5 is about 10 gigabytes.
The maximum size of a PDF with a version PDF 1.5 or higher using a compressed cross-reference stream depends only on the limitations of the software processing the PDF.
The maximum size of a PDF created with iText versions before 5.3 is 2 gigabytes. The maximum size of a PDF created with iText versions 5.3 and higher is 1 terabyte.
Since you are using iText 5.1.3, you can create a PDF of 2 GBytes. It beats me why you are using a version of iText that dates from November 2011 instead of a more recent version, but there is no reason why you wouldn't be able to put a table containing 3000 rows in a PDF that can be as large as 2 GBytes.
Chances are that your code is really bad. Unfortunately, you don't show us your code. Did you read the documentation on how to create Large Tables?
I can't comment on the part where you say:
In my jspx page has customer table & button has file downloader listner there i'm simply calling the report.
That doesn't seem to be relevant in the context of your question.
We are using iText Java 5.5.3 with XFAWorker to inject XML into PDF templates and flatten those to simple PDFs.
To integrate into a system that has parts built in various technologies we have wrapped it into a http-Server using the simple framework
The injection stage works fine, but after flattening some sections are lost.
Detailled information:
The PDF template we inject into is: CLAIM.Plan.pdf.
Sample data we try to inject is: plan_v4.xml.
Without flattening we get: CLAIM_plan_unflattened.pdf.
With flattening the result is CLAIM_plan_flattened.pdf.
plan_v4.xml has multiple instances of //form/PlanItems/PlanItem and [CLAIM_plan_v3.pdf][6] is repeating the section to display all of them. This is the OK case. [CLAIM_plan_v4.pdf][7] is not showing the repeated sections for the individual PlanItem instances. This is the broken case.
The main bit of code that uses iText looks like this:
// load the XML document that contains the contents of the data element.
// NOT the <data> element itself or anything else.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document newdoc = db.parse(new InputSource(new InputStreamReader(xfaStream, "UTF-8")));
Node newdata = newdoc.getDocumentElement();
// Open the PDF and extract the complete xfa.
PdfReader reader = new PdfReader(pdfStream);
XfaForm xfa = new XfaForm(reader);
Document doc = xfa.getDomDocument();
// Remove all contents of the <data> element
NodeList list = doc.getElementsByTagNameNS("http://www.xfa.org/schema/xfa-data/1.0/", "data");
Node child;
do {
child = list.item(0).getFirstChild();
if (child!=null) {
list.item(0).removeChild(child);
}
} while (child!=null);
// Replace <data> with the new xml to inject.
list.item(0).appendChild(doc.importNode(newdata,true));
ByteArrayOutputStream os = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, os, '\0', false);
xfa.setDomDocument(doc);
xfa.setChanged(true);
XfaForm.setXfa(xfa, stamper.getReader(), stamper.getWriter());
stamper.close();
If I now just finish quickly:
response.getOutputStream().write(os.toByteArray());
I get the good (but unflattened) result.
If I add the flattening stage like this:
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter writer = PdfWriter.getInstance(document, response.getOutputStream());
XFAFlattener xfaf = new XFAFlattener(document, writer);
xfaf.flatten(new PdfReader(os.toByteArray()));
document.close();
The result is flattened but missing the repeated sections.
Can someone tell me what I am doing wrong so the PlanItems don't get rendered in the final PDF?
My code below is lost when opening PDF file which has only one column on the front page and more than 1 column on other pages.
Someone can tell me what I'm doing wrong?
Below my code:
PdfReader pdfreader = new PdfReader(pathNmArq);
ITextExtractionStrategy strategy = new SimpleTextExtractionStrategy();
for (int page=1; page <= lastPage; page++)
{
extractText = PdfTextExtractor.GetTextFromPage(pdfreader, page, strategy);
extractText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(extractText)));
/ / ...
}
You use the SimpleTextExtractionStrategy. This strategy assumes that the text drawing instructions in the PDF are sorted by the reading order. In your case that does not seem to be the case.
If you cannot count on the PDF containing drawing operations in reading order but are only using iText text extraction strategies from the distribution, you have to know areas which constitute a single column. If a page contains multiple columns, you have to use RegionTextRenderFilter to restrict to a column and then use the LocationTextExtractionStrategy.
PS: What exactly is your intention in that
extractText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(Encoding.Default, Encoding.UTF8, Encoding.Default.GetBytes(extractText)));
line?
I'm having a very strange issue with XFA Forms in iText / iTextSharp (iTextSharp 5.3.3 via NuGet). I am trying to fill out a static XFA styled form, however my changes are not taking.
I have both editions of iText in Action and have been consulting the second edition as well as the iTextSharp code sample conversions from the book.
Background: I have an XFA Form that I can fill out manually using Adobe Acrobat on my computer. Using iTextSharp I can read what the Xfa XML data is and see the structure of the data. I am essentially trying to mimic that with iText.
What the data looks like when I add data and save in Acrobat (note: this is only the specific section for datasets)
Here is the XML file I am trying to read in to replace the existing data (note: this is the entire contexts of that file):
However, when I pass the path to the replacement XML File in and try to set the data, the new file created (a copy of the original with the data replaced) without any errors being thrown, but the data is not being updated. I can see that the new file is created and I can open it, but there is no data in the file.
Here is the code being utilized to replace the data or populate for the first time, which is a variation of http://sourceforge.net/p/itextsharp/code/HEAD/tree/trunk/book/iTextExamplesWeb/iTextExamplesWeb/iTextInAction2Ed/Chapter08/XfaMovie.cs
public void Generate(string sourceFilePath, string destinationtFilePath, string replacementXmlFilePath)
{
PdfReader pdfReader = new PdfReader(sourceFilePath);
using (MemoryStream ms = new MemoryStream())
{
using (PdfStamper stamper = new PdfStamper(pdfReader, ms))
{
XfaForm xfaForm = new XfaForm(pdfReader);
XmlDocument doc = new XmlDocument();
doc.Load(replacementXmlFilePath);
xfaForm.DomDocument = doc;
xfaForm.Changed = true;
XfaForm.SetXfa(xfaForm, stamper.Reader, stamper.Writer);
}
var bytes = ms.ToArray();
File.WriteAllBytes(destinationtFilePath, bytes);
}
}
Any help would be very much appreciated.
I found the issue. The replacement DomDocument needs to be the entire merged XML of the new document, not just the data or datasets portion.
I upvoted your answer, because it's not incorrect (I'm happy my reference to the demo led you to have another look at your code), but now that I have a second look at your original code, I think it's better to use the book example:
public byte[] ManipulatePdf(String src, String xml) {
PdfReader reader = new PdfReader(src);
using (MemoryStream ms = new MemoryStream()) {
using (PdfStamper stamper = new PdfStamper(reader, ms)) {
AcroFields form = stamper.AcroFields;
XfaForm xfa = form.Xfa;
xfa.FillXfaForm(XmlReader.Create(new StringReader(xml)));
}
return ms.ToArray();
}
}
As you can see, it's not necessary to replace the whole XFA XML. If you use the FillXfaForm method, the data is sufficient.
Note: for the C# version of the examples, see http://tinyurl.com/iiacsCH08 (change the 08 into a number from 01 to 16 for the examples of the other chapters).