How does one add a PDF Form element to a PDFsharp PdfPage object?
I understand that AcroForm is the best format for form-fillable PDF elements, but the PDFsharp library doesn't seem to allow you to create instances of the AcroForm objects.
I have been able to use PDFsharp to generate simple documents, as here:
static void Main(string[] args) {
PdfDocument document = new PdfDocument();
document.Info.Title = "Created with PDFsharp";
// Create an empty page
PdfPage page = document.AddPage();
// Draw Text
XGraphics gfx = XGraphics.FromPdfPage(page);
XFont font = new XFont("Verdana", 20, XFontStyle.BoldItalic);
gfx.DrawString("Hello, World!", font, XBrushes.Black,
new XRect(0, 0, page.Width, page.Height), XStringFormats.Center);
// Save document
const string filename = "HelloWorld.pdf";
document.Save(filename);
}
But I cannot work out how to add a fillable form element. I gather it would likely use the page.Elements.Add(string key, PdfItem item) method, but how do you make an AcroForm PdfItem? (As classes like PdfTextField do not seem to have a public constructor)
The PDFsharp forums and documentation have not helped with this, and the closest answer I found on Stack Overflow was this one, which is answering with the wrong library.
So, in short: How would I convert the "Hello World" text above into a text field?
Is it possible to do this in PDFsharp, or should I be using a different C# PDF library? (I would very much like to stick with free - and preferably open-source - libraries)
Most of the classes constructors in PdfSharp are sealed which makes it kind of difficult to create new pdf objects. However, you can create objects using it's classes to add low-level pdf elements.
Below is an example of creating a text field.
Please refer to the pdf tech specs starting on page 432 on definition of key elements
https://www.adobe.com/content/dam/acom/en/devnet/pdf/pdfs/PDF32000_2008.pdf
public static void AddTextBox()
{
using (PdfDocument pdf = new PdfDocument())
{
PdfPage page1 = pdf.AddPage();
double left = 50;
double right = 200;
double bottom = 750;
double top = 725;
PdfArray rect = new PdfArray(pdf);
rect.Elements.Add(new PdfReal(left));
rect.Elements.Add(new PdfReal(bottom));
rect.Elements.Add(new PdfReal(right));
rect.Elements.Add(new PdfReal(top));
pdf.Internals.AddObject(rect);
PdfDictionary form = new PdfDictionary(pdf);
form.Elements.Add("/Filter", new PdfName("/FlateDecode"));
form.Elements.Add("/Length", new PdfInteger(20));
form.Elements.Add("/Subtype", new PdfName("/Form"));
form.Elements.Add("/Type", new PdfName("/XObject"));
pdf.Internals.AddObject(form);
PdfDictionary appearanceStream = new PdfDictionary(pdf);
appearanceStream.Elements.Add("/N", form);
pdf.Internals.AddObject(appearanceStream);
PdfDictionary textfield = new PdfDictionary(pdf);
textfield.Elements.Add("/FT", new PdfName("/Tx"));
textfield.Elements.Add("/Subtype", new PdfName("/Widget"));
textfield.Elements.Add("/T", new PdfString("fldHelloWorld"));
textfield.Elements.Add("/V", new PdfString("Hello World!"));
textfield.Elements.Add("/Type", new PdfName("/Annot"));
textfield.Elements.Add("/AP", appearanceStream);
textfield.Elements.Add("/Rect", rect);
textfield.Elements.Add("/P", page1);
pdf.Internals.AddObject(textfield);
PdfArray annotsArray = new PdfArray(pdf);
annotsArray.Elements.Add(textfield);
pdf.Internals.AddObject(annotsArray);
page1.Elements.Add("/Annots", annotsArray);
// draw rectangle around text field
//XGraphics gfx = XGraphics.FromPdfPage(page1);
//gfx.DrawRectangle(new XPen(XColors.DarkOrange, 2), left, 40, right, bottom - top);
// Save document
const string filename = #"C:\Downloads\HelloWorld.pdf";
pdf.Save(filename);
pdf.Close();
Process.Start(filename);
}
}
Related
I'm using the iTextSharp library to convert my html to pdf. The issue is I'm trying to add checkbox appearance using the below code:
string HTML,public static String FONT = "c:/windows/fonts/WINGDING.TTF";
public static String TEXT = "o";
public void HTMLToPdf( string FileName)
{
string HTML="<!DOCTYPE html>
<html>
<head><title></title><meta charset='UTF-8'></head>
<body><div class='mystyle'>Here i want to print many checkbox lik appearances</div></body>
<html>";
Document pdfDoc = new Document(PageSize.A4, 30f, 30f, 10f, 10f);
pdfDoc.Add(p);
BaseFont bf = BaseFont.CreateFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font f = new Font(bf, 12);
Paragraph p = new Paragraph(TEXT, f);
pdfDoc.Add(p);
}
The problem is this method adds the checkbox at the begining of pdf, please help me to attach the paragraph containing the checkbox value to my html.
Simply put, I'm getting the value at pdfDoc.Add(p), but I want it in a variable to print it many times in html.
In fact, it is not very clear what was meant in the question:
please help me to attach the paragraph containing the checkbox value to my html
I can assume that you wanted to convert HTML to PDF, and add paragraphs on the next line.
In general, it's a bad idea to use iTextSharp for this, since this library is outdated and no longer supported. I can suggest my own way of solving your problem in pdfHTML, this is an iText7 add-on. My code is in Java, but it's not much different from sharp.The main idea is not to close the document after html conversion. Because if you try to write a paragraph in a closed document, it will be at the very beginning, as in your example.
String FONT = "c:/windows/fonts/WINGDING.TTF";
String TEXT = "o";
File htmlSource = new File("checkBoxHtml.html");
File pdfDest = new File("output.pdf");
ConverterProperties converterProperties = new ConverterProperties();
Document document = HtmlConverter.convertToDocument(new FileInputStream(htmlSource),
new PdfDocument(new PdfWriter(pdfDest)), converterProperties);
PdfFont font = PdfFontFactory.createFont(FONT);
Text text = new Text(TEXT);
text.setFont(font);
Paragraph paragraph = new Paragraph();
// Adding text to the paragraph
paragraph.add(text);
// Adding paragraph to the document
document.add(paragraph);
document.close();
I convert HTML to PDF, but when i look PDF it has 2 page because content is a bit longer for one page. But i want to fit content to one page.
I tried this but it doesn't help me.
PdfDocument pdf = new PdfDocument();
pdf.LoadFromFile(pdfPath);
PdfDocument newPdf = new PdfDocument();
foreach (PdfPageBase page in pdf.Pages)
{
PdfPageBase newPage = newPdf.Pages.Add(PdfPageSize.A1, new Spire.Pdf.Graphics.PdfMargins(0));
PdfTextLayout loLayout = new PdfTextLayout();
loLayout.Layout = PdfLayoutType.OnePage;
page.CreateTemplate().Draw(newPage, new PointF(0, 0), loLayout);
}
newPdf.SaveToFile(newPdfPath);
I have a simple questions. How can you show a PDf file by using PagePreview?
I have a full pathname document.FileName = "c:\scans\Insurance_34345.pdf";
pagePreview.Preview(document.FileName); or something...
If there another way for showing a pdf. It's okay. I want to show it on a WinForms Form.
I tried this. I don't know what I have to do...
in the Designer
private MigraDoc.Rendering.Forms.DocumentPreview dpvScannedDoc;
Part of the code
string fullPadnaam = Path.Combine(defaultPath, document.FileName);
//PdfDocument pdfDocument = new PdfDocument(fullPadnaam);
//PdfPage page = new PdfPage(pdfDocument);
//XGraphics gfx = XGraphics.FromPdfPage(page);
MigraDoc.DocumentObjectModel.Document pdfDocument = new MigraDoc.DocumentObjectModel.Document();
pdfDocument.ImagePath = fullPadnaam;
var docRenderer = new DocumentRenderer(pdfDocument);
docRenderer.PrepareDocument();
var inPdfDoc = PdfReader.Open(fullPadnaam, PdfDocumentOpenMode.ReadOnly);
for (var i = 0; i < inPdfDoc.PageCount; i++)
{
pdfDocument.AddSection();
docRenderer.PrepareDocument();
var page = inPdfDoc.Pages[i];
var gfx = XGraphics.FromPdfPage(page);
docRenderer.RenderPage(gfx, i + 1);
}
var renderer = new PdfDocumentRenderer();
renderer.Document = pdfDocument;
renderer.RenderDocument();
// MigraDoc.DocumentObjectModel.IO.DdlWriter dw = new MigraDoc.DocumentObjectModel.IO.DdlWriter("HelloWorld.mdddl");
// dw.WriteDocument(pdfDocument);
// dw.Close();
//renderer.PdfDocument.rea(outFilePath);
//string ddl = MigraDoc.DocumentObjectModel.IO.DdlWriter.WriteToString(document1);
dpvScannedDoc.Show( pdfDocument);
PDFsharp does not render PDF files. You cannot show PDF files using the PagePreview.
If you use the XGraphics class for drawing then you can use shared code that draws on the PagePreview and on PDF pages.
The PagePreview sample can be found in the sample package and here:
http://www.pdfsharp.net/wiki/Preview-sample.ashx
If you have code that creates a new PDF file using PDFsharp then you can use the PagePreview to show on screen what you would otherwise draw on PDF pages. You cannot draw existing PDF pages using the PagePreview because PDF does not render PDF.
The MigraDoc DocumentPreview can display MDDDL files (your sample code creates a file "HelloWorld.mdddl"), but it cannot display PDF files.
If the MDDDL uses PDF files as images, they will not show up in the preview. They will show when creating a PDF from the MDDDL.
I have this code which I merged and modified for my needs. But I still can't make it work as I need. The first part that I made, it generates PDF with an option from aspx page chosen. Second, I need to have the background over the page, so I added next code, but now it generates just the second code and not the PDF. And im not able to merge those codes together.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;
public partial class CreatePDFFromScratch : System.Web.UI.Page
{
protected void btnCreatePDF_Click(object sender, EventArgs e)
{
// Create a Document object
var document = new Document(iTextSharp.text.PageSize.LETTER.Rotate(), 0f, 0f, 0f, 0f);
// Create a new PdfWrite object, writing the output to a MemoryStream
var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, output);
// Open the Document for writing
document.Open();
// First, create our fonts..
var titleFont = FontFactory.GetFont("Arial", 18, Font.BOLD);
var subTitleFont = FontFactory.GetFont("Arial", 14, Font.BOLD);
var boldTableFont = FontFactory.GetFont("Arial", 12, Font.BOLD);
var endingMessageFont = FontFactory.GetFont("Arial", 10, Font.ITALIC);
var bodyFont = FontFactory.GetFont("Arial", 12, Font.NORMAL);
// Add the "Northwind Traders Receipt" title
document.Add(new Paragraph("Northwind Traders Receipt", titleFont));
// Now add the "Thank you for shopping at Northwind Traders. Your order details are below." message
document.Add(new Paragraph("Thank you for shopping at Northwind Traders. Your order details are below.", bodyFont));
document.Add(Chunk.NEWLINE);
// Add the "Order Information" subtitle
document.Add(new Paragraph("Order Information", subTitleFont));
// Create the Order Information table
var orderInfoTable = new PdfPTable(2);
orderInfoTable.HorizontalAlignment = 0;
orderInfoTable.SpacingBefore = 10;
orderInfoTable.SpacingAfter = 10;
orderInfoTable.DefaultCell.Border = 0;
orderInfoTable.SetWidths(new int[] { 1, 4 });
orderInfoTable.AddCell(new Phrase("Order:", boldTableFont));
orderInfoTable.AddCell(txtOrderID.Text);
orderInfoTable.AddCell(new Phrase("Price:", boldTableFont));
orderInfoTable.AddCell(Convert.ToDecimal(txtTotalPrice.Text).ToString("c"));
document.Add(orderInfoTable);
// Add the "Items In Your Order" subtitle
document.Add(new Paragraph("Items In Your Order", subTitleFont));
// Create the Order Details table
var orderDetailsTable = new PdfPTable(3);
orderDetailsTable.HorizontalAlignment = 0;
orderDetailsTable.SpacingBefore = 10;
orderDetailsTable.SpacingAfter = 35;
orderDetailsTable.DefaultCell.Border = 0;
orderDetailsTable.AddCell(new Phrase("Item #:", boldTableFont));
orderDetailsTable.AddCell(new Phrase("Item Name:", boldTableFont));
orderDetailsTable.AddCell(new Phrase("Qty:", boldTableFont));
foreach (System.Web.UI.WebControls.ListItem item in cblItemsPurchased.Items)
if (item.Selected)
{
// Each CheckBoxList item has a value of ITEMNAME|ITEM#|QTY, so we split on | and pull these values out...
var pieces = item.Value.Split("|".ToCharArray());
orderDetailsTable.AddCell(pieces[1]);
orderDetailsTable.AddCell(pieces[0]);
orderDetailsTable.AddCell(pieces[2]);
}
document.Add(orderDetailsTable);
// Add ending message
var endingMessage = new Paragraph("Thank you for your business! If you have any questions about your order, please contact us at 800-555-NORTH.", endingMessageFont);
endingMessage.SetAlignment("Center");
document.Add(endingMessage);
document.Close();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", string.Format("inline;filename=Receipt-{0}.pdf", txtOrderID.Text));
///create background
Response.BinaryWrite(output.ToArray());
Response.Cache.SetCacheability(HttpCacheability.NoCache);
string imageFilePath = Server.MapPath(".") + "/images/1.jpg";
iTextSharp.text.Image jpg = iTextSharp.text.Image.GetInstance(imageFilePath);
Document pdfDoc = new Document(iTextSharp.text.PageSize.LETTER.Rotate(), 0, 0, 0, 0);
jpg.ScaleToFit(790, 777);
jpg.Alignment = iTextSharp.text.Image.UNDERLYING;
pdfDoc.Open();
pdfDoc.NewPage();
pdfDoc.Add(jpg);
pdfDoc.Close();
Response.Write(pdfDoc);
Response.End();
}
}
Thanks
I almost missed this question because it wasn't tagged as an itext question.
First let me copy/paste/adapt #mkl's comment:
The first part of your code in which you create a document document makes sense.
The second part in which you create a document pdfDoc does not.
First of all, at the end of the first part you write the pdf to
the response. That PDF is complete. It's finished. It's done.
It's ready to send to the browser.
Why do you think anything additional written to the
response thereafter might have a chance of combining with the original
written data to a properly generated PDF?
Also: the second part of your code is
written as if you want to create a new PDF from scratch; but didn't you
want to manipulate the PDF created in the first part?
All of this is true, but it doesn't solve your problem. It only reveals your deep lack of understanding in PDF.
There are different ways to achieve what you want. I see that you want to use an image as a background of all the pages of a newly created PDF. In that case, you should create a page event, and add that image underneath all the existing content in the OnEndPage() method. This is explained in the answer to How can I add an image to all pages of my PDF?
Create a PDF as is done in the first part of your code, but introduce a page event:
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.GetInstance(document, stream);
MyEvent event = new MyEvent();
writer.PageEvent = event;
// step 3
document.Open();
// step 4
// Add whatever content you want to add
// step 5
document.Close();
What is the MyEvent class, you might ask? Well, that's a class you create yourself like this:
protected class MyEvent : PdfPageEventHelper {
Image image;
public override void OnOpenDocument(PdfWriter writer, Document document) {
image = Image.GetInstance(Server.MapPath("~/images/background.png"));
image.SetAbsolutePosition(0, 0);
}
public override void OnEndPage(PdfWriter writer, Document document) {
writer.DirectContent.AddImage(image);
}
}
Suppose that your requirement isn't as easy as adding an image in the background, then you could use the bytes created as output to create a PdfReader instance. You could then use the PdfReader to create a PdfStamper and you can use the PdfStamper to watermark the original document. If the simple solution doesn't meet your needs, create a new question that involves PdfReader/PdfStamper and don't forget to tag that question as an iText question. (And also: please read the documentation. A lot of time was spent on the iText web site. That time was wasted if you don't consult it.)
I'm trying to build pdfs to digitize our reporting system at my company. I've used iTextSharp and so far it looks great but my margins don't seem to be working properly. I've set the margins to a config file and the left and right margins are working great, but my paragraph seems to start about 30% down the page regardless of the top and bottom margin. Here's the code I'm using:
public int PrintPdf()
{
//Getting the path
//Path.GetFileNameWithoutExtension("Test_Doc_Print") + ".pdf");
object OutputFileName = this._path;
//Making the PDF Doc
iTextSharp.text.Document PDFReport = new iTextSharp.text.Document
(
PageSize.A4.Rotate(),
/*this._left,
this._right,
this._top,
this._bottom*/
10,
10,
10,
10
);
//Setting The Font
string fontpath = #"C:\Windows\Fonts\";
BaseFont monoFont = BaseFont.CreateFont(fontpath + "Consola.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);
Font fontPDF = new Font(monoFont, this._fontSize);
// create file stream for writing the PDF
FileStream fs = new FileStream(this._path, FileMode.Create, FileAccess.ReadWrite);
//FileStream fs = new FileStream(#"c:\\Reportlocation", FileMode.Create);
// Create an FCFC scan object to convert TextToPrint page at a time
FCFCScanner page = new FCFCScanner(this._text);
// Create PDF writer and associate with file stream
//iTextSharp.text.pdf.PdfWriter writer = new iTextSharp.text.pdf.PdfWriter.GetInstance(PDFReport, fs);
PdfWriter writer = PdfWriter.GetInstance(PDFReport, fs);
//Opening the PDF Doc
PDFReport.Open();
//Load each page from the string into the PDF
page.NextPage();
do
{
if (page.PageLength > 0)
{
Paragraph prg = new Paragraph(page.Page, fontPDF);
PDFReport.Add(prg);
PDFReport.NewPage();
page.NextPage();
}
} while (page.MorePages);
PDFReport.Close();
return (0);
}
I've set the margins to 10 (hardcoded for now) to show what I'm working with. This program should read a string that I send it from my StringBuider class.
It's designed to receive one page of text at a time and to convert it into a PDF document.
Ok, so the problem: when the page is built, the first paragraph doesn't begin at the top margin. If I reduce the margin, it doesn't shift the paragraph up to the new margin. It's causing my PDFs to be much longer as the text that fits easily on a printer page takes two PDF pages. Any help with getting my paragraph to simply begin at the top margin would be really appreciated.
I'm relatively new to programming and this is my first post, so if you need more information, let me know and I'll add more info.