How to create a multi-line input box (similar to HTML Textarea)? - itext

I am running the MultiLineField example from this link:
http://developers.itextpdf.com/examples/form-examples-itext5/multiline-fields
However, I am not able to see any multi-line input box that allow people to enter text.
How to can I create a multi-line input box (similar to HTML Textarea)?
UPDATE
Here is the code I have now. I am not able to enter any value in the PDF form.
public void createPdf_multilines(String filename) throws DocumentException, IOException {
PdfReader reader = new PdfReader(createForm());
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(filename));
AcroFields form = stamper.getAcroFields();
form.setField("text", "A B C D E F\nG H I J K L M N\nO P Q R S T U\r\nV W X Y Z\n\nAlphabet street");
stamper.setFormFlattening(true);
stamper.close();
}
public byte[] createForm() throws DocumentException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, baos);
document.open();
Rectangle rect = new Rectangle(36, 770, 144, 806);
TextField tf = new TextField(writer, rect, "text");
tf.setOptions(TextField.MULTILINE);
tf.setBorderColor(BaseColor.BLUE);
tf.setBorderWidth(2);
writer.addAnnotation(tf.getTextField());
document.close();
return baos.toByteArray();
}

This creates a text field that will wrap text when it doesn't fit the width of the text area:
Rectangle rect = new Rectangle(36, 770, 144, 806);
TextField tf = new TextField(writer, rect, "text");
tf.setOptions(TextField.MULTILINE);
tf.setBorderColor(BaseColor.BLUE);
tf.setText("A B C D E F\nG H I J K L M N\nO P Q R S T U\r\nV W X Y Z\n\nAlphabet street");
tf.setBorderWidth(2);
writer.addAnnotation(tf.getTextField());
I have added a border width and a border color, so that you clearly see the field on the page. Maybe that's your problem: maybe the field is there, but you just don't see it.
Note that you shouldn't expect people to be able to resize the field as is possible in HTML. In PDF, all fields have fixed coordinates (in this case 36, 770 and 144, 806). You shouldn't expect PDF forms to behave the same way as HTML forms behave.

Related

Placing Text on Multiple Imported PDF Pages with iTextSharp [duplicate]

I am trying to add a header to existing pdf documents in Java with iText. I can add the header at a fixed place on the document, but all the documents are different page sizes, so it is not always at the top of the page. I have tried getting the page size so that I could calculate the position of the header, but it seems as if the page size is not actually what I want. On some documents, calling reader.getPageSize(i).getTop(20) will place the text in the right place at the top of the page, however, on some different documents it will place it half way down the page. Most of the pages have been scanned be a Xerox copier, if that makes a difference. Here is the code I am using:
PdfReader reader = new PdfReader(readFilePath);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(writeFilePath));
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
PdfContentByte cb = stamper.getOverContent(i);
cb.beginText();
cb.setFontAndSize(bf, 14);
float x = reader.getPageSize(i).getWidth() / 2;
float y = reader.getPageSize(i).getTop(20);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "Copy", x, y, 0);
cb.endText();
}
stamper.close();
PDF that works correctly
PDF that works incorrectly
Take a look at the StampHeader1 example. I adapted your code, introducing ColumnText.showTextAligned() and using a Phrase for the sake of simplicity (maybe you can change that part of your code too):
public void manipulatePdf(String src, String dest) throws IOException, DocumentException {
PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
Phrase header = new Phrase("Copy", new Font(FontFamily.HELVETICA, 14));
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
float x = reader.getPageSize(i).getWidth() / 2;
float y = reader.getPageSize(i).getTop(20);
ColumnText.showTextAligned(
stamper.getOverContent(i), Element.ALIGN_CENTER,
header, x, y, 0);
}
stamper.close();
reader.close();
}
As you have found out, this code assumes that no rotation was defined.
Now take a look at the StampHeader2 example. I'm using your "Wrong" file and I've added one extra line:
stamper.setRotateContents(false);
By telling the stamper not to rotate the content I'm adding, I'm adding the content using the coordinates as if the page isn't rotated. Please take a look at the result: stamped_header2.pdf. We added "Copy" at the top of the page, but as the page is rotated, we see the word appear on the side. The word is rotated because the page is rotated.
Maybe that's what you want, maybe it isn't. If it isn't, please take a look at StampHeader3 in which I calculate x and y differently, based on the rotation of the page:
if (reader.getPageRotation(i) % 180 == 0) {
x = reader.getPageSize(i).getWidth() / 2;
y = reader.getPageSize(i).getTop(20);
}
else {
x = reader.getPageSize(i).getHeight() / 2;
y = reader.getPageSize(i).getRight(20);
}
Now the word "Copy" appears on what is perceived as the "top of the page" (but in reality, it could be the side of the page): stamped_header3.pdf

adding a textbox to the right corner of the existing pdf using ITextSharp in C#

I tiied to add a TextBox to the right corner of the existing pdf using c#, but im unable to get it done. I have wrote the following code,but it is not helping in solving the problem, can any body please suggest me
using (MemoryStream stream = new MemoryStream())
{
PdfReader reader = new PdfReader(bytes);
PdfReader.unethicalreading = true;
Paragraph p = new Paragraph();
Document doc = new Document();
using (PdfStamper stamper = new PdfStamper(reader, stream))
{
PdfContentByte canvas = stamper.GetOverContent(1);
iTextSharp.text.Rectangle size = reader.GetPageSizeWithRotation(1);
//PdfContentByte cb = null;
//PdfImportedPage page;
int pages = reader.NumberOfPages;
for (int i = 1; i <= pages; i++)
{
var size1 = reader.GetPageSize(i);
w = size1.Width;
h = size1.Height;
stamper.FormFlattening = true;
TextField tf = new TextField(stamper.Writer, new iTextSharp.text.Rectangle(0, 0, 300, 100), displaytext);
//Change the orientation of the text
tf.Rotation = 0;
stamper.AddAnnotation(tf.GetTextField(), i);
}
}
bytes = stream.ToArray();
}
File.WriteAllBytes(str, bytes);
As the OP clarified in comments to the question, he wants
to add the text as a page content in the right bottom corner of the page and
the page content previously existing there to be removed.
A simple implementation of this would include
first covering the existing page content with a filled rectangle and
then writing text there.
These tasks can be achieved with these helper methods:
void EmptyTextBoxSimple(PdfStamper stamper, int pageNumber, Rectangle boxArea, BaseColor fillColor)
{
PdfContentByte canvas = stamper.GetOverContent(pageNumber);
canvas.SaveState();
canvas.SetColorFill(fillColor);
canvas.Rectangle(boxArea.Left, boxArea.Bottom, boxArea.Width, boxArea.Height);
canvas.Fill();
canvas.RestoreState();
}
and
ColumnText GenerateTextBox(PdfStamper stamper, int pageNumber, Rectangle boxArea)
{
PdfContentByte canvas = stamper.GetOverContent(pageNumber);
ColumnText columnText = new ColumnText(canvas);
columnText.SetSimpleColumn(boxArea);
return columnText;
}
E.g. like this:
using (PdfReader reader = new PdfReader(source))
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create)))
{
Rectangle cropBox = reader.GetCropBox(1);
Rectangle bottomRight = new Rectangle(cropBox.GetRight(216), cropBox.Bottom, cropBox.Right, cropBox.GetBottom(146));
EmptyTextBoxSimple(stamper, 1, bottomRight, BaseColor.WHITE);
ColumnText columnText = GenerateTextBox(stamper, 1, bottomRight);
columnText.AddText(new Phrase("Some test text to draw into a text box in the lower right corner of the first page"));
columnText.Go();
}
For this source page
the sample code generates this
Addendum
In a comment the OP indicated
it is working for all files but for some pdf files it is displaying in the middle
Eventually he supplied a sample file for which the issue occurs. And indeed, with this file the issue could be reproduced.
The cause for the issue is that the pages in the sample file use page rotation, something that iText (only) partially allows users to ignore. In particular iText automatically rotates text to be upright after rotation and transforms coordinates, but when retrieving the cropbox of a page, one still has to apply rotation before making use of it coordinates. Thus, a more complete example would be like this:
using (PdfReader reader = new PdfReader(source))
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create)))
{
Rectangle cropBox = reader.GetCropBox(1);
int rotation = reader.GetPageRotation(1);
while (rotation > 0)
{
cropBox = cropBox.Rotate();
rotation -= 90;
}
Rectangle bottomRight = new Rectangle(cropBox.GetRight(216), cropBox.Bottom, cropBox.Right, cropBox.GetBottom(146));
EmptyTextBoxSimple(stamper, 1, bottomRight, BaseColor.WHITE);
ColumnText columnText = GenerateTextBox(stamper, 1, bottomRight);
columnText.AddText(new Phrase("Some test text to draw into a text box in the lower right corner of the first page"));
columnText.Go();
}

iTextSharp centering text on page

I cannot get the text to be centered on the page. What am I doing wrong? I have tried several ways to get the page with, but none seem to make the text centered on the page.....
BaseFont bf = BaseFont.CreateFont("c:\\windows\\fonts\\calibri.ttf", BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfReader reader = new PdfReader("C:\\temp\\Certificate12.pdf");
var pageSize = reader.GetPageSize(1);
iTextSharp.text.Rectangle rec2 = new iTextSharp.text.Rectangle(PageSize.LETTER);
PdfStamper stamper = new PdfStamper(reader, stream1);
PdfContentByte canvas = stamper.GetUnderContent(1);
canvas.BeginText();
canvas.SetFontAndSize(bf, 24);
string nameText = "First Name Last Name";
int textWidth = (int)nameText.Length;
int canvasWidth = (int)canvas.PdfDocument.PageSize.Width;
float xStart = (canvasWidth / 2) - (textWidth / 2);
canvas.ShowTextAligned(PdfContentByte.ALIGN_CENTER, nameText, xStart, pageSize.GetTop(Utilities.MillimetersToPoints(145)), 0);
First of all, if you use ShowTextAligned with ALIGN_CENTER, iTextSharp will center the text for you, so you do not have to deal with the text width at all. You merely need to tell it to center the text on which center point.
Thus, you can center your text on the page like this:
BaseFont bf = BaseFont.CreateFont("c:\\windows\\fonts\\calibri.ttf", BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
using (PdfReader reader = new PdfReader(source))
using (PdfStamper stamper = new PdfStamper(reader, new FileStream(dest, FileMode.Create, FileAccess.Write)))
{
Rectangle pageSize = reader.GetPageSize(1);
PdfContentByte canvas = stamper.GetUnderContent(1);
string nameText = "First Name Last Name";
canvas.BeginText();
canvas.SetFontAndSize(bf, 24);
canvas.ShowTextAligned(PdfContentByte.ALIGN_CENTER, nameText, (pageSize.Left + pageSize.Right) / 2, pageSize.GetTop(Utilities.MillimetersToPoints(145)), 0);
canvas.EndText();
}

Using ColumnText results in "The document has no pages" exception

I want to wrap text in a rect which is below (or left or right) of a image as below :
Please see link : http://upanh.in/SLk/
I use ColumnText for wrapping text in my code:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/pdf");
try {
// step 1
Document document = new Document(PageSize.A4.rotate());
// step 2
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(document, baos);
// step 3
document.open();
// step 4
ColumnText column = new ColumnText(writer.getDirectContent());
column.setSimpleColumn(new Phrase("text is very long ..."), 10, 10, 20, 20, 18, Element.ALIGN_CENTER);
column.go();
// step 5
document.close();
ServletOutputStream os = response.getOutputStream();
baos.writeTo(os);
os.flush();
os.close();
} catch (DocumentException e) {
throw new IOException(e.getMessage());
}
}
Result:
ExceptionConverter: java.io.IOException: The document has no pages.
Do you have any suggestions how to fix that?
Question 2
I try to display text (center and middle) in the rect with below code but it wasn't success. The text was only center in the rect.
ColumnText column = new ColumnText(writer.getDirectContent());
column.setSimpleColumn(RectImg1[0], RectImg1[1], RectImg1[0] + squareHeight, RectImg1[1] + squareHeight
* 1 / 4);
Paragraph p = new Paragraph(imgr.getText(), fontH);
p.setAlignment(Element.ALIGN_CENTER | Element.ALIGN_MIDDLE);
p.setLeading(18);
column.addElement(p);
column.go();
where was my mistake ?
I have edited the title of your question because it was misleading: the exception you encounter will occur in a standalone application too. The fact that you are using the code in a Servlet is irrelevant.
I see that you have the following line:
column.go();
You did not use something like this:
int status = column.go();
If you did, and if you examined status, you would have noticed that the column object still contained some text.
What text? All the text.
There is a serious error in this line:
column.setSimpleColumn(new Phrase("text is very long ..."), 10, 10, 20, 20, 18, Element.ALIGN_CENTER);
You are trying to add the text "text is very long ..." into a rectangle with the following coordinates:
float llx = 10;
float lly = 10;
float urx = 20;
float ury = 20;
You didn't define a font, so the font is Helvetica with font size 12pt and you defined a leading of 18pt.
This means that you are trying to fit text that is 12pt high with an extra 6pt for the leading into a square that measures 10 by 10 pt. Surely you understand that this can't work!
As a result, nothing is added to the PDF and rather than showing an empty page, iText throws an exception saying: there are no pages! You didn't add any content to the document!
You can fix this, for instance by changing the incorrect line into something like this:
column.setSimpleColumn(new Phrase("text is very long ..."), 36, 36, 559, 806, 18, Element.ALIGN_CENTER);
An alternative would be:
column.setSimpleColumn(rect);
column.addElement(paragraph);
In these two lines rect is a Rectangle object. The leading and the alignment are to be defined at the level of the Paragraph object (in this case, you don't use a Phrase).

iTextSharp ColumnText.SetSimpleColumn Addtext causes Error in Adobe Reader X 10.1.5

The code below illustrates a problem I have with iTextSharp. Everything works perfectly. The pdf file is created and appears correct on the screen. When I print the pdf from Adobe Reader X, it looks exactly right but Adobe reports "An error exists on this page. Acrobat may not display the page correctly. Please contact the person who created the PDF document to correct the problem."
Unfortunately, the file has to be attached to an email and sent to clients. The error message is not a good look and I want to fix it. It happens in all versions of Reader that I have tried, including 10.1.15 installed today.
I have iTextSharp 5.3.4.0 under Windows 7 Pro SP1
private void writeTestDoc()
{
string fname = "test.pdf";
float textWidth = 500;
float leftMgn = 60;
float rubricTop = 720;
float leftPad = 5;
float topPad = 12;
float leading = 0;
BaseFont baseCalibri = BaseFont.CreateFont("c:/windows/fonts/calibri.ttf", BaseFont.WINANSI, true);
Font plainFont = new Font(baseCalibri, 11, Font.NORMAL);
Document document = new Document();
try
{
PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(fname, FileMode.Create));
document.Open();
PdfContentByte cb = writer.DirectContent;
cb.BeginText();
ColumnText ct = new ColumnText(cb);
float boxTop = rubricTop;
ct.SetSimpleColumn(leftMgn + leftPad, boxTop - topPad, leftMgn + textWidth, boxTop, leading, Element.ALIGN_CENTER);
ct.AddText(new Phrase("A test message", plainFont));
ct.Go();
cb.EndText();
document.Close();
}
catch (Exception ex)
{
writeFile("ERROR in writeTestDoc " + ex.Message);
}
}
Remove cb.BeginText(); and cb.EndText();. It's illegal for BT/ET text objects to be nested. Report the place where you've found the documentation that told you to use BeginText()/EndText in combination with ColumnText, so that we can ask the author to correct it from his or her documentation.