Is it possible to remove all text occurrences contained in a specified area(red color rectangle area) of a pdf document Using iText?
Please take a look at the RemoveContentInRectangle example.
Let's say we have the following page:
Now we want to remove all the text in the rectangle defined by the coordinates: llx = 97, lly = 405, urx = 480, ury = 445] (where ll stands for lower-left and ur stands for upper-right).
We can now use the following code:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
List<PdfCleanUpLocation> cleanUpLocations = new ArrayList<PdfCleanUpLocation>();
cleanUpLocations.add(new PdfCleanUpLocation(1, new Rectangle(97f, 405f, 480f, 445f), BaseColor.GRAY));
PdfCleanUpProcessor cleaner = new PdfCleanUpProcessor(cleanUpLocations, stamper);
cleaner.cleanUp();
stamper.close();
reader.close();
}
As you see, we define a list of PdfCleanUpLocation objects. To this list, we add a PdfCleanUpLocation passing the page number, a Rectangle defining the area we want to clean up, and a color that will show the area where content has been removed.
We then pass this list of PdfCleanUpLocations to the PdfCleanUpProcessor along with the PdfStamper instance. We invoke the cleanUp() method and when we close the PdfStamper instance, we get the following result:
You can inspect this file: you will no longer be able to select any text in the gray area. All the text inside that rectangle has been removed.
Note that this code sample will only work if you add the itext-xtra.jar to your CLASSPATH (itext-xtra is shipped with iText core). It will only work with versions equal to or higher than iText 5.5.4.
Related
I want to add a variable string to a fixed drawing rectangle using iText 7 - this is a sample code:
try (PdfWriter writer = new PdfWriter("test.pdf");
PdfDocument pdf = new PdfDocument(writer)) {
// Create a page
PdfPage currentPage = pdf.addNewPage(PageSize.A4);
// Create the position rectangle
Rectangle rect = new Rectangle(
75f,
currentPage.getPageSize().getHeight() - 315f - 22f,
75f,
22f
);
// Create the font
PdfFont currentFont = PdfFontFactory.createFont(
"Helvetica",
"Cp1252"
);
// Create the paragraph
Paragraph p = (new Paragraph("Some longer value"))
.setFont(currentFont)
.setFontSize(12f)
.setWidth(75f)
.setHeight(22f)
.setTextAlignment(TextAlignment.LEFT);
// Add the paragraph
(new Canvas(new PdfCanvas(currentPage), pdf, rect))
.add((BlockElement)p);
}
When I run this code, I'll get this exception when the last line is being executed:
Exception in thread "main" java.lang.IllegalArgumentException: fromIndex(0) > toIndex(-1)
at java.base/java.util.AbstractList.subListRangeCheck(AbstractList.java:509)
at java.base/java.util.ArrayList.subList(ArrayList.java:1138)
at com.itextpdf.layout.renderer.ParagraphRenderer.layout(ParagraphRenderer.java:235)
at com.itextpdf.layout.renderer.RootRenderer.addChild(RootRenderer.java:84)
at com.itextpdf.layout.renderer.CanvasRenderer.addChild(CanvasRenderer.java:86)
at com.itextpdf.layout.RootElement.add(RootElement.java:98)
at itext.bug.reproduce.ITextBugReproduce.main(ITextBugReproduce.java:50)
When I replace Some longer value with test, everything works. So it seems adding an overlength string to a small drawing area fails.
The problem is: In real know only the destination drawing area, but I don't know the string which is going to be processed. This leads to my question: How can I draw even an overlength string to the PDF without pre-measuring etc.?
Update: When I expand the paragraph dimensions, I still have the same exception, so I assume its not a problem with the paragraph, but with the canvas which I use to restrict drawing to the destination rectangle (for not overwriting any contents outside of the rectangle).
With a newer iText 7 version (I used 7.0.1 before) and a slightly different code it's working now:
BasicConfigurator.configure();// Satisfy the logger
try (PdfWriter writer = new PdfWriter("test.pdf");
PdfDocument pdf = new PdfDocument(writer)) {
// Create a page
PdfPage currentPage = pdf.addNewPage(PageSize.A4);
// Create the position rectangle
Rectangle rect = new Rectangle(
75f,
currentPage.getPageSize().getHeight() - 315f - 22f,
75f,
22f
);
// Create the font
PdfFont currentFont = PdfFontFactory.createFont(
"Helvetica",
"Cp1252"
);
// Create the paragraph
Paragraph p = (new Paragraph("Some longer value"))
.setFont(currentFont)
.setFontSize(12f)
.setWidth(75f)
.setHeight(22f)
.setTextAlignment(TextAlignment.LEFT);
// Override the renderer
p.setNextRenderer(new ParagraphRenderer(p){
#Override
public List initElementAreas(LayoutArea area) {
List list = new ArrayList();
list.add(rect);
return list;
}
});
// Add the paragraph
(new Canvas(new PdfCanvas(currentPage), rect))
.add((BlockElement)p);
I have existed pdf template
Now I want to add some text to this file, so I did that:
PdfReader reader = new PdfReader(path + PdfCreator.TEMPORARY);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(path + PdfCreator.DEST));
PdfContentByte canvasBookingDate = stamper.getOverContent(1);
//add text "Hellow"
canvasBookingDate.setFontAndSize(base, 9.5f);
canvasBookingDate.moveText(72f, 788f);
canvasBookingDate.showText("Hello");
canvasBookingDate.moveText(72f, 762f);
//add text "How are you"
canvasBookingDate.setFontAndSize(base, 9.5f);
canvasBookingDate.showText("How are you");
canvasBookingDate.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
The problem is that, only "Hello" was inserted to pdf file, "How are you" was not
Maybe I wrong something there?
I also using seperate PdfContentByte object to write each text but no luck
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(path + PdfCreator.DEST));
PdfContentByte canvasBookingDate = stamper.getOverContent(1);
//add text "Hellow"
canvasBookingDate.setFontAndSize(base, 9.5f);
canvasBookingDate.moveText(72f, 788f);
canvasBookingDate.showText("Hello");
canvasBookingDate.moveText(72f, 762f);
//add text "How are you"
PdfContentByte canvasPlanName2 = stamper.getOverContent(1);
canvasPlanName2.setFontAndSize(base, 9.5f);
canvasPlanName2.moveText(72f, 762f);
canvasPlanName2.showText(entity.getPlanName());
canvasPlanName2.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
The problem is that, only "Hello" was inserted to pdf file, "How are you" was not
Your observation is inaccurate: "How are you" was inserted, merely far off-page! (Doing CtrlA CtrlC from adobe reader and pasting into some editor you would have seen that it is there somewhere.)
The cause is that you misunderstand how moveText works. Have a look at its JavaDoc documentation:
/**
* Moves to the start of the next line, offset from the start of the current line.
*
* #param x x-coordinate of the new current point
* #param y y-coordinate of the new current point
*/
public void moveText(final float x, final float y)
Thus, the coordinates are relative, not absolute!
So you should do
canvasBookingDate.beginText();
canvasBookingDate.setFontAndSize(base, 9.5f);
canvasBookingDate.moveText(72f, 788f);
canvasBookingDate.showText("Hello");
canvasBookingDate.moveText(0f, -16f);
//add text "How are you"
canvasBookingDate.showText("How are you");
canvasBookingDate.endText();
I found answer from Vishal Kawade link
Just using beginText() and endText() after each text need insert to pdf
I have a PDF File (ex:Hello.pdf) and what i need to do with this PDF is Read the file and get text content and replace the text with HashMap Values (If find the key in Text)
ex:- If PDF Content Text is (My Name is [Name])
and hashMap Key "Name":"Vikrant" Then overwrite this as
"My Name is Vikrant" and write it to the PDF.
I have Tried iTextPDF Jar but still won't got any logical Solution.
/* example inspired from "iText in action" (2006), chapter 2 */
PdfReader reader = new PdfReader("D:/HelloWorld.pdf"); // input PDF
PdfStamper stamper = new PdfStamper(reader,
new FileOutputStream("D:/Bubi_modified.pdf")); // output PDF
BaseFont bf = BaseFont.createFont(
BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); // set font
//loop on pages (1-based)
for (int i=1; i<=reader.getNumberOfPages(); i++){
// get object for writing over the existing content;
// you can also use getUnderContent for writing in the bottom layer
PdfContentByte over = stamper.getOverContent(i);
// write text
over.beginText();
over.setFontAndSize(bf, 10); // set font and size
over.setTextMatrix(107, 740); // set x,y position (0,0 is at the bottom left)
over.showText("I can write at page " + i); // set text
over.endText();
// draw a red circle
over.setRGBColorStroke(0xFF, 0x00, 0x00);
over.setLineWidth(5f);
over.ellipse(250, 450, 350, 550);
over.stroke();
}
stamper.close();
}
I have Tried PDFStamper(iTextPDF.jar) But this class can put the content to the pdf not edit the earlier Text or Image.
This question already has an answer here:
How to add overlay text with link annotations to existing pdf?
(1 answer)
Closed 7 years ago.
Two questions,
How to hide or set color white to Rectangle box border
How to add text to Rectangle
public void addLinkedtoTOC(String src, String dest,String IMG,int linkedPageNumber,int linkDisplayTOCPageNumber) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
Rectangle linkLocation = new Rectangle(320, 695, 560, 741);
linkLocation.setBorderColorLeft(BaseColor.WHITE);
linkLocation.setBorderColorRight(BaseColor.RED);
linkLocation.setBorderColorTop(BaseColor.RED);
PdfDestination destination = new PdfDestination(PdfDestination.FIT);
PdfAnnotation link = PdfAnnotation.createLink(stamper.getWriter(), linkLocation, PdfAnnotation.HIGHLIGHT_INVERT,linkedPageNumber, destination);
stamper.addAnnotation(link, linkDisplayTOCPageNumber);
stamper.close();
reader.close();
}
Your first question is easy. It's a duplicate of iText - How to stamp image on existing PDF and create an anchor
When you create a PdfAnnotation object that represents a link annotation, a border is defined by default. You can remove this border using the setBorder() method at the level of the annotation as is done in the AddImageLink example:
link.setBorder(new PdfBorderArray(0, 0, 0));
Your second question has also been answered before. See for instance:
How to add text at an absolute position on the top of the first page?
How to add text inside a rectangle?
How to truncate text within a bounding box?
How to fit a String inside a rectangle?
I have combined both in the AddLinkAnnotation5 example:
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
// Here we define the location:
Rectangle linkLocation = new Rectangle(320, 695, 560, 741);
// here we add the actual content at this location:
ColumnText ct = new ColumnText(stamper.getOverContent(1));
ct.setSimpleColumn(linkLocation);
ct.addElement(new Paragraph("This is a link. Click it and you'll be forwarded to another page in this document."));
ct.go();
// now we create the link that will jump to a specific destination:
PdfDestination destination = new PdfDestination(PdfDestination.FIT);
PdfAnnotation link = PdfAnnotation.createLink(stamper.getWriter(),
linkLocation, PdfAnnotation.HIGHLIGHT_INVERT,
3, destination);
// If you don't want a border, here's where you remove it:
link.setBorder(new PdfBorderArray(0, 0, 0));
// We add the link (that is the clickable area, not the text!)
stamper.addAnnotation(link, 1);
stamper.close();
reader.close();
}
However, there's also another way to add the text and the link annotation at the same time. That's explained in my answer to the duplicate question: How to add overlay text with link annotations to existing pdf?
In this answer, I refer to the AddLinkAnnotation2 example, where we add the content using ColumnText as described above, but we introduce a clickable Chunk:
Chunk chunk = new Chunk("The Best iText Questions on StackOverflow", bold);
chunk.setAnchor("http://developers.itextpdf.com/frequently-asked-developer-questions");
Wrap the chunk object inside a Paragraph, add the Paragraph using ColumnText and you have your borderless link.
I have two parts to my java project.
I need to populate the fields of a pdf
I need to add a table below the populated section on the blank area of the page (and this table needs to be able to rollover to the next page).
I am able to do these things separately (populate the pdf and create a table). But I cannot effectively merge them. I have tried doing a doc.add(table) which will result in the table being on the next page of the pdf, which I don't want.
I essentially just need to be able to specify where the table starts on the page (so it wouldn't overlap the existing content) and then stamp the table onto the existing pdf.
My other option if this doesn't work is trying to add fields to the original pdf that will be filled by the table contents (so it will instead be a field-based table).
Any suggestions?
EDIT:
I'm new to iText and have not used columntext before, but I'm trying to test it out in the following code but the table is not being displayed. I looked at other columntext examples and I have not seen exactly where the columntext is added back into the pdf.
//CREATE FILLED FORM PDF
PdfReader reader = new PdfReader(sourcePath);
PdfStamper pdfStamper = new PdfStamper(reader, new FileOutputStream(destPath));
pdfStamper.setFormFlattening(true);
AcroFields form = pdfStamper.getAcroFields();
form.setField("ID", "99999");
form.setField("ADDR1", "425 Test Street");
form.setField("ADDR2", "Test, WA 91334");
form.setField("PHNBR", "(999)999-9999");
form.setField("NAME", "John Smith");
//CREATE TABLE
PdfPTable table = new PdfPTable(3);
Font bfBold12 = new Font(FontFamily.HELVETICA, 12, Font.BOLD, new BaseColor(0, 0, 0));
insertCell(table, "Table", Element.ALIGN_CENTER, 1, bfBold12);
table.completeRow();
ColumnText column = new ColumnText(pdfStamper.getOverContent(1));
column.addElement(table);
pdfStamper.close();
reader.close();
Please take a look at the AddExtraTable example. It's a simplification of the AddExtraPage example written in answer to the question How to continue field output on a second page?
That question is almost an exact duplicate of your question, with as only difference the fact that your requirement is easier to achieve.
I simplified the code like this:
public void manipulatePdf(String src, String dest) throws DocumentException, IOException {
PdfReader reader = new PdfReader(src);
Rectangle pagesize = reader.getPageSize(1);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
AcroFields form = stamper.getAcroFields();
form.setField("Name", "Jennifer");
form.setField("Company", "iText's next customer");
form.setField("Country", "No Man's Land");
PdfPTable table = new PdfPTable(2);
table.addCell("#");
table.addCell("description");
table.setHeaderRows(1);
table.setWidths(new int[]{ 1, 15 });
for (int i = 1; i <= 150; i++) {
table.addCell(String.valueOf(i));
table.addCell("test " + i);
}
ColumnText column = new ColumnText(stamper.getOverContent(1));
Rectangle rectPage1 = new Rectangle(36, 36, 559, 540);
column.setSimpleColumn(rectPage1);
column.addElement(table);
int pagecount = 1;
Rectangle rectPage2 = new Rectangle(36, 36, 559, 806);
int status = column.go();
while (ColumnText.hasMoreText(status)) {
status = triggerNewPage(stamper, pagesize, column, rectPage2, ++pagecount);
}
stamper.setFormFlattening(true);
stamper.close();
reader.close();
}
public int triggerNewPage(PdfStamper stamper, Rectangle pagesize, ColumnText column, Rectangle rect, int pagecount) throws DocumentException {
stamper.insertPage(pagecount, pagesize);
PdfContentByte canvas = stamper.getOverContent(pagecount);
column.setCanvas(canvas);
column.setSimpleColumn(rect);
return column.go();
}
As you can see, the main differences are:
We create a rectPage1 for the first page and a rectPage2 for page 2 and all pages that follow. That's because we don't need a full page on the first page.
We don't need to load a PdfImportedPage, instead we're just adding blank pages of the same size as the first page.
Possible improvements: I hardcoded the Rectangle instances. It goes without saying that rect1Page depends on the location of your original form. I also hardcoded rect2Page. If I had more time, I would calculate rect2Page based on the pagesize value.
See the following questions and answers of the official FAQ:
How to add a table on a form (and maybe insert a new page)?
How to continue field output on a second page?