This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
I was trying to create a PDF using iText.
My objective is to make a question paper. I was able to only add the questions and answers to the PDF.
Then i tried modifying it by adding page numbers, watermarks etc. by adding Header/Footer. Now it gives me NullPointerException i cannot figure out what went wrong.
Error I'm getting
Caused by: java.lang.NullPointerException
at
edu.ijse.gdse41.ams.other.HeaderFooter.onEndPage(HeaderFooter.java:57)
at com.itextpdf.text.pdf.PdfDocument.newPage(PdfDocument.java:902)
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:837) at
com.itextpdf.text.Document.close(Document.java:416) at
edu.ijse.gdse41.ams.view.CreateAssignmentController.createPDF(CreateAssignmentController.java:644)
at
edu.ijse.gdse41.ams.view.CreateAssignmentController.proceedBtnClicked(CreateAssignmentController.java:292)
... 58 more
createPDF() method in CreateAssignment.java class
private void createPDF(ArrayList<Assignment_QuesDTO> questionPaper) throws DocumentException, BadElementException, IOException {
try {
OutputStream outputStream = null;
Document doc = new Document();
outputStream = new FileOutputStream(new File("C:\\Users\\Dell\\Documents\\NetBeansProjects\\AssignmentManagementSystem\\src\\PDF\\mypdf.pdf"));
PdfWriter writer = PdfWriter.getInstance(doc, outputStream);
PdfPageEventHelper eventHelper = new HeaderFooter(doc);
writer.setPageEvent(eventHelper);
doc.open();
Font fontTitle = new Font(Font.getFamily("TIMES_ROMAN"), 15);
Paragraph title = new Paragraph("ABC", fontTitle);
title.setAlignment(Paragraph.ALIGN_CENTER);
doc.add(title);
for (int i = 0; i < 3; i++) {
doc.add(Chunk.NEWLINE);
}
Paragraph subTitle = new Paragraph(questionPaper.get(1).getAssignment().getAssignName());
subTitle.setAlignment(Paragraph.ALIGN_CENTER);
Paragraph subTitle2 = new Paragraph(questionPaper.get(1).getAssignment().getDate());
subTitle2.setAlignment(Paragraph.ALIGN_CENTER);
doc.add(subTitle);
doc.add(subTitle2);
List orderedList = new List(List.ORDERED);
for (Assignment_QuesDTO questionPaper1 : questionPaper) {
Paragraph question = new Paragraph(questionPaper1.getQuestion().getQues());
question.setAlignment(Paragraph.ALIGN_JUSTIFIED);
orderedList.add(question);
List desc = new List(List.UNORDERED);
desc.setIndentationLeft(36);
desc.setListSymbol(new Chunk(" "));
desc.add(new Phrase("\t\t" + questionPaper1.getQuestion().getQuesDesc()));
orderedList.add(desc);
orderedList.add(Chunk.NEWLINE);
List answers = new List(List.ORDERED,List.ALPHABETICAL);
answers.setIndentationLeft(72);
for (AnswerDTO answer : questionPaper1.getQuestion().getAnswers()) {
answers.add(" " + answer.getAnswer());
}
orderedList.add(answers);
orderedList.add(Chunk.NEWLINE);
}
doc.add(orderedList);
doc.close();
} catch (FileNotFoundException ex) {
Logger.getLogger(CreateAssignmentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
HeaderFooter.java class
public class HeaderFooter extends PdfPageEventHelper {
Phrase[] header = new Phrase[2];
int pageNum;
Image watermark;
public HeaderFooter(Document doc) throws BadElementException, IOException {
this.watermark = Image.getInstance("C:\\Users\\Dell\\Documents\\NetBeansProjects\\AssignmentManagementSystem\\src\\edu\\ijse\\gdse41\\ams\\resources\\images\\watermark.png");
watermark.rotate();
watermark.scaleToFit(doc.getPageSize());
watermark.setRotationDegrees(30);
}
#Override
public void onChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title) {
header[1] = new Phrase(title.getContent());
pageNum = 1;
}
#Override
public void onEndPage(PdfWriter writer, Document document) {
try {
Rectangle rect = writer.getBoxSize("art");
switch (writer.getPageNumber() % 2) {
case 0:
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_RIGHT, header[0], rect.getRight(), rect.getTop(), 0);
break;
case 1:
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, header[1], rect.getLeft(), rect.getTop(), 0);
break;
}
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, new Phrase(String.format("Page %d", pageNum)), (rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
PdfContentByte content = writer.getDirectContent();
content.addImage(watermark);
} catch (DocumentException ex) {
Logger.getLogger(HeaderFooter.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void onStartPage(PdfWriter writer, Document document) {
pageNum++;
}
#Override
public void onOpenDocument(PdfWriter writer, Document document) {
header[0] = new Phrase("ABC");
}
}
In your page event, you assume that the PDF you are creating has an /ArtBox boundary:
Rectangle rect = writer.getBoxSize("art");
However, when I look at the code that creates your PDF, I don't see you creating such a page boundary anywhere. This means that rect is null, and that methods such as rect.getRight(), rect.getTop(),... throw a NullPointerException.
Related
How can I draw specific underline between :
String s = "This text is underlined with a dashed line";
Paragraph paragraph = new Paragraph();
Text text;
for (int i = 0; i <s.length() ; i++) {
text = new Text(String.valueOf(s.charAt(i)));
paragraph.add(text);
text.setNextRenderer(new DashedLineTextRenderer(text));
}
doc.add(paragraph);
doc.close();
private static class DashedLineTextRenderer extends TextRenderer {
public DashedLineTextRenderer(Text textElement) {
super(textElement);
}
// If renderer overflows on the next area, iText uses getNextRender() method to create a renderer for the overflow part.
// If getNextRenderer isn't overriden, the default method will be used and thus a default rather than custom
// renderer will be created
#Override
public IRenderer getNextRenderer() {
return new DashedLineTextRenderer((Text) modelElement);
}
#Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle rect = this.getOccupiedAreaBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas.moveTo(rect.getLeft(), rect.getBottom());
canvas.curveTo(rect.getLeft()+100,rect.getBottom()+5,
rect.getLeft()+150,rect.getBottom()-2,rect.getLeft()+200,rect.getBottom()-5);
canvas.stroke();
}
}
if i do with single element text it works:
enter image description here
How i can define where draw canvas if there are several text elements
The question is underspecified (see clarifying comment). Basically to avoid the overlap as on the screenshot:
You can customize the renderer for the Paragraph, not for the Text:
private static class WaveUnderlinedParagraphRenderer extends ParagraphRenderer {
public WaveUnderlinedParagraphRenderer(Paragraph paragraph) {
super(paragraph);
}
#Override
public void draw(DrawContext drawContext) {
super.draw(drawContext);
Rectangle rect = this.getOccupiedAreaBBox();
PdfCanvas canvas = drawContext.getCanvas();
canvas.moveTo(rect.getLeft(), rect.getBottom());
canvas.curveTo(rect.getLeft() + 100, rect.getBottom() + 5,
rect.getLeft() + 150, rect.getBottom() - 2, rect.getLeft() + 200, rect.getBottom() - 5);
canvas.stroke();
}
#Override
public IRenderer getNextRenderer() {
return new WaveUnderlinedParagraphRenderer((Paragraph) modelElement);
}
}
Document doc = new Document(pdfDocument);
String s = "This text is underlined with a dashed line";
Paragraph paragraph = new Paragraph();
Text text;
for (int i = 0; i <s.length() ; i++) {
text = new Text(String.valueOf(s.charAt(i)));
paragraph.add(text);
}
paragraph.setNextRenderer(new WaveUnderlinedParagraphRenderer(paragraph));
doc.add(paragraph);
doc.close();
And get the following result:
I have created a PDF file dynamically using iText Library, Now I want to add Header and Footer in PDF's pages, for this one I have added given code:
document.addHeader("My Header Title", "My Header Details");
But in my PDF's pages this header couldn't set. What is issue that I don't know, If you have any idea related to it,please share your thoughts.
In case you use a current iText version (i.e. 5.4.x as of now) have a look at the sample MovieHistory2 from iText in Action — 2nd Edition which shows how to add headers (different ones for odd and even pages) to a PDF while creating it.
Most essential is a PdfPageEventHelper implementation
/** Inner class to add a header and a footer. */
class HeaderFooter extends PdfPageEventHelper {
/** Alternating phrase for the header. */
Phrase[] header = new Phrase[2];
/** Current page number (will be reset for every chapter). */
int pagenumber;
/**
* Initialize one of the headers.
* #see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onOpenDocument(PdfWriter writer, Document document) {
header[0] = new Phrase("Movie history");
}
/**
* Initialize one of the headers, based on the chapter title;
* reset the page number.
* #see com.itextpdf.text.pdf.PdfPageEventHelper#onChapter(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document, float,
* com.itextpdf.text.Paragraph)
*/
public void onChapter(PdfWriter writer, Document document,
float paragraphPosition, Paragraph title) {
header[1] = new Phrase(title.getContent());
pagenumber = 1;
}
/**
* Increase the page number.
* #see com.itextpdf.text.pdf.PdfPageEventHelper#onStartPage(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onStartPage(PdfWriter writer, Document document) {
pagenumber++;
}
/**
* Adds the header and the footer.
* #see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onEndPage(PdfWriter writer, Document document) {
Rectangle rect = writer.getBoxSize("art");
switch(writer.getPageNumber() % 2) {
case 0:
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_RIGHT, header[0],
rect.getRight(), rect.getTop(), 0);
break;
case 1:
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_LEFT, header[1],
rect.getLeft(), rect.getTop(), 0);
break;
}
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER, new Phrase(String.format("page %d", pagenumber)),
(rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
}
}
which is registered like this:
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
HeaderFooter event = new HeaderFooter();
writer.setBoxSize("art", new Rectangle(36, 54, 559, 788));
writer.setPageEvent(event);
EDIT: As requested in the comments, a simpler variant of the onEndPage method with a static header instead of the alternating one:
public void onEndPage(PdfWriter writer, Document document)
{
Rectangle rect = writer.getBoxSize("art");
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_RIGHT, new Phrase("My static header text"),
rect.getRight(), rect.getTop(), 0);
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER, new Phrase(String.format("page %d", pagenumber)),
(rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
}
please refer this site.......
https://www.coderanch.com/how-to/java/ItextExample
Please first refer to the accepted answer of this question.
That answer is very helpful (and It helped me to).
Just in case you are programming in C#, here is the SAME accepted answer but in C# version
/// <summary>
/// Inner class to add a header and a footer.
/// </summary>
internal class HeaderFooter : PdfPageEventHelper
{
private Phrase[] header = new Phrase[2];
private int pageNumber;
public override void OnOpenDocument(PdfWriter writer, Document document)
{
header[0] = new Phrase("Smares in Header");
}
public override void OnChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title)
{
header[1] = new Phrase(title.Content);
pageNumber = 1;
}
public override void OnStartPage(PdfWriter writer, Document document)
{
pageNumber++;
}
public override void OnEndPage(PdfWriter writer, Document document)
{
Rectangle rect = writer.GetBoxSize("art");
switch (writer.PageNumber % 2)
{
case 0:
ColumnText.ShowTextAligned(writer.DirectContent,
Element.ALIGN_RIGHT, header[0],
rect.Right, rect.Top, 0);
break;
case 1:
ColumnText.ShowTextAligned(writer.DirectContent,
Element.ALIGN_LEFT, header[1],
rect.Left, rect.Top, 0);
break;
}
ColumnText.ShowTextAligned(writer.DirectContent,
Element.ALIGN_CENTER, new Phrase(String.Format("page {0}", pageNumber)),
(rect.Left + rect.Right) / 2, rect.Bottom - 18, 0);
}
}
and the registration of the event will be :
using (MemoryStream ms = new MemoryStream())
{
using (Document doc = new Document(PageSize.A4, -30, -30, 45, 45))
{
using (PdfWriter writer = PdfWriter.GetInstance(doc, ms))
{
HeaderFooter ev = new HeaderFooter();
writer.SetBoxSize("art", new Rectangle(36, 54, 559, 788));
writer.PageEvent = ev;
// continue your code here
}
}
}
NOTE : this is just a conversion of the accepted answer from java to C#.
but you can customize this according to your needs, as I did with it.
You can add like that
HeaderFooter header = new HeaderFooter(new Phrase("Add Header Part Here"), false);
HeaderFooter footer = new HeaderFooter(new Phrase("Add Footer Here"), new Phrase("."));
document.setHeader(header);
document.setFooter(footer);
Let's say that I want to load an shp file, do my stuff on it and save the map as an image.
In order to save an image I am using:
public void saveImage(final MapContent map, final String file, final int imageWidth) {
GTRenderer renderer = new StreamingRenderer();
renderer.setMapContent(map);
Rectangle imageBounds = null;
ReferencedEnvelope mapBounds = null;
try {
mapBounds = map.getMaxBounds();
double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0);
imageBounds = new Rectangle(0, 0, imageWidth, (int) Math.round(imageWidth * heightToWidth));
} catch (Exception e) {
// Failed to access map layers
throw new RuntimeException(e);
}
BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_RGB);
Graphics2D gr = image.createGraphics();
gr.setPaint(Color.WHITE);
gr.fill(imageBounds);
try {
renderer.paint(gr, imageBounds, mapBounds);
File fileToSave = new File(file);
ImageIO.write(image, "png", fileToSave);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
But, let's say I am doing something like this:
...
MapContent map = new MapContent();
map.setTitle("TEST");
map.addLayer(layer);
map.addLayer(shpLayer);
// zoom into the line
MapViewport viewport = new MapViewport(featureCollection.getBounds());
map.setViewport(viewport);
saveImage(map, "/tmp/img.png", 800);
1) The problem is that the zoom level isn't saved on the image file.Is there a way to save it?
2) When I am doing MapViewport(featureCollection.getBounds()); is there a way to extend a little bit the boundaries in order to have a better visual representation?
...
The reason that you aren't saving the map at the current zoom level is that in your saveImage method you have the line:
mapBounds = map.getMaxBounds();
which always uses the full extent of the map, you can change this to
mapBounds = map.getViewport().getBounds();
You can expand a bounding box by something like:
ReferencedEnvelope bounds = featureCollection.getBounds();
double delta = bounds.getWidth()/20.0; //5% on each side
bounds.expandBy(delta );
MapViewport viewport = new MapViewport(bounds);
map.setViewport(viewport );
A quicker (and easier) way to save a map from the GUI is to use a method like this which just saves exactly what is on the screen:
public void drawMapToImage(File outputFile, String outputType,
JMapPane mapPane) {
ImageOutputStream outputImageFile = null;
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(outputFile);
outputImageFile = ImageIO.createImageOutputStream(fileOutputStream);
RenderedImage bufferedImage = mapPane.getBaseImage();
ImageIO.write(bufferedImage, outputType, outputImageFile);
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (outputImageFile != null) {
outputImageFile.flush();
outputImageFile.close();
fileOutputStream.flush();
fileOutputStream.close();
}
} catch (IOException e) {// don't care now
}
}
}
I have written an android app to do inspections. It collects the data and then formats it and places it on a PDF document. I am having a problem creating a 2nd page of the PDF before I save it and email it. I have commented out "PAGE 2 OF PDF". This section of code up to the declaration of pdfName is where the problem is. I do not want to use anything like iText or Apose. Can anyone help???
public void createPDF(){
// Create a object of PdfDocument
PdfDocument document = new PdfDocument();
// content view is TableLayout of data
View content = findViewById(id.final_table_layout_for_pdf_page_1);
// create a page info with attributes as below
// page number, height and width
// i have used height and width to that of pdf content view
int pageNumber = 1;
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(content.getWidth(),
content.getHeight() - 20, pageNumber).create();
// create a new page from the PageInfo
PdfDocument.Page page = document.startPage(pageInfo);
// repaint the user's text into the page
content.draw(page.getCanvas());
// do final processing of the page
document.finishPage(page);
/* PAGE 2 OF PDF
content = findViewById(id.final_table_layout_for_pdf_page_2);
// create a page info with attributes as below
// for 2nd page
// i have used height and width to that of pdf content view
pageNumber = 2;
pageInfo = new PdfDocument.PageInfo.Builder(content.getWidth(),
content.getHeight() - 20, pageNumber).create();
// create a new page from the PageInfo
page = document.startPage(pageInfo);
// repaint the user's text into the page
content.draw(page.getCanvas());
// do final processing of the page
document.finishPage(page);*/
// saving pdf document to root dir
String pdfName = "pdf_inspection_demo.pdf";
// all created files will be saved at path /sdcard/PDFDemo_AndroidSRC/
File outputFile = new File("/storage/emulated/0/", pdfName);
try {
outputFile.createNewFile();
OutputStream out = new FileOutputStream(outputFile);
document.writeTo(out);
document.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
errorString = e.getMessage();
}
}
private void generatePDF() {
PdfDocument pdfDocument = new PdfDocument();
criNewPag(1,"ان شاء الله ",pdfDocument);
criNewPag(2,"ان شاء الله ربي ",pdfDocument);
File file = new File(Environment.getExternalStorageDirectory(), "GFG.pdf");
try {
pdfDocument.writeTo(new FileOutputStream(file));
Toast.makeText(getApplicationContext(), "PDF file generated successfully.", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
pdfDocument.close();
}
private void criNewPag(int numpag,String text, PdfDocument pdfDocument ){
Paint paint = new Paint();
Paint title = new Paint();
PdfDocument.PageInfo mypageInfo = new PdfDocument.PageInfo.Builder(pagewidth, pageHeight, numpag).create();
PdfDocument.Page myPage = pdfDocument.startPage(mypageInfo);
Canvas canvas = myPage.getCanvas();
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.gfgimage);
scaledbmp = Bitmap.createScaledBitmap(bmp, 140, 140, false);
canvas.drawBitmap(scaledbmp, 56, 40, paint);
title.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL));
title.setTextSize(15);
title.setColor(ContextCompat.getColor(this, R.color.purple_200));
canvas.drawText("A portal for IT professionals.", 209, 100, title);
canvas.drawText("Geeks for Geeks", 209, 80, title);
title.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
title.setColor(ContextCompat.getColor(this, R.color.purple_200));
title.setTextSize(15);
title.setTextAlign(Paint.Align.CENTER);
canvas.drawText(text, 150, 240, title);
pdfDocument.finishPage(myPage);
}
I generate an event for adding header and footer to every page on my pdf document, the problem is that when I add a new image to the page, the new image appears under the header image. I had tried to find the solution, but I can´t find it, I have tried with image on png with Alpha channel set, but the problem don´t disappear.
class PieCabecera extends PdfPageEventHelper{
public int numeroPagina;
public Image imagen;
public PdfPTable tabla;
public PdfTemplate tpl;
public Phrase cabecera;
Font smallBold = new Font(Font.FontFamily.HELVETICA, 1, Font.BOLD);
/**
*
* #param writer
* #param documento
*/
#Override
public void onStartPage(PdfWriter writer, Document documento){
numeroPagina++;
try{
imagen = Image.getInstance("D:/Users/Operador/Documents/NetBeansProjects/ServiciosWeb-dev/web/img/logoPDF.jpg");
imagen.setAbsolutePosition(50, 0);
PdfContentByte cbCabecera = writer.getDirectContent();
tpl = cbCabecera.createTemplate(600, 250);
tpl.addImage(imagen);
cbCabecera.addTemplate(tpl, 0, 750);
cabecera = new Phrase(cbCabecera + ".", smallBold);
documento.add(cabecera);
Paragraph parrafo0 = new Paragraph();
parrafo0.setSpacingBefore(12);
parrafo0.setSpacingAfter(14);
documento.add(parrafo0);
/*Línea de separación*/
LineSeparator ls = new LineSeparator();
documento.add(new Chunk(ls));
Paragraph parrafo = new Paragraph();
parrafo.setSpacingBefore(4);
documento.add(parrafo);
}catch(BadElementException e){
LOGGER.log(Level.SEVERE, "Error: {0}", e.getStackTrace());
}catch( IOException e){
LOGGER.log(Level.SEVERE, "Error: {0}", e.getStackTrace());
}catch( DocumentException e){
LOGGER.log(Level.SEVERE, "Error: {0}", e.getStackTrace());
}
}
/**
*
* #param writer
* #param documento
*/
#Override
public void onEndPage(PdfWriter writer, Document documento){
Rectangle rect = writer.getBoxSize("art");
//header
ColumnText.showTextAligned(writer.getDirectContent(),Element.ALIGN_CENTER, cabecera, rect.getRight(), rect.getTop(), 0);
//footer
ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_CENTER, new Phrase(String.format("Página %d", numeroPagina)), (rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
}
}
Thanks in advance for your help.
Have you set the margins of the Document so that you take into account the height of both header and footer?