I want to do the following with iText:
(1) parse an existing PDF file
(2) add some data to it, on the existing single page of the document (such as a timestamp)
(3) write out the document
I just can't seem to figure out how to do this with iText. In pseudo code I would do this:
Document document = reader.read(input);
document.add(new Paragraph("my timestamp"));
writer.write(document, output);
But for some reason iText's API is so dauntingly complicated that I can't wrap my head around it. The PdfReader actually holds the document model or something (rather than spitting out a document), and you need a PdfWriter to read pages from it... eh?
iText has more than one way of doing this. The PdfStamper class is one option. But I find the easiest method is to create a new PDF document then import individual pages from the existing document into the new PDF.
// Create output PDF
Document document = new Document(PageSize.A4);
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cb = writer.getDirectContent();
// Load existing PDF
PdfReader reader = new PdfReader(templateInputStream);
PdfImportedPage page = writer.getImportedPage(reader, 1);
// Copy first page of existing PDF into output PDF
document.newPage();
cb.addTemplate(page, 0, 0);
// Add your new data / text here
// for example...
document.add(new Paragraph("my timestamp"));
document.close();
This will read in a PDF from templateInputStream and write it out to outputStream. These might be file streams or memory streams or whatever suits your application.
Gutch's code is close, but it'll only work right if:
There are no annotations (links, fields, etc), no Document Structure/Marked Content, no bookmarks, no document-level script, etc, etc, etc...
The page size happens to be A.4 (decent odds, but it won't work on any ol' PDF you happen to come across)
You don't mind losing all the original document metadata (producer, creation date, possibly author/title/keywords), and maybe the document ID. You can't copy the creation date and doc ID unless you do some pretty deep hackery on iText itself).
The Approved Method is to do it the other way around. Open the existing document with a PdfStamper, and use the returned PdfContentByte from getOverContent() to write text (and whatever else you might need) directly to the page. No second document needed.
And you can use a ColumnText to handle layout and such for you... no need to get down and dirty with beginText(),setFontAndSize(),drawText(),drawText()...,endText().
This is the most complicated scenario I can imagine: I have a PDF file created with Ilustrator and modified with Acrobat to have AcroFields (AcroForm) that I'm going to fill with data with this Java code, the result of that PDF file with the data in the fields is modified adding a Document.
Actually in this case I'm dynamically generating a background that is added to a PDF that is also dynamically generated with a Document with an unknown amount of data or pages.
I'm using JBoss and this code is inside a JSP file (should work in any JSP webserver).
Note: if you are using IExplorer you must submit a HTTP form with POST method to be able to download the file. If not you are going to see the PDF code in the screen. This does not happen in Chrome or Firefox.
<%# page import="java.io.*, com.lowagie.text.*, com.lowagie.text.pdf.*" %><%
response.setContentType("application/download");
response.setHeader("Content-disposition","attachment;filename=listaPrecios.pdf" );
// -------- FIRST THE PDF WITH THE INFO ----------
String str = "";
// lots of words
for(int i = 0; i < 800; i++) str += "Hello" + i + " ";
// the document
Document doc = new Document( PageSize.A4, 25, 25, 200, 70 );
ByteArrayOutputStream streamDoc = new ByteArrayOutputStream();
PdfWriter.getInstance( doc, streamDoc );
// lets start filling with info
doc.open();
doc.add(new Paragraph(str));
doc.close();
// the beauty of this is the PDF will have all the pages it needs
PdfReader frente = new PdfReader(streamDoc.toByteArray());
PdfStamper stamperDoc = new PdfStamper( frente, response.getOutputStream());
// -------- THE BACKGROUND PDF FILE -------
// in JBoss the file has to be in webinf/classes to be readed this way
PdfReader fondo = new PdfReader("listaPrecios.pdf");
ByteArrayOutputStream streamFondo = new ByteArrayOutputStream();
PdfStamper stamperFondo = new PdfStamper( fondo, streamFondo);
// the acroform
AcroFields form = stamperFondo.getAcroFields();
// the fields
form.setField("nombre","Avicultura");
form.setField("descripcion","Esto describe para que sirve la lista ");
stamperFondo.setFormFlattening(true);
stamperFondo.close();
// our background is ready
PdfReader fondoEstampado = new PdfReader( streamFondo.toByteArray() );
// ---- ADDING THE BACKGROUND TO EACH DATA PAGE ---------
PdfImportedPage pagina = stamperDoc.getImportedPage(fondoEstampado,1);
int n = frente.getNumberOfPages();
PdfContentByte background;
for (int i = 1; i <= n; i++) {
background = stamperDoc.getUnderContent(i);
background.addTemplate(pagina, 0, 0);
}
// after this everithing will be written in response.getOutputStream()
stamperDoc.close();
%>
There is another solution much simpler, and solves your problem. It depends the amount of text you want to add.
// read the file
PdfReader fondo = new PdfReader("listaPrecios.pdf");
PdfStamper stamper = new PdfStamper( fondo, response.getOutputStream());
PdfContentByte content = stamper.getOverContent(1);
// add text
ColumnText ct = new ColumnText( content );
// this are the coordinates where you want to add text
// if the text does not fit inside it will be cropped
ct.setSimpleColumn(50,500,500,50);
ct.setText(new Phrase(str, titulo1));
ct.go();
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("E:/TextFieldForm.pdf"));
document.open();
PdfPTable table = new PdfPTable(2);
table.getDefaultCell().setPadding(5f); // Code 1
table.setHorizontalAlignment(Element.ALIGN_LEFT);
PdfPCell cell;
// Code 2, add name TextField
table.addCell("Name");
TextField nameField = new TextField(writer,
new Rectangle(0,0,200,10), "nameField");
nameField.setBackgroundColor(Color.WHITE);
nameField.setBorderColor(Color.BLACK);
nameField.setBorderWidth(1);
nameField.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
nameField.setText("");
nameField.setAlignment(Element.ALIGN_LEFT);
nameField.setOptions(TextField.REQUIRED);
cell = new PdfPCell();
cell.setMinimumHeight(10);
cell.setCellEvent(new FieldCell(nameField.getTextField(),
200, writer));
table.addCell(cell);
// force upper case javascript
writer.addJavaScript(
"var nameField = this.getField('nameField');" +
"nameField.setAction('Keystroke'," +
"'forceUpperCase()');" +
"" +
"function forceUpperCase(){" +
"if(!event.willCommit)event.change = " +
"event.change.toUpperCase();" +
"}");
// Code 3, add empty row
table.addCell("");
table.addCell("");
// Code 4, add age TextField
table.addCell("Age");
TextField ageComb = new TextField(writer, new Rectangle(0,
0, 30, 10), "ageField");
ageComb.setBorderColor(Color.BLACK);
ageComb.setBorderWidth(1);
ageComb.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
ageComb.setText("12");
ageComb.setAlignment(Element.ALIGN_RIGHT);
ageComb.setMaxCharacterLength(2);
ageComb.setOptions(TextField.COMB |
TextField.DO_NOT_SCROLL);
cell = new PdfPCell();
cell.setMinimumHeight(10);
cell.setCellEvent(new FieldCell(ageComb.getTextField(),
30, writer));
table.addCell(cell);
// validate age javascript
writer.addJavaScript(
"var ageField = this.getField('ageField');" +
"ageField.setAction('Validate','checkAge()');" +
"function checkAge(){" +
"if(event.value < 12){" +
"app.alert('Warning! Applicant\\'s age can not" +
" be younger than 12.');" +
"event.value = 12;" +
"}}");
// add empty row
table.addCell("");
table.addCell("");
// Code 5, add age TextField
table.addCell("Comment");
TextField comment = new TextField(writer,
new Rectangle(0, 0,200, 100), "commentField");
comment.setBorderColor(Color.BLACK);
comment.setBorderWidth(1);
comment.setBorderStyle(PdfBorderDictionary.STYLE_SOLID);
comment.setText("");
comment.setOptions(TextField.MULTILINE |
TextField.DO_NOT_SCROLL);
cell = new PdfPCell();
cell.setMinimumHeight(100);
cell.setCellEvent(new FieldCell(comment.getTextField(),
200, writer));
table.addCell(cell);
// check comment characters length javascript
writer.addJavaScript(
"var commentField = " +
"this.getField('commentField');" +
"commentField" +
".setAction('Keystroke','checkLength()');" +
"function checkLength(){" +
"if(!event.willCommit && " +
"event.value.length > 100){" +
"app.alert('Warning! Comment can not " +
"be more than 100 characters.');" +
"event.change = '';" +
"}}");
// add empty row
table.addCell("");
table.addCell("");
// Code 6, add submit button
PushbuttonField submitBtn = new PushbuttonField(writer,
new Rectangle(0, 0, 35, 15),"submitPOST");
submitBtn.setBackgroundColor(Color.GRAY);
submitBtn.
setBorderStyle(PdfBorderDictionary.STYLE_BEVELED);
submitBtn.setText("POST");
submitBtn.setOptions(PushbuttonField.
VISIBLE_BUT_DOES_NOT_PRINT);
PdfFormField submitField = submitBtn.getField();
submitField.setAction(PdfAction
.createSubmitForm("",null, PdfAction.SUBMIT_HTML_FORMAT));
cell = new PdfPCell();
cell.setMinimumHeight(15);
cell.setCellEvent(new FieldCell(submitField, 35, writer));
table.addCell(cell);
// Code 7, add reset button
PushbuttonField resetBtn = new PushbuttonField(writer,
new Rectangle(0, 0, 35, 15), "reset");
resetBtn.setBackgroundColor(Color.GRAY);
resetBtn.setBorderStyle(
PdfBorderDictionary.STYLE_BEVELED);
resetBtn.setText("RESET");
resetBtn
.setOptions(
PushbuttonField.VISIBLE_BUT_DOES_NOT_PRINT);
PdfFormField resetField = resetBtn.getField();
resetField.setAction(PdfAction.createResetForm(null, 0));
cell = new PdfPCell();
cell.setMinimumHeight(15);
cell.setCellEvent(new FieldCell(resetField, 35, writer));
table.addCell(cell);
document.add(table);
document.close();
}
class FieldCell implements PdfPCellEvent{
PdfFormField formField;
PdfWriter writer;
int width;
public FieldCell(PdfFormField formField, int width,
PdfWriter writer){
this.formField = formField;
this.width = width;
this.writer = writer;
}
public void cellLayout(PdfPCell cell, Rectangle rect,
PdfContentByte[] canvas){
try{
// delete cell border
PdfContentByte cb = canvas[PdfPTable
.LINECANVAS];
cb.reset();
formField.setWidget(
new Rectangle(rect.left(),
rect.bottom(),
rect.left()+width,
rect.top()),
PdfAnnotation
.HIGHLIGHT_NONE);
writer.addAnnotation(formField);
}catch(Exception e){
System.out.println(e);
}
}
}
how-to-update-a-pdf-without-creating-a-new-pdf
iText 7, please pay attention to version
PdfReader reader = new PdfReader(src);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
//manipulate pdf…
pdfDoc.close();
Related
I have two PDF files A and B, I have a requirement where i need to Merge both these PDF files based on a condition.Like,If i find a string like "attach PDF" in my A, i have to merge the B file into A from that particular page in A. For Example,If i spot the word in Page No 3 in my A file I need to merge the B file from Page No:3. I'm using I-Text 5.5.10. Is it possible to achieve this in I-Text or PDFBox. Here is what i have tried as of now.
public static void mergePdf() throws IOException, DocumentException
{
PdfReader reader1 = new PdfReader("C:\\Users\\user1\\Downloads\\generatedSample.pdf");
PdfReader reader2 = new PdfReader("C:\\Users\\user1\\Desktop\\sample1.pdf");
Document document = new Document();
document.addHeader("Header Text", "");
FileOutputStream fos = new FileOutputStream("C:\\Users\\user1\\Downloads\\MergeFile.pdf");
PdfCopy copy = new PdfCopy(document, fos);
document.open();
PdfImportedPage page;
PdfCopy.PageStamp stamp;
Phrase phrase;
BaseFont bf = BaseFont.createFont();
Font font = new Font(bf, 9);
int n = reader1.getNumberOfPages();
for (int i = 1; i <= reader1.getNumberOfPages(); i++)
{
page = copy.getImportedPage(reader1, i);
stamp = copy.createPageStamp(page);
ColumnText.showTextAligned(stamp.getOverContent(), Element.ALIGN_CENTER, null, 520, 5, 0);
stamp.alterContents();
copy.addPage(page);
}
for (int i = 1; i <= reader2.getNumberOfPages(); i++)
{
page = copy.getImportedPage(reader2, i);
stamp = copy.createPageStamp(page);
ColumnText.showTextAligned(stamp.getOverContent(), Element.ALIGN_CENTER, null, 520, 5, 0);
stamp.alterContents();
copy.addPage(page);
}
document.close();
reader1.close();
reader2.close();
}
Thanks for the solution in advance !!
I am creating a PDF file, but have stumbled upon a problem. Below are the iText commands that are causing it.
document.Header = header;
document.Open();
PdfContentByte cb = writer.DirectContentUnder; (getDirectContentUnder() for java)
document is of type Document; writer is a PdfWriter and header is of type HeaderFooter.
iText have same conditions for order of those commands and those are:
PdfWriter cannot be used before opening the document
header of the PDF will not be shown at all, if I open the document before I add the header to it
That would be fine and I would write it in the order just like in the snippet above. But I need the PdfWriter for creating the header. And now I am in a loop:
to create the header, I need to use PdfWriter
to use PdfWriter, I need to open the document first
for the header to be visible, I would need to create it before opening the document
Also, I found sources both for recommending the header to be created as the last thing before opening the document, as well as for recommending the header to be created after the document has been opened. Which is right and how to solve my problem?
Update: Code
BaseFont bf16 = BaseFont.CreateFont( "c:\\windows\\fonts\\Arial.ttf", BaseFont.CP1250, false );
Font fnt10Bold = new Font( bf16, 10, Font.BOLD, new Color( 100, 100, 100 ) );
System.Drawing.Bitmap headerBitmap = Properties.Resources.doc_header;
Image headerImg = Image.GetInstance( headerBitmap, Color.BLACK );
Document document = new Document( PageSize.A4, 36, 40, 20, 20 );
PdfWriter writer = PdfWriter.GetInstance( document, new FileStream( path, FileMode.Create ) );
for ( int i = 0; i < DocList.Count; i++ )
{
PdfPTable tblHeader = new PdfPTable( new float[] { 40, 60 } );
tblHeader.WidthPercentage = 100;
PdfContentByte cb = writer.DirectContentUnder;
Image img = getWatermarkedImage( cb, headerImg, "Watermark", font10Bold );
PdfPCell cellHeader = new PdfPCell( img, true ) { Colspan = 2
HorizontalAlignment = Element.ALIGN_LEFT,
VerticalAlignment = Element.ALIGN_BOTTOM };
tblHeader.AddCell( cellHeader );
Phrase headerPhrase = new Phrase();
headerPhrase.Add( tblHeader );
document.Header = new HeaderFooter( headerPhrase, false );
if ( i == 0 )
document.Open();
else
document.NewPage();
}
document.Close();
getWatermarkedImage is the method from this answer by Bruno Lowagie.
I'm using iText and create a dynamic table which has a a reoccurring header in the method createTabularHeader:
PdfPTable table = new PdfPTable(6);
// fill it with some basic information
table.setHeaderRows(1);
Yet on the first page I would like to display different information. (but the table structure/size remains the same)
Due to the dynamic content which is obtained in a different method I can't say when a new page starts.
I tried with the most primitive variant - just adding a white rectangle over the text and insert the different text. As it's just on the first page all I have to do is creating that rectangle between both methods.
But the white rectangle doesn't have any opacity and can' cover anything.
Yet by trying around I found the method writer.getDirectContent().setColorStroke(BaseColor.WHITE); which set the text to white. Later I just set the BaseColor of my cells manually to black. But the even though the new text is applied after the calling of my createTabularHeader-method its layer is under the layer of the original text and the letters are covering the new text partly.
Using the answer to How to insert invisible text into a PDF? brought me to the idea of using myPdfContentByte.setTextRenderMode(PdfContentByte.TEXT_RENDER_MODE_INVISIBLE); was not so helpful as it resets only on the 2nd page regardless what I do and the regular text on the first page stays invisible.
I'm unable to find a proper solution... How can the table-header be modified only on the first page?
The solution is not really nice, but works... and as some sort of bonus I want to add how you can modify the indentions on the first page.
public void createPdf() {
document = new Document();
try {
PdfWriter writer = PDFHead.getWriter(document);
//If it's a letter we have a different indention on the top
if (letterPDF) {
document.setMargins(36, 36, 100, 36);
} else {
document.setMargins(36, 36, 36, 36);
}
document.open();
document.add(createTabularContent());
document.close();
} catch (DocumentException | FileNotFoundException ex) {
try {
document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(FILENAME));
document.open();
document.add(new Phrase(ex.getLocalizedMessage()));
document.close();
Logger.getLogger(Etikette.class.getName()).log(Level.SEVERE, null, ex);
} catch (FileNotFoundException | DocumentException ex1) {
Logger.getLogger(Etikette.class.getName()).log(Level.SEVERE, null, ex1);
}
}
}
The PDFHead is used to create a regular header (the one which appears on every page, not only on pages with the table):
public static PdfWriter getWriter(Document document) throws FileNotFoundException, DocumentException {
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(filename));
HeaderFooter event = new HeaderFooter("Ing. Mario J. Schwaiger", type + " " + DDMMYYYY.format(new java.util.Date()), 835, isLetterPDF(), customerNumber);
writer.setBoxSize("art", new Rectangle(36, 54, 559, 788));
writer.setPageEvent(event);
return writer;
}
And in that HeaderFooter-Event I use the fact the function is called after the PDF is basically created (for the page number for instance):
#Override
public void onEndPage(PdfWriter writer, Document document) {
if (isLetter) {
//That's only for the first page, apparently 1 is too late
//I'm open for improvements but that works fine for me
if (writer.getPageNumber() == 0) {
//If it's a letter we use the different margins
document.setMargins(36, 36, 100, 36);
}
if (writer.getPageNumber() == 1) {
PdfContentByte canvas = writer.getDirectContent();
float llx = 460;
float lly = 742;
float urx = 36;
float ury = 607;
//As I add the rectangle in the event here it's
//drawn over the table-header. Seems the tableheader
//is rendered afterwards
Rectangle rect1 = new Rectangle(llx, lly, urx, ury);
rect1.setBackgroundColor(BaseColor.WHITE);
rect1.setBorder(Rectangle.NO_BORDER);
rect1.setBorderWidth(1);
canvas.rectangle(rect1);
ColumnText ct = new ColumnText(canvas);
ct.setSimpleColumn(rect1);
PdfPTable minitable = new PdfPTable(1);
PdfPCell cell = PDFKopf.getKundenCol(PDFHeader.getCustomer(customerNumber));
cell.setBorder(Rectangle.NO_BORDER);
minitable.addCell(cell);
//A single cell is not accepted as an "Element"
//But a table including only a single cell is
ct.addElement(minitable);
try {
ct.go();
} catch (DocumentException ex) {
Logger.getLogger(HeaderFooter.class.getName()).log(Level.SEVERE, null, ex);
}
//In any other case we reset the margins back to normal
//This could be solved in a more intelligent way, feel free
} else {
document.setMargins(36, 36, 36, 36);
}
}
//The regular header of any page...
PdfPTable table = new PdfPTable(4);
try {
table.setWidths(new int[]{16, 16, 16, 2});
table.setWidthPercentage(100);
table.setTotalWidth(527);
table.setLockedWidth(true);
table.getDefaultCell().setFixedHeight(20);
table.getDefaultCell().setBorder(Rectangle.BOTTOM);
table.addCell(header);
PdfPCell cell;
cell = new PdfPCell(new Phrase(mittelteil));
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setBorder(Rectangle.BOTTOM);
table.addCell(cell);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
table.addCell(String.format("Page %d of ", writer.getPageNumber()));
cell = new PdfPCell(Image.getInstance(total));
cell.setBorder(Rectangle.BOTTOM);
table.addCell(cell);
table.writeSelectedRows(0, -1, 34, y, writer.getDirectContent());
} catch (DocumentException de) {
throw new ExceptionConverter(de);
}
}
I run the following code for an HTML file with Tables.
I am able to convert HTML to PDF for first page with margins all sides.
But as I do document.newPage(); and apply document.setPageSize(); its not working. Margins are not present.
PDF is borderless, without any margins.
Pls guide.
Code:
public class Potrait_ParseHtmlObjects {
public static final String HTML = "C:/h.html";
public static final String DEST = "C:/test33.pdf";
public void createPdf(String file) {
// Parse HTML into Element list
try{
XMLWorkerHelper helper = XMLWorkerHelper.getInstance();
// CSS
CSSResolver cssResolver = helper.getDefaultCssResolver(true);
CssFile cssFile = helper.getCSS(new FileInputStream("D:\\Itext_Test\\Test\\src\\test.css"));
cssResolver.addCss(cssFile);
// HTML
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
htmlContext.autoBookmark(false);
//mycode starts
FontFactory.registerDirectories();
//mycode ends
// Pipelines
ElementList elements = new ElementList();
ElementHandlerPipeline end = new ElementHandlerPipeline(elements, null);
HtmlPipeline html = new HtmlPipeline(htmlContext, end);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
// XML Worker
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
//mycode starts
p.parse(new FileInputStream(HTML),Charset.forName("UTF-8"));//changed for Charset Encoding
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
writer.setInitialLeading(12.5f);
// step 3
document.open();
// step 4
Rectangle left = new Rectangle(33,33,550,770);
document.setPageSize(left);
System.out.println("1"+document.getPageSize());
ColumnText column = new ColumnText(writer.getDirectContent());
column.setSimpleColumn(left);
int runDirection = PdfWriter.RUN_DIRECTION_LTR;
column.setRunDirection(runDirection);
int status = ColumnText.START_COLUMN;
for (Element e : elements) {
if (e instanceof PdfPTable) {
PdfPTable table = (PdfPTable) e;
for (PdfPRow row : table.getRows()) {
for (PdfPCell cell : row.getCells()) {
if(cell!=null)
cell.setRunDirection(runDirection);
}
}
}
if (ColumnText.isAllowedElement(e)) {
column.addElement(e);
status = column.go();
while (ColumnText.hasMoreText(status)) {
Rectangle left1 = new Rectangle(50,50,500,700);
document.newPage();
document.setPageSize(left1);
column.setSimpleColumn(left1);
status = column.go();
}
}
}
// step 5
document.close();
}catch(Exception ex)
{ex.printStackTrace();}
}
/**
* Main method
*/
public static void main(String[] args) throws IOException, DocumentException {
File file = new File(DEST);
file.getParentFile().mkdirs();
new Potrait_ParseHtmlObjects().createPdf(DEST);
}
}
You initialize all page parameters when you do document.newPage(), hence changing the page size or margins doesn't make sense after triggering document.newPage(). If you want a different page size (or orientation, or margins), you need to set the values for the page size, orientation and margins before invoking document.newPage() (and before document.open() if you want to change the first page).
For instance: in your case, you should create your document like this:
Document document = new Document(new Rectangle(33,33,550,770));
And you should change the page size like this:
document.setPageSize(left1);
document.newPage();
column.setSimpleColumn(left1);
You don't have any margins because you use the same Rectangle for the page size as for the column. You are creating a PDF of which the coordinate of the lower-left corner is not equal to (0, 0). This isn't illegale, but it's unusual. My guess is that you want to do something like this:
document.setPageSize(new Rectangle(0, 0, 550, 750););
document.newPage();
column.setSimpleColumn(new Rectangle(50,50,500,700));
This will result in a page size of 7.64 by 10.42 inch (550 by 750 pt) and you'll have a margin of 0
69 inches on every side (50 pt).
I am doing html to pdf conversion using iText.
I am already using HTMLWorker class (deprecated) having the following content code:
String htmlString = "<html><body> This is my Project <table width= '50%' border='0' align='left' cellpadding='0' cellspacing='0'><tr><td>{VERTICALTEXT}</td></tr></table></body></html>";
OutputStream file = new FileOutputStream(new File("C:\\Test.pdf"));
Document document = new Document();
PdfWriter.getInstance(document, file);
document.open();
HTMLWorker htmlWorker = new HTMLWorker(document);
htmlWorker.parse(new StringReader(htmlString ));
document.close();
file.close();
}
Now I want to replace {VERTICALTEXT} dynamically with some string.
So I further added the code below:
PdfPTable table = null;
PdfPCell cell;
cell = new PdfPCell(new Phrase("My Vertical Text"));
cell.setRotation(90);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(cell);
String verticalLoc = table.toString(); //this variable should hold the text "My Vertical Text" in 90 degree rotated form.
HashMap<String, String> map = new HashMap<String, String>();
map.put("VERTICALTEXT", verticalLoc);
html = new String(buffer);
for (HashMap.Entry<String, String> e : map.entrySet())
{
String value = e.getValue() != null ? e.getValue():"";
html = html.replace("{" + e.getKey() + "}", value);
}
htmlWorker.parse(new StringReader(htmlStr));
In the Output:
{VERTICALTEXT} is replaced with com.itextpdf.text.pdf.PdfPTable#41d62bcO
Desired Output:
{VERTICALTEXT} should be replaced with My Vertical Text in a 90 degree rotated form.
This is the solution figured out and tested -
Java file relevant code:
static PdfWriter writer;
writer = PdfWriter.getInstance(document, new FileOutputStream(FILE));
document.open();
PdfPTable table = new PdfPTable(2);
PdfPCell cell;
cell = new PdfPCell(new Phrase("My Vertical Text"));
cell.setRotation(90);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
table.addCell(cell);
htmlWorker.parse(new StringReader(htmlStr));
table.setTotalWidth(400f);
table.writeSelectedRows( 0, -1, 80, 330, writer.getDirectContent());
So the magic of method writeSelectedRows worked in placing the table to the (x, y) location.
Where,
x = 80
y = 330
Complete details about writeSelectedRows.
This will help somebody facing the same problems with itext positioning.