I created a PDF with a table inside. I managed to create fields in selected cells by listening to the PdfPCellEvent:
cell.setCellEvent( new PdfPCellEvent() {
#Override
public void cellLayout( PdfPCell pdfPCell,
Rectangle rectangle,
PdfContentByte[] canvas ) {
PdfContentByte pcb = canvas[canvas.length - 1];
PdfWriter writer = pcb.getPdfWriter();
PdfFormField field = PdfFormField.createTextField( writer, false, false, 3 );
field.setName( "quantity " + hashCode() );
field.setFieldFlags( PdfFormField.FF_EDIT );
Rectangle rect = new Rectangle( rectangle.getLeft() + 5, rectangle.getTop() - 5,
rectangle.getLeft() + rectangle.getWidth() - 5,
rectangle.getTop() - rectangle.getHeight() + 5);
field.setWidget( rect, PdfAnnotation.HIGHLIGHT_OUTLINE );
field.setFieldFlags( PdfAnnotation.FLAGS_PRINT );
writer.addAnnotation( field );
writer.flush();
}
} );
It works fine as far as entering text into the fields is concerned. But once the field looses focus, the content disappears. If I set the focus to the field again, the data reappears.
My question is: what do I need to do in order for the text in the PdfFormField to stay printed?
there is a sample PDF here: http://qr.sertal.ch/output.pdf
thank you for your help.
I got an answer from the iText mailing list. The way to add form fields described in the book is deprecated. Here is the new way, which works fine:
cell.setCellEvent( new PdfPCellEvent() {
#Override
public void cellLayout( PdfPCell pdfPCell,
Rectangle rectangle,
PdfContentByte[] canvas ) {
PdfContentByte pcb = canvas[canvas.length - 1];
PdfWriter writer = pcb.getPdfWriter();
Rectangle rect = new Rectangle( rectangle.getLeft() + 5, rectangle.getTop() - 5,
rectangle.getLeft() + rectangle.getWidth() - 5,
rectangle.getTop() - rectangle.getHeight() + 5 );
TextField field = new TextField( writer, rectangle, "quantity " + hashCode() );
field.setRotation( A4.rotate().getRotation() );
try {
writer.addAnnotation(field.getTextField());
} catch ( IOException e ) {
e.printStackTrace();
} catch ( DocumentException e ) {
e.printStackTrace();
}
writer.flush();
pcb.rectangle( rect );
}
} );
I had the most problems with the orientation on a landscape page, until I found out you could set the Rotation of the field.
Related
This question is a follow-up from this
After the previous post I managed to create the following method that fits text in certain spaces in paragraphs.
public static void getPlainFill2(String str, Document doc, PdfDocument document, Paragraph root,
Paragraph space, boolean isCentred) {
// System.out.println("prevText: "+prev.getText());
float width = doc.getPageEffectiveArea(PageSize.A4).getWidth();
float height = doc.getPageEffectiveArea(PageSize.A4).getHeight();
if (str.isEmpty() || str.isBlank()) {
str = "________";
}
IRenderer spaceRenderer = space.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult spaceResult = spaceRenderer
.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
Rectangle rectSpaceBox = ((ParagraphRenderer) spaceRenderer).getOccupiedArea().getBBox();
float writingWidth = rectSpaceBox.getWidth();
float writingHeight = rectSpaceBox.getHeight();
Rectangle remaining = doc.getRenderer().getCurrentArea().getBBox();
float yReal = remaining.getTop() + 2f;// orig 4f
float sizet = 0;
for (int i = 0; i < root.getChildren().size(); i++) {
IElement e = root.getChildren().get(i);
if (e.equals(space)) {
break;
}
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
sizet += ss.getOccupiedArea().getBBox().getWidth();
System.out.println("width: " + width + " current: " + sizet);
}
float start = sizet+doc.getLeftMargin();
if(isCentred)
start = (width - getRealWidth(doc, root,width,height))/2+doc.getLeftMargin()+sizet;
Rectangle towr = new Rectangle(start, yReal, writingWidth, writingHeight);// sizet+doc.getLeftMargin()
PdfCanvas pdfcanvas = new PdfCanvas(document.getFirstPage());
Canvas canvas = new Canvas(pdfcanvas, towr);
canvas.setTextAlignment(TextAlignment.CENTER);
canvas.setHorizontalAlignment(HorizontalAlignment.CENTER);
Paragraph paragraph = new Paragraph(str).setTextAlignment(TextAlignment.CENTER).setBold();//.setMultipliedLeading(0.9f);
Div lineDiv = new Div();
lineDiv.setVerticalAlignment(VerticalAlignment.MIDDLE);
lineDiv.add(paragraph);
float fontSizeL = 1f;
float fontSizeR = 12;
int adjust = 0;
while (Math.abs(fontSizeL - fontSizeR) > 1e-1) {
float curFontSize = (fontSizeL + fontSizeR) / 2;
lineDiv.setFontSize(curFontSize);
// It is important to set parent for the current element renderer to a root
// renderer
IRenderer renderer = lineDiv.createRendererSubTree().setParent(canvas.getRenderer());
LayoutContext context = new LayoutContext(new LayoutArea(1, towr));
if (renderer.layout(context).getStatus() == LayoutResult.FULL) {
// we can fit all the text with curFontSize
fontSizeL = curFontSize;
} else {
fontSizeR = curFontSize;
}
if(adjust>=2) {
writingHeight -=1.3f;
yReal += 1.4f;
adjust= 0;
}
}
lineDiv.setFontSize(fontSizeL);
canvas.add(lineDiv);
// border
// PdfCanvas(document.getFirstPage()).rectangle(towr).setStrokeColor(ColorConstants.BLACK).stroke();
canvas.close();
}
public static float getRealWidth (Document doc, Paragraph root,float width,float height) {
float sizet = 0;
for(int i = 0;i<root.getChildren().size();i++) {
IElement e = root.getChildren().get(i);
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width,height))));
sizet +=ss.getOccupiedArea().getBBox().getWidth();
}
return sizet;}
Now this works almost decent, there are minor issues when text scales to lower sizes and it goes like:
https://i.ibb.co/MkxfwjQ/Screenshot-from-2021-06-14-18-27-09.png (I can't post images because I have no rep.)
but the main issue is that you have to write Paragraphs line by line to work. As next example:
Cell cell3 = new Cell();
LineCountingParagraph line3 = new LineCountingParagraph("");
Text ch07 = new Text("Paragraph Prev ");
line3.add(ch07);
Paragraph nrZile = getEmptySpace(15);
line3.add(nrZile);
Text ch08 = new Text("afterStr, textasdsadasdas ");
line3.add(ch08);
Paragraph data = getEmptySpace(18);
line3.add(data);
Text ch09 = new Text(".\n");
line3.add(ch09);
line3.setTextAlignment(TextAlignment.CENTER);
cell3.add(line3);
doc.add(cell3);
getPlainFill2("thisisalongstring", doc, document, line3, nrZile, true);
getPlainFill2("1333", doc, document, line3, data, true);
Cell cell4 = new Cell();
LineCountingParagraph line4 = new LineCountingParagraph("");
Paragraph loc2 = getEmptySpace(30);
line4.add(loc2);
Text pr32 = new Text(" aasdbsadasd ");
line4.add(pr32);
Paragraph nr2 = getEmptySpace(8);
line4.add(nr2);
Text pr33 = new Text(" asdasdasdasd.\n");
line4.add(pr33);
line4.setTextAlignment(TextAlignment.CENTER);
cell4.add(line4);
doc.add(cell4);
getPlainFill2("1333", doc, document, line4, nr2, true);
If you need more code, I'll upload it somewhere.
Now is there a way to insert text within the same paragraph on multiple lines ? because there seems I cannot find a way to detect line break in IText 7.1.11.
Full code:
package pdfFill;
import java.io.File;
import java.io.IOException;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Div;
import com.itextpdf.layout.element.IElement;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.layout.LayoutArea;
import com.itextpdf.layout.layout.LayoutContext;
import com.itextpdf.layout.layout.LayoutResult;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import com.itextpdf.layout.renderer.DrawContext;
import com.itextpdf.layout.renderer.IRenderer;
import com.itextpdf.layout.renderer.ParagraphRenderer;
public class Newway4 {
public static void main(String[] args) {
PdfWriter writer;
try {
writer = new PdfWriter(new File("test4.pdf"));
PdfDocument document = new PdfDocument(writer);
document.getDocumentInfo().addCreationDate();
document.getDocumentInfo().setAuthor("Piri");
document.getDocumentInfo().setTitle("Test_Stackoverflow");
document.setDefaultPageSize(PageSize.A4);
Document doc = new Document(document);
doc.setFontSize(12);
final Paragraph titlu = new Paragraph();
final Text t1 = new Text("\n\n\n\nTest Stackoverflow\n\n\n").setBold().setUnderline();
titlu.setHorizontalAlignment(HorizontalAlignment.CENTER);
titlu.setTextAlignment(TextAlignment.CENTER);
titlu.add(t1).setBold();
doc.add(titlu);
Cell cell1 = new Cell();
LineCountingParagraph line1 = new LineCountingParagraph("");
line1.add( addTab());
Text ch01 = new Text("This is the 1st example ");
line1.add(ch01);
Paragraph name = getEmptySpace(42);
line1.add(name);// cnp new line
Text ch02 = new Text(" that works ");
line1.add(ch02);
Paragraph domiciliu = getEmptySpace(63);
line1.add(domiciliu);
/* Text ch03 = new Text("\njudet");
line1.add(ch03);
Paragraph judet = getEmptySpace(12);
line1.add(judet);*/
Text ch031 = new Text("\n");
line1.add(ch031);
cell1.add(line1);
doc.add(cell1);
getPlainFill2("with insertion str", doc, document, line1, name, false);
getPlainFill2("because is writtin line by line", doc, document, line1, domiciliu, false);
Cell cell2 = new Cell();
LineCountingParagraph line2 = new LineCountingParagraph("");
Text p51 = new Text("as you can see in this");
line2.add(p51);
Paragraph localitatea = getEmptySpace(30);
line2.add(localitatea);
Text p7 = new Text(" and ");
line2.add(p7);
Paragraph nrCasa =getEmptySpace(8);
line2.add(nrCasa);
Text p09 = new Text(" of text scalling ");
line2.add(p09);
Paragraph telefon = getEmptySpace(22);
line2.add(telefon);
Text p11 = new Text(".");
line2.add(p11);
line2.setTextAlignment(TextAlignment.CENTER);
cell2.add(line2);
doc.add(cell2);
getPlainFill2("sentence", doc, document, line2, localitatea, true);
getPlainFill2("example", doc, document, line2, nrCasa, true);
getPlainFill2("text scalling bla bla", doc, document, line2, telefon, true);
doc.add(new Paragraph("\n\n\n"));
LineCountingParagraph paragraphTest = new LineCountingParagraph("");
paragraphTest.add(addTab());
Text testch01 = new Text("This is the 2nd example ");
paragraphTest.add(testch01);
Paragraph emptyTest01 = getEmptySpace(42);
paragraphTest.add(emptyTest01);
Text testch02 = new Text(" that doesn't work ");
paragraphTest.add(testch02);
Paragraph emptyTest02 = getEmptySpace(53);
paragraphTest.add(emptyTest02);
Text testch04 = new Text(" this next goes to the next line but ");
paragraphTest.add(testch04);
Paragraph emptyTest03 = getEmptySpace(42);
paragraphTest.add(emptyTest03);
Text testch05 = new Text(" won't appear !!");
paragraphTest.add(testch05);
doc.add(paragraphTest);
getPlainFill2("with insertion str", doc, document, paragraphTest, emptyTest01, false);
getPlainFill2("because next text goes next line", doc, document, paragraphTest, emptyTest02, false);
getPlainFill2("this text", doc, document, paragraphTest, emptyTest03, false);
doc.close();
writer.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static String getStrWithDots(final int dots, final String str) {
final int strSize = str.length();
final StringBuilder sb = new StringBuilder();
int dotsRemained;
if (strSize > dots) {
dotsRemained = 0;
} else {
dotsRemained = dots - strSize;
}
for (int i = 0; i < dotsRemained; ++i) {
if (i == dotsRemained / 2) {
sb.append(str);
}
sb.append(".");
}
return sb.toString();
}
public static void getPlainFill2(String str, Document doc, PdfDocument document, Paragraph root,
Paragraph space, boolean isCentred) {
// System.out.println("prevText: "+prev.getText());
float width = doc.getPageEffectiveArea(PageSize.A4).getWidth();
float height = doc.getPageEffectiveArea(PageSize.A4).getHeight();
if (str.isEmpty() || str.isBlank()) {
str = "________";
}
IRenderer spaceRenderer = space.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult spaceResult = spaceRenderer
.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
Rectangle rectSpaceBox = ((ParagraphRenderer) spaceRenderer).getOccupiedArea().getBBox();
float writingWidth = rectSpaceBox.getWidth();
float writingHeight = rectSpaceBox.getHeight();
Rectangle remaining = doc.getRenderer().getCurrentArea().getBBox();
float yReal = remaining.getTop() + 2f;// orig 4f
float sizet = 0;
for (int i = 0; i < root.getChildren().size(); i++) {
IElement e = root.getChildren().get(i);
if (e.equals(space)) {
break;
}
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width, height))));
sizet += ss.getOccupiedArea().getBBox().getWidth();
}
float start = sizet+doc.getLeftMargin();
if(isCentred)
start = (width - getRealWidth(doc, root,width,height))/2+doc.getLeftMargin()+sizet;
Rectangle towr = new Rectangle(start, yReal, writingWidth, writingHeight);// sizet+doc.getLeftMargin()
PdfCanvas pdfcanvas = new PdfCanvas(document.getFirstPage());
Canvas canvas = new Canvas(pdfcanvas, towr);
canvas.setTextAlignment(TextAlignment.CENTER);
canvas.setHorizontalAlignment(HorizontalAlignment.CENTER);
Paragraph paragraph = new Paragraph(str).setTextAlignment(TextAlignment.CENTER).setBold();//.setMultipliedLeading(0.9f);//setbold oprtional
Div lineDiv = new Div();
lineDiv.setVerticalAlignment(VerticalAlignment.MIDDLE);
lineDiv.add(paragraph);
float fontSizeL = 0.0001f, fontSizeR= 10000;
int adjust = 0;
while (Math.abs(fontSizeL - fontSizeR) > 1e-1) {
float curFontSize = (fontSizeL + fontSizeR) / 2;
lineDiv.setFontSize(curFontSize);
// It is important to set parent for the current element renderer to a root
// renderer
IRenderer renderer = lineDiv.createRendererSubTree().setParent(canvas.getRenderer());
LayoutContext context = new LayoutContext(new LayoutArea(1, towr));
if (renderer.layout(context).getStatus() == LayoutResult.FULL) {
// we can fit all the text with curFontSize
fontSizeL = curFontSize;
if (++adjust>1)
towr.setHeight(towr.getHeight()-0.90f);
} else {
fontSizeR = curFontSize;
}
}
lineDiv.setFontSize(fontSizeL);
canvas.add(lineDiv);
new PdfCanvas(document.getFirstPage()).rectangle(towr).setStrokeColor(ColorConstants.BLACK).stroke();
canvas.close();
}
public static Text addTab() {
StringBuilder sb = new StringBuilder();
for(int i = 0;i<8;i++)
sb.append("\u00a0");
return new Text(sb.toString());
}
public static float getRealWidth (Document doc, Paragraph root,float width,float height) {
float sizet = 0;
for(int i = 0;i<root.getChildren().size();i++) {
IElement e = root.getChildren().get(i);
IRenderer ss = e.createRendererSubTree().setParent(doc.getRenderer());
LayoutResult ss2 = ss.layout(new LayoutContext(new LayoutArea(1, new Rectangle(width,height))));
sizet +=ss.getOccupiedArea().getBBox().getWidth();
}
return sizet;
}
private static Paragraph getEmptySpace(int size) {
Paragraph space = new Paragraph();
space.setMaxWidth(size);
for(int i=0;i<size;i++) {
// par.add("\u00a0");
space.add("\u00a0");
}
return space;
}
private static class LineCountingParagraph extends Paragraph {
private int linesWritten = 0;
public LineCountingParagraph(String text) {
super(text);
}
public void addWrittenLines(int toAdd) {
linesWritten += toAdd;
}
public int getNumberOfWrittenLines() {
return linesWritten;
}
#Override
protected IRenderer makeNewRenderer() {
return new LineCountingParagraphRenderer(this);
}
}
private static class LineCountingParagraphRenderer extends ParagraphRenderer {
public LineCountingParagraphRenderer(LineCountingParagraph modelElement) {
super(modelElement);
}
#Override
public void drawChildren(DrawContext drawContext) {
((LineCountingParagraph)modelElement).addWrittenLines(lines.size());
super.drawChildren(drawContext);
}
#Override
public IRenderer getNextRenderer() {
return new LineCountingParagraphRenderer((LineCountingParagraph) modelElement);
}
}
}
The issue: in the top half of the PDF you can see the result of two LineCountingParagraph instances being created, one per line. In the bottom half of the PDF you can see the result when only one instance of LineCountingParagraph is created. So fitting the text in boxes does not work well in case content of the paragraph wraps to the next line.
You have unnecessarily complicated things in such a way that we have to start from scratch :)
So the goal is to be able to create paragraphs with boxed intrusions of fixed width, where we need to copy-fit (place) some text, making sure the font size is selected in such a way that the text fits into that box.
The result should look similar to this picture:
The idea is that we will add paragraphs of fixed width into our main paragraph (iText allows adding block elements and a paragraph is a block element - into paragraphs). The fixed width will be guaranteed by the contents of our paragraph - it will just contain non-breakable spaces. Our paragraph will actually be backed by another paragraph with the actual content we want to fit into our wrapping paragraph. During the layout of the wrapping paragraph we will know its effective boundary and we will just use that area to determine the right font size for our content paragraph using binary search algorithm. Once the right font size has been determined we will just make sure the paragraph with the content gets drawn right next to our wrapping paragraph.
The code for our wrapping paragraph is pretty simple. It just expects the underlying paragraph with real content as the parameter. As always with iText layout, we should customize the renderer of our autoscaling paragraph:
private static class AutoScalingParagraph extends Paragraph {
Paragraph innerParagraph;
public AutoScalingParagraph(Paragraph innerParagraph) {
this.innerParagraph = innerParagraph;
}
#Override
protected IRenderer makeNewRenderer() {
return new AutoScalingParagraphRenderer(this);
}
}
private static class AutoScalingParagraphRenderer extends ParagraphRenderer {
private IRenderer innerRenderer;
public AutoScalingParagraphRenderer(AutoScalingParagraph modelElement) {
super(modelElement);
}
#Override
public LayoutResult layout(LayoutContext layoutContext) {
LayoutResult baseResult = super.layout(layoutContext);
this.innerRenderer = ((AutoScalingParagraph)modelElement).innerParagraph.createRendererSubTree().setParent(this);
if (baseResult.getStatus() == LayoutResult.FULL) {
float fontSizeL = 0.0001f, fontSizeR= 10000;
while (Math.abs(fontSizeL - fontSizeR) > 1e-1) {
float curFontSize = (fontSizeL + fontSizeR) / 2;
this.innerRenderer.setProperty(Property.FONT_SIZE, UnitValue.createPointValue(curFontSize));
if (this.innerRenderer.layout(new LayoutContext(getOccupiedArea().clone())).getStatus() == LayoutResult.FULL) {
// we can fit all the text with curFontSize
fontSizeL = curFontSize;
} else {
fontSizeR = curFontSize;
}
}
this.innerRenderer.setProperty(Property.FONT_SIZE, UnitValue.createPointValue(fontSizeL));
this.innerRenderer.layout(new LayoutContext(getOccupiedArea().clone()));
}
return baseResult;
}
#Override
public void drawChildren(DrawContext drawContext) {
super.drawChildren(drawContext);
innerRenderer.draw(drawContext);
}
#Override
public IRenderer getNextRenderer() {
return new AutoScalingParagraphRenderer((AutoScalingParagraph) modelElement);
}
}
Now we add the helper function for creating our wrapper paragraphs that just accepts the desired paragraph width in spaces and the underlying content we want to fit into that space:
private static Paragraph createAdjustableParagraph(int widthInSpaces, Paragraph innerContent) {
AutoScalingParagraph paragraph = new AutoScalingParagraph(innerContent);
paragraph.setBorder(new SolidBorder(1));
StringBuilder sb = new StringBuilder();
for(int i=0;i<widthInSpaces;i++) {
sb.append("\u00a0");
}
paragraph.add(sb.toString());
return paragraph;
}
Finally, the main code:
PdfWriter writer = new PdfWriter(new File("test4.pdf"));
PdfDocument document = new PdfDocument(writer);
Document doc = new Document(document);
Paragraph paragraphTest = new Paragraph();
Text testch01 = new Text("This is the 2nd example ");
paragraphTest.add(testch01);
paragraphTest.add(createAdjustableParagraph(42, new Paragraph("with insertion str")));
Text testch02 = new Text(" that doesn't work ");
paragraphTest.add(testch02);
paragraphTest.add(createAdjustableParagraph(53, new Paragraph("because next text goes next line")));
Text testch04 = new Text(" this next goes to the next line but ");
paragraphTest.add(testch04);
paragraphTest.add(createAdjustableParagraph(42, new Paragraph("this text")));
Text testch05 = new Text(" won't appear !!");
paragraphTest.add(testch05);
doc.add(paragraphTest);
doc.close();
Which gives us the following result:
So we just have the one main paragraph which contains some content and our paragraph wrappers, which in tern have the underlying content we want to fit.
Hint: centering the text is very easy, you don't need to calculate coordinates etc. Just set the right property to the paragraph with the content that you feed to your wrapper paragraph:
paragraphTest.add(createAdjustableParagraph(42, new Paragraph("this text").setTextAlignment(TextAlignment.CENTER)));
And you get the result:
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?
I'm using ItextPdf 5.
I have an SVG file with specifical font (integrated in svg).
When I print my SVG (using batik 1.8) the graphic is print on my document, but fonts are blocked, so, can't select them.
see below my java code :
public class ItextPdfSmallTests {
#Test
public void svgFontsTest() throws IOException, DocumentException, URISyntaxException {
String RESULT = "C:\\test\\svgFontsTest.pdf";
Document document = new Document(PageSize.A4, 36, 36, 54, 36);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
document.open();
document.add(new Paragraph("SVG Example"));
int width = 250;
int height = 250;
PdfContentByte cb = writer.getDirectContent();
PdfTemplate template = cb.createTemplate(width, height);
PdfPrinterGraphics2D g2 = new PdfPrinterGraphics2D(cb, width, height, new MyFontMapper(), PrinterJob.getPrinterJob());
PrintTranscoder prm = new PrintTranscoder();
URI svgFileURI = getClass().getResource("myfont.svg").toURI();
TranscoderInput ti = new TranscoderInput(svgFileURI.toString());
prm.transcode(ti, null);
PageFormat pg = new PageFormat();
Paper pp = new Paper();
pp.setSize(width, height);
pp.setImageableArea(0, 0, width, height);
pg.setPaper(pp);
prm.print(g2, pg, 0);
g2.dispose();
ImgTemplate img = new ImgTemplate(template);
document.add(img);
document.close();
}
class MyFontMapper extends DefaultFontMapper {
#Override
public BaseFont awtToPdf(java.awt.Font font) {
try {
return BaseFont.createFont("AmaticSC-Regular.ttf", BaseFont.WINANSI, false);
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
is it possible make it editable ?
thanks for your helps
The case is that the TopTaskGroup(left one) can "grab excess vertical space" while resizing window, but the NewTaskGroup(the right one), after adding a TooBar on it(see the createAddBtnOnGroup method), it doesn't grow as you resize the window. Why is that?
(I have a shell instance with 2-column GridLayout)
Code is here:
private void createTaskWidgets() {
createTopTaskGroup();
createNewTaskGroup();
}
private void createTopTaskGroup() {
Group topTasksGroup = new Group(shell, SWT.SHADOW_NONE);
topTasksGroup.setText(TaskConsts.TOP_TASK_LIST);
topTasksTable = new TaskTable(topTasksGroup, TaskTable.SORT_BY_VOTES, iteration, this);
topTasksTable.setLayoutData(getTableGridData() );
topTasksGroup.setLayout(new GridLayout() );
topTasksGroup.setLayoutData(getTableGridData() );
topTasksGroup.pack();
}
private void createNewTaskGroup() {
Group newTasksGroup = new Group(shell, SWT.SHADOW_NONE);
newTasksGroup.setText(TaskConsts.NEW_TASK_LIST);
newTasksTable = new TaskTable(newTasksGroup, TaskTable.SORT_BY_CREATION_TIME, iteration, this);
topTasksTable.setLayoutData(getTableGridData() );
ToolBar actionToolBar = createAddBtnOnGroup(newTasksGroup);
newTasksGroup.setLayout(new GridLayout() );
newTasksGroup.setLayoutData(getTableGridData() );
newTasksGroup.layout();
newTasksGroup.pack();
// set actionToolBar's location to newTasksGroup's right-top position
actionToolBar.setLocation(
newTasksGroup.getLocation().x + newTasksGroup.getSize().x
- actionToolBar.getSize().x - 5,
newTasksGroup.getLocation().y - 2);
}
private GridData getTableGridData() {
GridData gridData = new GridData(0, SWT.FILL, false, true);
return gridData;
}
private ToolBar createAddBtnOnGroup(Group newTasksGroup) {
ToolBar actionToolBar = new ToolBar(newTasksGroup, SWT.HORIZONTAL | SWT.RIGHT);
addTaskToolItem = new ToolItem(actionToolBar, SWT.PUSH | SWT.RIGHT);
addTaskToolItem.setImage(new Image(display, TaskConsts.ICON_PLUS));
final MainWindow mainWindow = this;
addTaskToolItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
new CreateTask(getShell(), mainWindow);
}
});
GridData gridData = new GridData();
gridData.exclude = true;
actionToolBar.setLayoutData(gridData);
actionToolBar.pack();
return actionToolBar;
}
private void organize() {
GridLayout gridLayout = new GridLayout(2, false);
shell.setLayout(gridLayout);
shell.pack();
}
Thanks in advance~
Thanks for your excellent problem description!
It seems to me that this is a simple copy-paste bug.
The fourth line in your createNewTaskGroup method should not be
topTasksTable.setLayoutData(getTableGridData() );
but
newTasksTable.setLayoutData(getTableGridData() );
I am creating a PDF using iText. I want to insert blank lines between paragraphs and tables.
How can I achieve this?
You can trigger a newline by inserting Chunk.NEWLINE into your document. Here's an example.
public static void main(String args[]) {
try {
// create a new document
Document document = new Document( PageSize.A4, 20, 20, 20, 20 );
PdfWriter.getInstance( document, new FileOutputStream( "HelloWorld.pdf" ) );
document.open();
document.add( new Paragraph( "Hello, World!" ) );
document.add( new Paragraph( "Hello, World!" ) );
// add a couple of blank lines
document.add( Chunk.NEWLINE );
document.add( Chunk.NEWLINE );
// add one more line with text
document.add( new Paragraph( "Hello, World!" ) );
document.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
Below is a screen shot showing part of the PDF that the code above produces.
And to insert blank line between tables you can use these both methods
table.setSpacingBefore();
table.setSpacingAfter();
You can use "\n" in Paragraph
document.add(new Paragraph("\n\n"));
You can try a blank phrase:
document.add(new Phrase("\n"));
You can add Blank Line throw PdfContentByte class in itextPdf. As shown below:
package com.pdf.test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
public class Ranvijay {
public static final String RESULT = "d:/printReport.pdf";
public void createPdf(String filename) throws Exception {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream(filename));
document.open();
Font bold = new Font(Font.FontFamily.HELVETICA, 8f, Font.BOLD);
Font normal = new Font(Font.FontFamily.HELVETICA, 8f, Font.NORMAL);
PdfPTable tabletmp = new PdfPTable(1);
tabletmp.getDefaultCell().setBorder(Rectangle.NO_BORDER);
tabletmp.setWidthPercentage(100);
PdfPTable table = new PdfPTable(2);
float[] colWidths = { 45, 55 };
table.setWidths(colWidths);
String imageUrl = "http://ssl.gstatic.com/s2/oz/images/logo/2x/googleplus_color_33-99ce54a16a32f6edc61a3e709eb61d31.png";
Image image2 = Image.getInstance(new URL(imageUrl));
image2.setWidthPercentage(60);
table.getDefaultCell().setBorder(Rectangle.NO_BORDER);
table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
table.getDefaultCell().setVerticalAlignment(Element.ALIGN_TOP);
PdfPCell cell = new PdfPCell();
cell.setBorder(Rectangle.NO_BORDER);
cell.addElement(image2);
table.addCell(cell);
String email = "ranvijay9286#gmail.com";
String collectionDate = "09/09/09";
Chunk chunk1 = new Chunk("Date: ", normal);
Phrase ph1 = new Phrase(chunk1);
Chunk chunk2 = new Chunk(collectionDate, bold);
Phrase ph2 = new Phrase(chunk2);
Chunk chunk3 = new Chunk("\nEmail: ", normal);
Phrase ph3 = new Phrase(chunk3);
Chunk chunk4 = new Chunk(email, bold);
Phrase ph4 = new Phrase(chunk4);
Paragraph ph = new Paragraph();
ph.add(ph1);
ph.add(ph2);
ph.add(ph3);
ph.add(ph4);
table.addCell(ph);
tabletmp.addCell(table);
PdfContentByte canvas = writer.getDirectContent();
canvas.saveState();
canvas.setLineWidth((float) 10 / 10);
canvas.moveTo(40, 806 - (5 * 10));
canvas.lineTo(555, 806 - (5 * 10));
canvas.stroke();
document.add(tabletmp);
canvas.restoreState();
PdfPTable tabletmp1 = new PdfPTable(1);
tabletmp1.getDefaultCell().setBorder(Rectangle.NO_BORDER);
tabletmp1.setWidthPercentage(100);
document.add(tabletmp1);
document.close();
}
/**
* Main method.
*
* #param args
* no arguments needed
* #throws DocumentException
* #throws IOException
*/
public static void main(String[] args) throws Exception {
new Ranvijay().createPdf(RESULT);
System.out.println("Done Please check........");
}
}
document.add(new Paragraph(""))
It is ineffective above,must add a blank string, like this:
document.add(new Paragraph(" "));
You can add empty line ;
Paragraph p = new Paragraph();
// add one empty line
addEmptyLine(p, 1);
// add 3 empty line
addEmptyLine(p, 3);
private static void addEmptyLine(Paragraph paragraph, int number) {
for (int i = 0; i < number; i++) {
paragraph.add(new Paragraph(" "));
}
}
You can also use
document.add(new Paragraph());
document.add(new Paragraph());
before seperator if you are using either it is fine.
Instead of using:
document.add( Chunk.NEWLINE );
use this:
document.add(new Paragraph(""));
it makes small space
directly use
paragraph.add("\n");
to add an empty line.
I posted this in another question, but I find using tables with iTextSharp offers a great level of precision.
document.Add(BlankLineDoc(16));
public static PdfPTable BlankLineDoc(int height)
{
var table = new PdfPTable(1) {WidthPercentage = 100};
table = BlankLineTable(table, height);
return table;
}
public static PdfPTable BlankLineTable(PdfPTable table, int height, int border = Rectangle.NO_BORDER)
{
var cell = new PdfPCell(new Phrase(" "))
{
Border = border,
Colspan = table.NumberOfColumns,
FixedHeight = height
};
table.AddCell(cell);
return table;
}
BlankLineTable can be used directly when working with tables
I had to add blank lines after a table and I manage it adding many divs as I need it with a css style with padding-top set it up, like this. I've used a template engine (underscore) to loop through the number of lines I need to add.
<% var maxRow = 30; var pos = items.models.length; %>
<% for( pos; pos < maxRow; pos++ ){ %>
<div class="blankRow"></div>
<% }; %>
My css file:
.blankRow:{ padding-top: 15px;}