I need to add the total page count to a PDF/A-2 document created using iText in Java. The following code is being used:
public class HeaderFooterPageEvent extends PdfPageEventHelper {
Font fontHEADER = null;
/** The template with the total number of pages. */
PdfTemplate total;
public HeaderFooterPageEvent() {
try {
fontHEADER = new Font(BaseFont.createFont("OpenSans-Regular.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED), 8, Font.BOLD);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onOpenDocument(PdfWriter writer, Document document) {
total = writer.getDirectContent().createTemplate(30, 16);
super.onOpenDocument(writer, document);
}
#Override
public void onCloseDocument(PdfWriter writer, Document document) {
PdfContentByte cb = writer.getDirectContent();
ColumnText.showTextAligned(total, Element.ALIGN_RIGHT,
new Phrase(String.valueOf(writer.getPageNumber() - 1)),fontHEADER),
document.right() - document.rightMargin()+5,
document.bottom() - 10, 0);
super.onCloseDocument(writer, document);
}
}
And when creating the PDF the following code is called:
Document document = new Document(PageSize.A4, 15, 15, 30, 20);
PdfAWriter writer = PdfAWriter.getInstance(document, new FileOutputStream(dest), PdfAConformanceLevel.PDF_A_2A);
writer.createXmpMetadata();
writer.setTagged();
// add header and footer
HeaderFooterPageEvent event = new HeaderFooterPageEvent();
writer.setPageEvent(event);
document.open();
document.addLanguage("en-us");
File file = new File("sRGB_CS_profile.icm");
ICC_Profile icc = ICC_Profile
.getInstance(new FileInputStream(file));
writer.setOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc);
Paragraph p=new Paragraph("Page 1 content",fontEmbedded); //setting an embedded font
p.setSpacingBefore(30f);
document.add(p);
document.newPage();
document.add(new Paragraph("Content of next page goes here",fontEmbedded));
document.close();
Now when we add content on 2 pages and use document.newPage() to add the new page, runtime exception is generated The page 3 was requested but the document has only 2 pages. What is a solution to this problem?
This question already has answers here:
iTextSharp-generated PDFs now cause Save dialog in Adobe Reader X
(2 answers)
Closed 5 years ago.
I am generating some reports with iTextSharp 5.
Opening the generated .PDF-file, everything looks and actually is fine with most PDF-readers.
When I open the PDF using AdobeReader(DC) however, it asks me if i want to save the changes on close. Although I didn't change anything.
Hitting 'Cancel' sure makes the message window go away, but hitting save causes the file to actually shrinks in size.
Now what is happening there? And why? How can I disable it?
The users of the application are most likely gonna use AdobeReader as well.
I don't want them to see the save dialog anytime they open a report.
Here is my BaseReport class
public abstract class BaseReport : PdfPageEventHelper
{
protected const string SPACE = " ";
protected const string COLON = ":";
protected static string NEWLINE = Environment.NewLine;
protected Document document;
protected PdfTemplate footerTemplate;
protected PdfContentByte contentByte;
protected PdfWriter writer;
private PdfTemplate totalPageNoTemplate;
private int lastPageNumber;
// properties for header
private bool done;
// needs to be overriden in subclass order to use header feature
protected string kundeHeader { get; set; }
// font definitions
protected BaseFont baseFont;
protected Font fontFooter;
protected Font fontGeneralText;
protected Font fontLabelText;
protected Font fontBoldLabelText;
protected Font fontBoldText;
protected Font fontSpace;
protected Font fontLargeBoldText;
protected int language;
protected bool useLogo = false;
protected bool usePageNumbers = false;
protected bool usePrintDate = false;
protected const string PRINT_FULLDATE_FORMAT = "dd.MM.yyyy HH:mm";
protected const string PRINT_DATE_ONLY_FORMAT = "dd.MM.yyyy";
protected Rectangle pagesize = PageSize.A4;
protected float marginLeft = 80;
protected float marginRight = 35;
protected float marginTop = 40;
protected float marginBottom = 40;
private MemoryStream PDFStream { get; set; } = new MemoryStream();
private DateTime printDate;
public BaseReport(int language = Languages.DE, bool landscape = false)
{
this.language = language;
if (landscape)
{
pagesize = pagesize.Rotate();
}
}
public byte[] GenerateReport()
{
CultureInfo cultureBefore = Resources.Culture;
try
{
Resources.Culture = SelectCultureForLangauge();
PrepareReport();
document = new Document(pagesize, marginLeft, marginRight, marginTop, marginBottom);
BuildFonts();
OpenDocument();
PrepareDocument();
GenerateContent();
document.Close();
return PDFStream.GetBuffer();
} finally
{
Resources.Culture = cultureBefore;
}
}
public void GenerateReport(string filename)
{
byte[] report = GenerateReport();
using (FileStream f = new FileStream(filename, FileMode.Create))
{
f.Write(report, 0, report.Length);
}
}
protected CultureInfo SelectCultureForLangauge()
{
string languageCode = GetLanguageCode();
return CultureInfo.GetCultureInfo(languageCode);
}
protected string GetLanguageCode()
{
string languageCode = string.Empty;
switch (language)
{
case Languages.FR: languageCode = "FR"; break;
case Languages.IT: languageCode = "IT"; break;
case Languages.EN: languageCode = "EN"; break;
default: languageCode = "DE"; break;
}
return languageCode;
}
protected virtual void PrepareReport() { }
protected virtual void PrepareDocument() { }
protected abstract void GenerateContent();
private void BuildFonts()
{
baseFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
fontFooter = FontFactory.GetFont(FontFactory.HELVETICA, 11, Font.ITALIC, BaseColor.DARK_GRAY);
fontGeneralText = FontFactory.GetFont(FontFactory.HELVETICA, 11, Font.NORMAL, BaseColor.BLACK);
fontLabelText = FontFactory.GetFont(FontFactory.HELVETICA, 8.5f, Font.NORMAL, BaseColor.BLACK);
fontBoldLabelText = FontFactory.GetFont(FontFactory.HELVETICA, 8.5f, Font.BOLD, BaseColor.BLACK);
fontBoldText = FontFactory.GetFont(FontFactory.HELVETICA, 11, Font.BOLD, BaseColor.BLACK);
fontSpace = FontFactory.GetFont(FontFactory.HELVETICA, 3.5f, Font.NORMAL, BaseColor.BLACK);
fontLargeBoldText = FontFactory.GetFont(FontFactory.HELVETICA, 17, Font.BOLD, BaseColor.BLACK);
GetFontIfAvailable();
}
private void GetFontIfAvailable()
{
string fileName = "IF_Rg";
try
{
baseFont = LoadFontFromFile(fileName, true);
fontFooter = new Font(baseFont, 11, Font.ITALIC, BaseColor.DARK_GRAY);
fontGeneralText = new Font(baseFont, 11, Font.NORMAL, BaseColor.BLACK);
fontLabelText = new Font(baseFont, 8.5f, Font.NORMAL, BaseColor.BLACK);
fontBoldLabelText = new Font(baseFont, 8.5f, Font.BOLD, BaseColor.BLACK);
fontBoldText = new Font(baseFont, 11, Font.BOLD, BaseColor.BLACK);
fontSpace = new Font(baseFont, 3.5f, Font.NORMAL, BaseColor.BLACK);
fontLargeBoldText = new Font(baseFont, 17, Font.BOLD, BaseColor.BLACK);
} catch (FileNotFoundException)
{
LogWrapper.Warn("Font not found - using default.");
}
}
protected BaseFont LoadFontFromFile(string fileName, bool embedded)
{
string fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\" + fileName + ".ttf";
if (File.Exists(fontPath))
{
return BaseFont.CreateFont(fontPath, BaseFont.WINANSI, embedded);
}
else
{
throw new FileNotFoundException($"Fontfile {fileName} was not found!");
}
}
protected Image HeaderLogo()
{
Image logo = Image.GetInstance(Resources.logo, BaseColor.BLACK);
// TODO msc pick logo from debitor
logo.ScaleToFit(100f, 100f);
return logo;
}
protected void OpenDocument()
{
writer = PdfWriter.GetInstance(document, PDFStream);
writer.PageEvent = this;
writer.SetFullCompression();
document.Open();
contentByte = writer.DirectContent;
}
protected void AddLabelAt(string label, float posX, float posY)
{
PdfContentByte cb = writer.DirectContent;
ColumnText column = new ColumnText(cb);
column.SetText(new Paragraph(label + NEWLINE, fontLabelText));
column.SetSimpleColumn(posX, 20, posX + 200, posY);
column.Go();
}
protected void AddLabelOnMargin(string label)
{
AddLabelAt(label, document.LeftMargin - 40, writer.GetVerticalPosition(false));
}
protected Phrase ParaLine(string Text, Font textfont)
{
return new Phrase(Text, textfont);
}
public override void OnOpenDocument(PdfWriter writer, Document document)
{
if (usePageNumbers)
{
totalPageNoTemplate = writer.DirectContentUnder.CreateTemplate(50, 50);
}
if (usePrintDate)
{
printDate = DateTime.Now;
}
}
public override void OnStartPage(PdfWriter writer, Document document)
{
if (useLogo || (document.PageNumber > 1 && !string.IsNullOrEmpty(kundeHeader)))
{
PdfContentByte canvas = writer.DirectContentUnder;
canvas.SaveState();
if (document.PageNumber > 1 && !string.IsNullOrEmpty(kundeHeader))
{
//showtextaligned only shows a single line
//therefor the header needs to be split and its parts need to be added seperately
string[] headerParts = kundeHeader.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
Phrase header = new Phrase(kundeHeader, fontLabelText);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT,
ParaLine(headerParts[0], fontLabelText),
document.LeftMargin,
document.Top + 30, 0);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT,
ParaLine(headerParts[1], fontLabelText),
document.LeftMargin,
document.Top + 20, 0);
}
if (useLogo)
{
Image logo = HeaderLogo();
logo.SetAbsolutePosition(marginLeft - 17.5f, document.Top + document.TopMargin - 50);
document.Add(logo);
}
canvas.RestoreState();
}
}
public override void OnEndPage(PdfWriter writer, Document document)
{
if (usePageNumbers || usePrintDate)
{
PdfContentByte canvas = writer.DirectContentUnder;
canvas.SaveState();
if (usePageNumbers)
{
// adds current page number to the footer section of the document
int pageN = writer.PageNumber;
string text = Resources.LabelSeite + SPACE + pageN + "/";
float len = fontLabelText.BaseFont.GetWidthPoint(text, fontLabelText.Size);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT,
ParaLine(text, fontLabelText),
document.LeftMargin,
document.Bottom - 10, 0);
// adds template to fill in total page number (see OnCloseDocument method)
canvas.AddTemplate(totalPageNoTemplate, document.LeftMargin + len, document.Bottom - 10);
lastPageNumber = pageN;
}
if (usePrintDate)
{
// adds the printdate to the footer secdtion of the document
string dateFormatted = printDate.ToString(PRINT_FULLDATE_FORMAT);
ColumnText.ShowTextAligned(canvas, Element.ALIGN_RIGHT,
ParaLine(dateFormatted, fontLabelText),
document.Right,
document.Bottom - 10, 0);
}
canvas.RestoreState();
}
}
public override void OnCloseDocument(PdfWriter writer, Document document)
{
if (usePageNumbers)
{
// fills in the total page number to the prepared template in the footer section of the document
string text = lastPageNumber + "";
float widthPoint = fontLabelText.BaseFont.GetWidthPoint(text, fontLabelText.Size);
totalPageNoTemplate.Width = widthPoint;
ColumnText.ShowTextAligned(totalPageNoTemplate, Element.ALIGN_LEFT, ParaLine(text, fontLabelText), 0, 0, 0);
}
}
iTextSharp-generated PDFs now cause Save dialog in Adobe Reader X
I had to switch PDFStream.GetBuffer() with PDFStream.ToArray(); problem solved.
We use the nice library iText for one of my customer's project to generate a pdf from a string representing a html page. The iText version is 5.5.10.
The following piece of code works well on the development environments and servers running on Windows, but it is not working on the customer's server running on iSeries.
public class GeneratePDFCmdImpl extends ControllerCommandImpl implements
GeneratePDFCmd {
private String charsetStr = null;
private Charset charset = null;
private BaseFont bf = null;
private String destFile = null;
private String destFilename = null;
private String srcContent = null;
private String docName = null;
public void setDocName(String docname) {
this.docName = docname;
}
public void setSrcContent(String srcContent) {
this.srcContent = srcContent;
}
private void prepareDefaultsAndSettings() {
/* srcContent may be more complex html but even this simple one is not working */
srcContent = "<html><head></head><body>This is just a test</body></html>";
docName = "mypdf";
charsetStr = "UTF-8";
destFilename = docName+".pdf";
Date timestamp = new Date();
/* destFile = "/" is just for the sample. In my real project, the value is a folder where my app has full rights
*/
destFile = "/" + destFilename;
charset = Charset.forName(charsetStr);
FontFactory.register("/fonts/arial.ttf","Arial");
bf = FontFactory.getFont("Arial").getBaseFont();
}
#Override
public void performExecute() throws ECException {
super.performExecute();
Document document = null;
OutputStream os = null;
prepareDefaultsAndSettings();
try {
InputStream srcInputStream;
srcInputStream = new ByteArrayInputStream(srcContent.getBytes(charset));
document = new Document(PageSize.A4, 20, 20, 75, 80);
FileOutputStream destOutput = new FileOutputStream(destFile);
PdfWriter writer = PdfWriter.getInstance(document,destOutput);
writer.setPageEvent( new HeaderFooterPageEvent(bf));
document.open();
XMLWorkerHelper.getInstance().parseXHtml(writer, document, srcInputStream, charset);
document.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} finally {
if(document != null) {
document.close();
}
document = null;
try {
if (os != null) {
os.close();
}
} catch(IOException e) {
e.printStackTrace();
}
os = null;
}
}
private class HeaderFooterPageEvent extends PdfPageEventHelper {
PdfContentByte cb;
PdfTemplate template;
BaseFont bf;
Font f;
float fs;
public HeaderFooterPageEvent(BaseFont _bf) {
super();
bf = _bf;
f = new Font(bf);
}
#Override
public void onOpenDocument(PdfWriter writer, Document document) {
cb = writer.getDirectContent();
template = cb.createTemplate(50, 50);
}
#Override
public void onEndPage(PdfWriter writer, Document document) {
Date dat = new Date();
ColumnText ct = new ColumnText(writer.getDirectContent());
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm");
ct.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, new Phrase(sdf.format(dat) ), 100, 30, 0);
String text = "Page " +writer.getPageNumber() + " to ";
float len = bf.getWidthPoint(text, 12);
cb.beginText();
cb.setFontAndSize(bf, 12);
cb.setTextMatrix(450, 30);
cb.showText(text);
cb.endText();
cb.addTemplate(template, 450 + len, 30);
}
#Override
public void onCloseDocument(PdfWriter writer, Document document) {
template.beginText();
template.setFontAndSize(bf, 12);
template.showText(String.valueOf(writer.getPageNumber()));
template.endText();
}
}
}
When executed on the iSeries, we have the error message
com.ibm.commerce.command.ECCommandTarget executeCommand CMN0420E: The following command exception has occurred during processing: "ExceptionConverter: java.io.IOException: The document has no pages.". ExceptionConverter: java.io.IOException: The document has no pages.
at com.itextpdf.text.pdf.PdfPages.writePageTree(PdfPages.java:112)
at com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1256)
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:900)
at com.itextpdf.text.Document.close(Document.java:415)
at be.ourcustomer.package.GeneratePDFCmdImpl.performExecute(GeneratePDFCmdImpl.java:107)
I don't have much idea about what we do wrong. Any help would be greatly appreciated
I have a pdf, but beyond the current page, there is content that is not being displayed. I want to change the pagesize so that all of the content can be displayed. Is there a way to do this with itext?
public PdfReader changePDFPageSize(String inpdf,String outpdf,float vertical,float horizontal)
{
try
{
PdfReader reader = new PdfReader(inpdf);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outpdf));
for (int curPageNum = 1; curPageNum <= reader.getNumberOfPages(); ++curPageNum) {
PdfDictionary pagedict = reader.getPageN(curPageNum);
PdfArray mediabox = pagedict.getAsArray(PdfName.MEDIABOX);
mediabox.set(0, new PdfNumber(mediabox.getAsNumber(0).intValue()-horizontal));//left add
mediabox.set(1, new PdfNumber(mediabox.getAsNumber(1).intValue()-vertical));//down
mediabox.set(2, new PdfNumber(mediabox.getAsNumber(2).intValue()+horizontal));//right
mediabox.set(3, new PdfNumber(mediabox.getAsNumber(3).intValue()+vertical));//up
}
stamper.close();
return new PdfReader(outpdf);
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (DocumentException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
itextsharp VB.NET
Dim objReader As PdfReader
Dim objStream As FileStream
Dim objStamper As PdfStamper
Dim objContent As PdfContentByte
Dim objImport As PdfImportedPage
Dim objMark As Image
objReader = New PdfReader(strBookPath)
objStream = New FileStream(strTempPath, FileMode.Create)
objStamper = New PdfStamper(objReader, objStream)
objContent = objStamper.GetOverContent(1)
objImport = objStamper.GetImportedPage(objReader, 1)
objContent.AddTemplate(objImport, PageSize.A4.Width / objImport.Width, 0, 0, PageSize.A4.Height / objImport.Height, 0, 0)
objReader.GetPageN(1).Put(PdfName.CROPBOX, New PdfRectangle(PageSize.A4.Width, PageSize.A4.Height))
objReader.GetPageN(1).Put(PdfName.MEDIABOX, New PdfRectangle(PageSize.A4.Width, PageSize.A4.Height))
I have a JFrame, which i wish to save as a PDF.
How do i paint this JFrame using iText?
public PrintFrameToPDF(JFrame bill) {
try {
Document d = new Document();
PdfWriter writer = PdfWriter.getInstance(d, new FileOutputStream ("sample.pdf"));
d.open ();
// HOW ?
d.close ();
}
catch(Exception e) {
//
}
}
This should do the trick (and it's generic for JComponent object):
public PrintFrameToPDF(JFrame bill) {
try {
Document d = new Document();
PdfWriter writer = PdfWriter.getInstance(d, new FileOutputStream ("sample.pdf"));
d.open ();
PdfContentByte cb = writer.getDirectContent( );
PdfTemplate template = cb.createTemplate(width, height);
Graphics2D g2d = template.createGraphics(width, height);
bill.print(g2d);
bill.addNotify();
bill.validate();
g2d.dispose();
d.close ();
}
catch(Exception e) {
//
}
}