I'm using itext 7.1.9 and I need to create a PDF document with two checkbox fields with the same names.
A have tried it the next way:
PdfFormField field = PdfFormField.createComboBox(pdf, rect, name, value, options);
PdfFormField parent;
if ( (parent = form.getField(name)) != null) {
parent.addKid(field);
parent.setValue(value);
}
but it doesn't work for me. The fields disappeared from the PDF.
I used iText version 7.2.0 to create PDF where iText creates two fields with the same name. To see the result use Google Chrome or PDF Studio 2021. For some reason Acrobat doesn't render second field with the same name
PdfDocument pdfDoc = new PdfDocument(new PdfWriter(outPdf));
pdfDoc.addNewPage();
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true);
PdfFormField field1 = PdfFormField.createComboBox(pdfDoc, new Rectangle(50, 730, 100, 20), "name", "value", new String[] {"one", "two"});
PdfFormField field2 = PdfFormField.createComboBox(pdfDoc, new Rectangle(50, 700, 100, 20), "name", "value", new String[] {"one", "two", "three"});
form.addField(field1);
form.addField(field2);
pdfDoc.close();
If you want to create checkbox fields with the same name use PdfFormField#createCheckbox method.
Related
Good day. I'm building a simple pdf report using native PrintedPdfDocument class and I need to insert a text with hyperlink into a document. This is my simple implementation of pdf page.
PrintedPdfDocument document = new PrintedPdfDocument(context, attributes);
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(595, 842, 1).create();
PdfDocument.Page page = document.startPage(pageInfo);
Canvas c = page.getCanvas();
TextPaint p = new TextPaint();
Here a several ways I had tried but still no luck.
First way using a Canvas drawText() method. Result: "some link" without hyperlink.
c.drawText("<a href='https://example.com'>some link</a>", 30, 30, p);
Second way using SpannableString. Result: "some link".
String link = "https://example.com";
SpannableString s = new SpannableString("some link");
s.setSpan(new URLSpan(link), 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
c.drawText(s.toString(), 30, 30, p);
Third way using StaticLayout. Result: blank space.
Spanned spanned = Html.fromHtml("<a href='https://example.com'>some link</a>", null, null);
StaticLayout l = new StaticLayout(spanned, p, 30, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false);
l.draw(c);
TextView do not draw anything to Canvas.
TextView tv = new TextView(context);
tv.setLayoutParams(new ViewGroup.LayoutParams(100, 100));
tv.setText(Html.fromHtml("<a href='https://example.com'>some link</a>"));
tv.draw(c);
Maybe you better know how to deal with it?
I wanted to insert a Table in the position of the form field. How do I get the position and page number of the form field? How do I insert the table in that location?
//Retrieves AcroForm from the document.
//If there is no AcroForm in the document Catalog and createIfNotExist
//flag is true then the AcroForm dictionary will be created and added to the document.
PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDoc, true);
//Gets the form fields as a Map.
Map<String, PdfFormField> fields = acroForm.getFormFields();
//Create Table
Table table = new Table(new float[]{1,1});
table.setHorizontalAlignment(HorizontalAlignment.CENTER);
table.setWidthPercent(95);
Cell cell = new Cell();
cell.add(new Paragraph("Name"));
//cell.setBorder(Border.NO_BORDER);
table.addCell(cell);
Cell cell = new Cell();
cell.add(new Paragraph("Address"));
//cell.setBorder(Border.NO_BORDER);
table.addCell(cell);
...
...
doc.add(table);
...
Field by itself does not have any position or page number. However, its widget annotations do.
To access those, you can use field.getWidgets(). You then can use annotation.getPage() and annotation.getRectangle() to get information about the annotation's position.
To layout an single element at some specific position, one of the best choices is using Canvas layout object. Annotation can then be removed with page.removeAnnotation(annotation);.
Overall, this compiles into following solution:
String fieldName = "Text1";
PdfFormField field = form.getField(fieldName);
for (PdfAnnotation annotation : field.getWidgets()) {
PdfPage page = annotation.getPage();
Rectangle rectangle = annotation.getRectangle().toRectangle();
Table table = new Table(UnitValue.createPointArray(new float[] {-1, -1}));
table.setHorizontalAlignment(HorizontalAlignment.CENTER);
Cell cell = new Cell();
cell.add(new Paragraph("Name"));
table.addCell(cell);
cell = new Cell();
cell.add(new Paragraph("Address"));
table.addCell(cell);
Canvas canvas = new Canvas(new PdfCanvas(page), pdfDocument, rectangle);
canvas.add(table);
canvas.close();
page.removeAnnotation(annotation);
}
Of course, you will have to take full responsibility for creating a table of proper size so that it fits into the area you want. You can use smaller font sizes etc.
I am creating a PDF using iText 5.5.6.
I wanted to tag table, row and cell as a DIV.
I have written the following code but only the table gets marked as a DIV and not the row and cell.
PdfPTable table = new PdfPTable(2);
table.setRunDirection(PdfAWriter.RUN_DIRECTION_LTR);
table.setRole(PdfName.DIV);
table.setWidthPercentage(80);
table.setWidths(new float[] { 0.8f, 1.2f });
table.setHorizontalAlignment(PdfPTable.ALIGN_LEFT);
table.setSpacingBefore(10);
table.setSpacingAfter(15);
Paragraph p3 = new Paragraph("Name:", font12);
Paragraph p4 = new Paragraph("FirstName LastName", font12);
Paragraph p5 = new Paragraph("DOB: ", font12);
Paragraph p6 = new Paragraph("00-00-0000", font12);
PdfPCell cellp3 = new PdfPCell(p3);
cellp3.setBorder(0);
PdfPCell cellp4 = new PdfPCell(p4);
cellp4.setBorder(0);
cellp3.setRole(PdfName.DIV);
cellp4.setRole(PdfName.DIV);
table.addCell(cellp3);
table.addCell(cellp4);
PdfPCell cellp5 = new PdfPCell(p5);
cellp5.setBorder(0);
PdfPCell cellp6 = new PdfPCell(p6);
cellp6.setBorder(0);
cellp5.setRole(PdfName.DIV);
cellp6.setRole(PdfName.DIV);
table.addCell(cellp5);
table.addCell(cellp6);
How to solve this?
If I test your code the table and all the cells are tagged as DIV. The rows are indeed not.
In iText the classes PdfPTable, PdfPRow and PdfPCell are responsible for table functionality. PdfPRow is typically only used in the iText implementation internally, because a PdfPTable instance accepts PdfPCells directly.
But you are able to retrieve the table rows to set their role. After you have added all the cells to the table, do this:
for (PdfPRow row : table.getRows())
row.setRole(PdfName.DIV);
I have a main report which is printed horizontally. It has 5 columns.
On every column i want to put a sub report. So i created this:
And the sub-report just like this:
The problem is, when i run i get the following exception:
net.sf.jasperreports.engine.JRRuntimeException: Subreport overflowed on a band that does not support overflow.
Looks like jasper reports can't stretch the detail band vertically when there is a sub-report in it and the print order is set to horizontal.
What can I do to avoid this error and achieve what i want?
I found the solution for this problem. After a deep search i found that, sadly, there's no way to do this on Jasper Reports because, no matter what, when you have a report printed horizontally, the "Detail" band will never change it's height. So, subreports or text fields which overflows will throw an exception.
The workaround for this problem is to work without reports, with a PDF generator like iText, for example.
This is the code i did to achive what i wanted with iText if somebody needs it:
Document document = new Document();
File arquivo = new File("C:\\Users\\Mateus\\Desktop\\testezãozarãozão.pdf");
PdfWriter.getInstance(document, new FileOutputStream(arquivo));
document.open();
LinkedHashMap<Produto, LinkedHashMap<String, List<PrePedidoItem>>> produtos = createStructuredHashMap();
for (Produto produto : produtos.keySet()) {
PdfPTable table = new PdfPTable(5);
PdfPCell cellProduto = new PdfPCell();
Phrase phraseProduto = new Phrase(String.valueOf(produto));
phraseProduto.setFont(new Font(Font.FontFamily.HELVETICA, 11, Font.BOLD|Font.UNDERLINE, new BaseColor(50, 65, 200)));
cellProduto.addElement(phraseProduto);
cellProduto.setColspan(5);
cellProduto.setHorizontalAlignment(PdfPCell.ALIGN_MIDDLE);
cellProduto.setBorder(Rectangle.NO_BORDER);
cellProduto.setPaddingBottom(10);
cellProduto.setPaddingTop(20);
table.addCell(cellProduto);
LinkedHashMap<String, List<PrePedidoItem>> mapas = produtos.get(produto);
int mapasAdicionados = 0;
for (String mapa : mapas.keySet()) {
PdfPCell cellMapa = new PdfPCell();
Phrase phraseMapa = new Phrase(mapa);
phraseMapa.setFont(new Font(Font.FontFamily.HELVETICA, 9, Font.BOLD, new BaseColor(215, 100, 0)));
cellMapa.addElement(phraseMapa);
List<PrePedidoItem> itensDoMapa = mapas.get(mapa);
for (PrePedidoItem item : itensDoMapa) {
DecimalFormat df = new DecimalFormat("###,##0.00");
Phrase phraseItem = new Phrase(df.format(item.getLargura()) + " x " + df.format(item.getComprimento()));
phraseItem.setFont(new Font(Font.FontFamily.HELVETICA, 9, Font.NORMAL, BaseColor.BLACK));
cellMapa.addElement(phraseItem);
}
cellMapa.setBorder(Rectangle.NO_BORDER);
table.addCell(cellMapa);
mapasAdicionados ++;
if(mapasAdicionados == 5) {
mapasAdicionados = 0;
}
}
PdfPCell celulaPreenchimentoMapas = new PdfPCell();
celulaPreenchimentoMapas.setColspan(5 - mapasAdicionados);
celulaPreenchimentoMapas.setBorder(Rectangle.NO_BORDER);
table.addCell(celulaPreenchimentoMapas);
document.add(table);
}
document.close();
Desktop.getDesktop().open(arquivo);
As the lucene migration guide mentioned, to set document level boost we should multiply all fields boost by boosting value. here is my code :
StringField nameField = new StringField("name", name, Field.Store.YES) ;
StringField linkField = new StringField("link", link, Field.Store.YES);
Field descField;
TextField reviewsField = new TextField("reviews", reviews_str, Field.Store.YES);
TextField authorsField = new TextField("authors", authors_str, Field.Store.YES);
FloatField scoreField = new FloatField("score", origScore,Field.Store.YES);
if (desc != null) {
descField = new TextField("desc", desc, Field.Store.YES);
} else {
descField = new TextField("desc", "", Field.Store.YES);
}
doc.add(nameField);
doc.add(linkField);
doc.add(descField);
doc.add(reviewsField);
doc.add(authorsField);
doc.add(scoreField);
nameField.setBoost(score);
linkField.setBoost(score);
descField.setBoost(score);
reviewsField.setBoost(score);
authorsField.setBoost(score);
scoreField.setBoost(score);
but I've got this exception when running code :
Exception in thread "main" java.lang.IllegalArgumentException: You cannot set an index-time boost on an unindexed field, or one that omits norms
I've searched google. but I've got no answers. would you please help me?
Index-time boosts are stored in the field's norm, and both StringField and FloatField omit norms by default. So, you'll need to turn them on before you set the boosts.
To turn norms on, you'll need to define your own field types:
//Start with a copy of the standard field type
FieldType myStringType = new FieldType(StringField.TYPE_STORED);
myStringType.setOmitNorms(false);
//StringField doesn't do anything special except have a customized fieldtype, so just use Field.
Field nameField = new Field("name", name, myStringType);
FieldType myFloatType = new FieldType(FloatField.TYPE_STORED);
myFloatType.setOmitNorms(false);
//For FloatField, use the appropriate FloatField ctor, instead of Field (similar for other numerics)
Field scoreField = new FloatField("score", origScore, myFloatType);