I'm using iTextSharp to create a PDF, how can I add a textField into PdfPCell?
You wouldn't really add a 'text field' to a PdfPCell, you'd create a PdfPCell and add text (or other stuff) to that.
mikesdotnetting.com might have the clearest example and there's always the iTextSharp tutorial.
Give this a try. It works for me.
Document doc = new Document(PageSize.LETTER, 18f, 18f, 18f, 18f);
MemoryStream ms = new MemoryStream();
PdfWriter writer = PdfWriter.GetInstance(doc, ms);
doc.Open();
// Create your PDFPTable here....
TextField tf = new TextField(writer, new iTextSharp.text.Rectangle(67, 585, 140, 800), "cellTextBox");
PdfPCell tbCell = new PdfPCell();
iTextSharp.text.pdf.events.FieldPositioningEvents events = new iTextSharp.text.pdf.events.FieldPositioningEvents(writer, tf.GetTextField());
tbCell.CellEvent = events;
myTable.AddCell(tbCell);
// More code...
I adapted this code from this post.
Edit:
Here is a full working console application that puts a TextBox in a table cell. I tried to keep the code to a bare minimum.
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace iTextSharpTextBoxInTableCell
{
class Program
{
static void Main(string[] args)
{
// Create a PDF with a TextBox in a table cell
BaseFont bfHelvetica = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1250, false);
Font helvetica12 = new Font(bfHelvetica, 12, Font.NORMAL, Color.BLACK);
Document doc = new Document(PageSize.LETTER, 18f, 18f, 18f, 18f);
FileStream fs = new FileStream("TextBoxInTableCell.pdf", FileMode.Create);
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
PdfPTable myTable = new PdfPTable(1);
myTable.TotalWidth = 568f;
myTable.LockedWidth = true;
myTable.HorizontalAlignment = 0;
TextField tf = new TextField(writer, new iTextSharp.text.Rectangle(67, 585, 140, 800), "cellTextBox");
PdfPCell tbCell = new PdfPCell(new Phrase(" ", helvetica12));
iTextSharp.text.pdf.events.FieldPositioningEvents events =
new iTextSharp.text.pdf.events.FieldPositioningEvents(writer, tf.GetTextField());
tbCell.CellEvent = events;
myTable.AddCell(tbCell);
doc.Add(myTable);
doc.Close();
fs.Close();
Console.WriteLine("End Of Program Execution");
Console.ReadLine();
}
}
}
Bon chance
DaveB's answer works, but the problem is that you have to know the coordinates to place the textfield into, the (67, 585, 140, 800). The more normal method of doing this is to create the table cell and add a custom event to the cell. When the table generation calls the celllayout event it passes it the dimensions and coordinates of the cell which you can use to place and size the textfield.
First create this call, which is the custom event
public class CustomCellLayout : IPdfPCellEvent
{
private string fieldname;
public CustomCellLayout(string name)
{
fieldname = name;
}
public void CellLayout(PdfPCell cell, Rectangle rectangle, PdfContentByte[] canvases)
{
PdfWriter writer = canvases[0].PdfWriter;
// rectangle holds the dimensions and coordinates of the cell that was created
// which you can then use to place the textfield in the correct location
// and optionally fit the textfield to the size of the cell
float textboxheight = 12f;
// modify the rectangle so the textfield isn't the full height of the cell
// in case the cell ends up being tall due to the table layout
Rectangle rect = rectangle;
rect.Bottom = rect.Top - textboxheight;
TextField text = new TextField(writer, rect, fieldname);
// set and options, font etc here
PdfFormField field = text.GetTextField();
writer.AddAnnotation(field);
}
}
Then in your code where you create the table you'll use the event like this:
PdfPCell cell = new PdfPCell()
{
CellEvent = new CustomCellLayout(fieldname)
// set borders, or other cell options here
};
If you want to different kinds of textfields you can either make additional custom events, or you could add extra properties to the CustomCellLayout class like "fontsize" or "multiline" which you'd set with the class constructor, and then check for in the CellLayout code to adjust the textfield properties.
Related
I am generating a PDF invoice report using OpenPDF. On the PDF, I have to set a rectangular block for header/footer on every page. I have used the HeaderFooter class to add header/footer on every page but this works only for a Phrase.
HeaderFooter header = new HeaderFooter(new Phrase("This is a Header."), false);
Is there any way to set a rectangular block with height and width for header/footer using HeaderFooter class?
This is what I am expecting on every page:
You can do this by creating your custom PdfPageEvent where you add the elements whenever a new page is finished (onEndPage-event). The simplest way of doing this is by extending PdfPageEventHelper in a standalone class or in an anonymous class. First, define and style your rectangles. Second, add them to the page using the PdfWriter inside the callback.
Here is a demo showing how to do it:
Document document = new Document(PageSize.A4, 40, 40, 200, 200);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
// footer
final Rectangle footer = new Rectangle(30, 30, PageSize.A4.getRight(30), 180);
footer.setBorder(Rectangle.BOX);
footer.setBorderColor(Color.BLACK);
footer.setBorderWidth(2);
// header
final Rectangle header = new Rectangle(footer);
header.setTop(PageSize.A4.getTop(30));
header.setBottom(PageSize.A4.getTop(180));
// content-box
final Rectangle box = new Rectangle(footer);
box.setTop(document.top());
box.setBottom(document.bottom());
// create and register page event to add the rectangles
writer.setPageEvent(new PdfPageEventHelper() {
#Override
public void onEndPage(PdfWriter writer, Document document) {
PdfContentByte cb = writer.getDirectContent();
cb.rectangle(header);
cb.rectangle(footer);
cb.rectangle(box);
}
});
document.open();
document.add(new Paragraph(LOREM_IPSUM)); // just some constant filler text
document.close();
The result looks like this:
I'm working in some Annotation stuff with iText.
I tried to draw a Stamp Annotation with text on an existing PDF file.
The Stamp Annotation did show on the PDF but when I moving the stamp (or resizing), the text (will all format) is disappear and can't gain it back anymore.
Here is my code
PdfReader reader = new PdfReader(SRC_FILE);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(DEST_FILE));
PdfWriter writer = stamper.getWriter();
BaseColor textColor = BaseColor.ORANGE;
BaseColor fillColor = BaseColor.GRAY;
Rectangle rectangle = new Rectangle(150, 250, 450, 320);
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(writer, rectangle, null, true);
annotation.setColor(textColor);
PdfDictionary dict = new PdfDictionary();
PdfTemplate template = PdfTemplate.createTemplate(writer, rectangle.getWidth(), rectangle.getHeight());
template.setBoundingBox(rectangle);
template.setColorFill(fillColor);
//template.setColorStroke(textColor);
template.setLineWidth(4);
template.rectangle(rectangle.getLeft(), rectangle.getBottom(), rectangle.getWidth(), rectangle.getHeight());
template.closePathFillStroke();
template.setColorFill(textColor);
ColumnText columnText = new ColumnText(template);
columnText.setSimpleColumn(rectangle);
Paragraph p = new Paragraph("This is my test", new Font(Font.FontFamily.HELVETICA, 24, Font.BOLD));
p.setAlignment(Element.ALIGN_CENTER);
p.setLeading(50);
columnText.setAlignment(Element.ALIGN_CENTER);
columnText.addElement(p);
columnText.go();
writer.releaseTemplate(template);
dict.put(PdfName.N, template.getIndirectReference());
annotation.put(PdfName.AP, dict);
annotation.put(PdfName.F, new PdfNumber(4));
stamper.addAnnotation(annotation, 1);
stamper.close();
reader.close();
I attached the Screenshot this issue for your review too.
I did some research and if I change the line code
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(writer, rectangle, null, true);
to
PdfAnnotation annotation= stamper.getWriter().createAnnotation(rectangle, PdfName.FREETEXT);
The text will still there when I moving the Stamp, but still disappear if I resize the Rectangle.
How do I make plain text in a PDF a link to another part of the pdf document?
Currently, I'm post processing a PDF. I've identified two pages that should link pack to each other base on if two numbers (text object) are found in the page.
Is there a way I can convert that text to a clickable local link?
We have checked the reported query "Make text a link/annotation to invoke goto other page action in PDF" and prepared a test sample to meet your requirement. In this sample we have used PdfDocumentLinkAnnotation to navigate the internal document by click on text. Please check the sample and it is available in the below link for your reference.
Please find the sample from the following link.
Also please find the below UG documentation link to more details about PdfDocumentLinkAnnotation.
Code in link:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using Syncfusion.Pdf;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf.Interactive;
namespace ConsoleApplication1
{
class Program
{
public static string DataPathOutput
{
get
{
if (!Directory.Exists(System.Environment.CurrentDirectory + #"\..\..\Output\"))
Directory.CreateDirectory(System.Environment.CurrentDirectory + #"\..\..\Output\");
return System.Environment.CurrentDirectory + #"\..\..\Output\";
}
}
static void Main(string[] args)
{
// Creates a new PDF document
PdfDocument document = new PdfDocument();
// Creates a first page
PdfPage firstPage = document.Pages.Add();
PdfFont font = new PdfStandardFont(PdfFontFamily.Courier, 12f);
PdfBrush brush = PdfBrushes.Black;
PdfGraphics graphics1 = firstPage.Graphics;
string inputText1 = "Sample Text-1";
graphics1.DrawString(inputText1, font, brush, 10, 40);
// Measure string size to use same size for annotation
SizeF size1 = font.MeasureString(inputText1);
RectangleF rectangle1 = new RectangleF(10, 40, size1.Width, size1.Height);
// Creates a second page
PdfPage secondPage = document.Pages.Add();
PdfGraphics graphics2 = secondPage.Graphics;
string secondPageInput = "Sample Text-2";
graphics2.DrawString(secondPageInput, font, brush, 10, 40);
// Measure string size to use same size for annotation
SizeF size2 = font.MeasureString(inputText1);
RectangleF rectangle2 = new RectangleF(10, 40, size2.Width, size2.Height);
// Add annotation for firstpage to link second page of PdfDocumet
PdfDocumentLinkAnnotation firstAnnotation = new PdfDocumentLinkAnnotation(rectangle1);
firstAnnotation.Color = new PdfColor(Color.Transparent);
firstAnnotation.Destination = new PdfDestination(secondPage);
// Use below comment for link specific part of page
//firstAnnotation.Destination.Location = new Point(10, 40);
firstPage.Annotations.Add(firstAnnotation);
// Add annotation for second page to link first page of PdfDocumet
PdfDocumentLinkAnnotation secondAnnotation = new PdfDocumentLinkAnnotation(rectangle2);
secondAnnotation.Color = new PdfColor(Color.Transparent);
secondAnnotation.Destination = new PdfDestination(firstPage);
// Use below comment for link specific part of page
//secondAnnotation.Destination.Location = new Point(10, 40);
secondPage.Annotations.Add(secondAnnotation);
// Save document on mentioned location
document.Save(System.IO.Path.Combine(DataPathOutput, "Output.pdf"));
document.Close(true);
}
}
}
I have a text file that is pre-formatted with spacing and line breaks. I am writing the text out to a blank pdf that has been set to landscape with minimal margins to fit all the text to a single page, however I am still running off the page. Can anyone recommend how I can use itextsharp to dynamically "fit to page" by reducing the font size and/or line-height (lead). I have seen responses about using a textfield or rectangles but I can't seem to get those working properly.
Update: Here is what I have so far that uses no advanced stuff at all, simply margin control and font size adjustments to force my sample text to the page. This works fine if I always have fixed line lengths, but that unfortunately won't be the case. There might be a common max line length I can use across the files but I don't have that data at this time.
private void CreatePDF()
{
string line = string.Empty;
StreamReader sr = new StreamReader(#"C:\dev\text1.txt");
StringBuilder sb = new StringBuilder();
string newFile = #"C:\dev\testPDF1.pdf";
Document pdfDoc = new Document(PageSize.LETTER.Rotate(), 50, 5, 5, 5);
PdfWriter writer = PdfWriter.GetInstance(pdfDoc, new FileStream(newFile, FileMode.OpenOrCreate));
pdfDoc.Open();
while ((line = sr.ReadLine()) != null)
{
if (line != "\f")
{
sb.AppendLine(line);
}
else
{
pdfDoc.Add(new Paragraph(sb.ToString(), new Font(Font.NORMAL, 6)));
pdfDoc.NewPage();
pdfDoc.SetPageSize(PageSize.LETTER.Rotate());
pdfDoc.SetMargins(50, 5, 5, 5);
sb.Clear();
sb.AppendLine("");
}
}
pdfDoc.Add(new Paragraph(sb.ToString(), new Font(Font.NORMAL, 6)));
pdfDoc.Close();
//Console.Write(sb);
}
I'm creating a pie chart using jFreechart and add the chart in pdf created in iText. The problem is chart is always added at the bottom of the page and not after the last line.
A sample code for regenrating the error is:
Document document = new Document();
PdfWriter writer;
File file = new File("c:/myPdf.pdf");
writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
try {
DefaultPieDataset pieDataset = new DefaultPieDataset();
pieDataset.setValue("OPT 1", 10);
pieDataset.setValue("OPT 2", 0);
pieDataset.setValue("OPT 3", 17);
pieDataset.setValue("OPT 4", 11);
JFreeChart chart = ChartFactory.createPieChart3D("Option click count",
pieDataset, true, false, false);
final PiePlot3D plot = (PiePlot3D) chart.getPlot();
plot.setNoDataMessage("No data to display");
chart.setTitle(new TextTitle("Option Click Count", new Font("Times New Roman", Font.PLAIN, 14)));
PdfContentByte pdfContentByte = writer.getDirectContent();
PdfTemplate pdfTemplateChartHolder = pdfContentByte.createTemplate(225,225);
Graphics2D graphicsChart = pdfTemplateChartHolder.createGraphics(225,225,new DefaultFontMapper());
Rectangle2D chartRegion =new Rectangle2D.Double(0,0,225,225);
chart.draw(graphicsChart,chartRegion);
graphicsChart.dispose();
pdfContentByte.addTemplate(pdfTemplateChartHolder,0,0);
} catch (Exception e) {
e.printStackTrace();
}
document.close();
Here the options are fetched from database so not sure on the count of the option. I want to show chart right to the table. How can I do this?
You are adding the chart as a template, and per definition they are added with absolute coordinates.
If you are using floating elements, as I assume you are, you can use com.lowagie.itext.Image (version 2.1), and in newer versions com.itextpdf.text.Image.
You can use the Image class to create the template, and add it as a Element:
See here (iText API).
PdfContentByte pdfContentByte = writer.getDirectContent();
PdfTemplate pdfTemplateChartHolder = pdfContentByte.createTemplate(225,225);
Graphics2D graphicsChart = pdfTemplateChartHolder.createGraphics(225,225,new DefaultFontMapper());
Rectangle2D chartRegion = new Rectangle2D.Double(0,0,225,225);
chart.draw(graphicsChart,chartRegion);
graphicsChart.dispose();
Image chartImage = Image.getInstance(pdfTemplateChartHolder);
document.add(chartImage);
The code example above shows the gist of it. You should as often as possible use Element objects such as Image if you don't want to handle heights and positions absolutely.