how can I draw checked box (with X) with iTextSharp.
I don't want it to be image. More like symbol
I tried this, but it didn't work:
RadioCheckField fCell = new RadioCheckField(writer, new Rectangle(20,20), "NoDeletion", "Yes");
fCell.CheckType = RadioCheckField.TYPE_CROSS;
PdfFormField footerCheck = null;
footerCheck = fCell.CheckField;
writer.AddAnnotation(footerCheck);
Thanks,
I assume that you don't need an interactive check box. You just want to use a check box character. The first thing you need, is a font that has such a character. When I work on Windows, I have access to a file named WINGDING.TTF. This is a font program that contains all kinds of symbols, among others some check boxes:
I created the PDF shown in the screen shot like this:
public static final String DEST = "results/fonts/checkbox_character.pdf";
public static final String FONT = "c:/windows/fonts/WINGDING.TTF";
public static final String TEXT = "o x \u00fd \u00fe";
public void createPdf(String dest) throws IOException, DocumentException {
Document document = new Document();
PdfWriter.GetInstance(document, new FileOutputStream(dest));
document.Open();
BaseFont bf = BaseFont.CreateFont(FONT, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
Font f = new Font(bf, 12);
Paragraph p = new Paragraph(TEXT, f);
document.Add(p);
document.Close();
}
As you can see, the empty check box corresponds with the letter o, there are three variations of a checked check box.
Thank you, but I found a solution. Here it is:
var checkBox = new Phrase();
checkBox.Add(new Chunk(" ☒ ", new Font(BaseFont.CreateFont(PrintCommonConstants.UnicodeFontNormal, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED), 18)));
Related
I'm using iText 7 for printing some text in List (in Hebrew) to PDF file, but while printing the Hebrew characters are printed in a reverse way.
The input given was "קניון אם הדרך" while the data printed in PDF is "ךרדה םא ןוינק"
I have set the font encoding and the base direction for the elements but still the characters are printed in the reverse order.
Code to print list into the table in PDF:
public void PrintListData(string filename)
{
var writer = new PdfWriter(filename);
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc, PageSize.A4);
SetFont(doc);
Table table = new Table(UnitValue.CreatePercentArray(2)).UseAllAvailableWidth();
table.SetTextAlignment(TextAlignment.RIGHT);
//table.SetBaseDirection(BaseDirection.RIGHT_TO_LEFT);
var index = 1;
foreach (var item in _data)
{
var para = new Paragraph(item);
para.SetTextAlignment(TextAlignment.RIGHT);
//para.SetBaseDirection(BaseDirection.RIGHT_TO_LEFT);
table.AddCell(index.ToString());
table.AddCell(para);
index++;
}
doc.Add(table);
doc.Close();
Process.Start(filename);
}
Set font function
void SetFont(Document doc)
{
FontSet _defaultFontSet = new FontSet();
var fontFolders = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
_defaultFontSet.AddFont(System.IO.Path.Combine(fontFolders, "arial.ttf"), PdfEncodings.IDENTITY_H);
_defaultFontSet.AddFont(System.IO.Path.Combine(fontFolders, "arialbd.ttf"), PdfEncodings.IDENTITY_H);
doc.SetFontProvider(new FontProvider(_defaultFontSet));
doc.SetProperty(Property.FONT, new String[] { "MyFontFamilyName" });
//doc.SetProperty(Property.BASE_DIRECTION, BaseDirection.RIGHT_TO_LEFT);
}
I'm not sure to where should we set the text direction to print RTL.
I have the following program that generates an example word document:
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
namespace OpenXmlExample
{
class Program
{
static void Main(string[] args)
{
string filePath = #"C:\Users\[Redacted]\Desktop\OpenXmlExample.docx";
using (WordprocessingDocument document = WordprocessingDocument.Create(filePath, WordprocessingDocumentType.Document))
{
// Create main part and body of document
MainDocumentPart mainPart = document.AddMainDocumentPart();
mainPart.Document = new Document();
Body body = mainPart.Document.AppendChild(new Body());
// Prototype code for generation of the document title
Paragraph paragraph = new Paragraph();
ParagraphProperties pPr = new ParagraphProperties
{
Justification = new Justification { Val = JustificationValues.Center }
};
RunProperties rPr = new RunProperties
{
RunFonts = new RunFonts { ComplexScript = new StringValue("Arial") },
Bold = new Bold { Val = true },
Caps = new Caps { Val = true },
FontSize = new FontSize { Val = "32" },
FontSizeComplexScript = new FontSizeComplexScript { Val = "36" }
};
Text t = new Text("Example Document");
Run r = new Run();
r.Append((OpenXmlElement) rPr.Clone());
r.Append(t);
pPr.Append((OpenXmlElement) rPr.Clone());
paragraph.Append(pPr);
paragraph.Append(r);
body.Append(paragraph);
}
}
}
}
It seems to be working just fine. "EXAMPLE DOCUMENT" is rendered properly, bold and uppercase, with 16pt font. However, the ComplexScript = new StringValue("Arial") part doesn't seem to be working. The text is just rendered in the default font. Can anyone help me to understand if I'm doing something incorrectly? It seems to work if I set the Ascii property to Arial, but I would like it to be generated as a <w:rFonts w:cs="Arial"/> tag.
For a single run, 4 different fonts can be configured.
The use of each of these fonts shall be determined by the Unicode character values of the run content.
ASCII for characters in the Unicode range (U+0000-U+007F).
Complex Script for characters in a complex script Unicode range, eg. Arabic text.
East Asian for characters in an East Asian Unicode range, eg. Japanese.
High ANSI for characters in a Unicode range which does not fall into one of the other categories.
The characters in 'EXAMPLE DOCUMENT' all fall within the ASCII group and will therefore have font of the corresponding group applied.
More details at MSDN and Office Open XML.
There are tips in "iText In Action" that cover setting fonts, as well as the "FontFactory.RegisterDirectories" method (which is, as the book says...an expensive call). However, in my case, the font that I want to use for new fields is already embedded in the document (in an existing Acrofield). With no guarantee that the same font will exist on the user's machine (or on a web server)....is there a way that I can register that already-embedded font, so that I can re-use it for other objects? In the code below, Acrofield "TheFieldIWantTheFontFrom" has the font that I want to re-use for a field named "my_new_field". Any help would be greatly appreciated!
using (MemoryStream output = new MemoryStream())
{
// Use iTextSharp PDF Reader, to get the fields and send to the
//Stamper to set the fields in the document
PdfReader pdfReader = new PdfReader(#"C:\MadScience\MSE_030414.pdf");
// Initialize Stamper (ms is a MemoryStream object)
PdfStamper pdfStamper = new PdfStamper(pdfReader, output);
// Get Reference to PDF Document Fields
AcroFields pdfFormFields = pdfStamper.AcroFields;
//*** CODE THAT HAVE NOT YET BEEN ABLE TO MAKE USE OF TO ASSIST WITH MY FONT ISSUE
//*** MIGHT BE HELP?
//List<object[]> fonts = BaseFont.GetDocumentFonts(pdfReader);
//BaseFont[] baseFonts = new BaseFont[fonts.Count];
//string[] fn = new string[fonts.Count];
//for (int i = 0; i < fonts.Count; i++)
//{
// Object[] obj = (Object[])fonts[i];
// baseFonts[i] = BaseFont.CreateFont((PRIndirectReference)(obj[1]));
// fn[i] = baseFonts[i].PostscriptFontName.ToString();
// //Console.WriteLine(baseFonts[i].FamilyFontName[0][1].ToString());
// //FontFactory.RegisteredFonts.Add(fn[i]);
// //FontFactory.Register(
// Console.WriteLine(fn[i]);
//}
//ICollection<string> registeredFonts = iTextSharp.text.FontFactory.RegisteredFonts;
//foreach (string s in registeredFonts)
//{
// Console.WriteLine("pre-registered: " + s);
//}
if (!FontFactory.Contains("georgia-bold"))
{
FontFactory.RegisterDirectories();
Console.WriteLine("had to register everything"); }
//registeredFonts = iTextSharp.text.FontFactory.RegisteredFonts;
//foreach (string s in registeredFonts)
//{
// Console.WriteLine("post-registered: " + s);
//}
Font myfont = FontFactory.GetFont("georgia-bold");
string nameOfField = "my_field";
AcroFields.Item fld = pdfFormFields.GetFieldItem(nameOfField);
//set the text of the form field
pdfFormFields.SetField(nameOfField, "test stuff");
pdfFormFields.SetField("TheFieldIWantTheFontFrom", "test more stuff");
bool madeit = pdfFormFields.SetFieldProperty(nameOfField, "textfont", myfont.BaseFont, null);
bool madeit2 = pdfFormFields.SetFieldProperty(nameOfField, "textsize", 8f, null);
pdfFormFields.RegenerateField(nameOfField);
// Set the flattening flag to false, so the document can continue to be edited
pdfStamper.FormFlattening = true;
// close the pdf stamper
pdfStamper.Close();
//get the bytes from the MemoryStream
byte[] content = output.ToArray();
using (FileStream fs = File.Create(#"C:\MadScience\MSE_Results.pdf"))
{
//byte[] b = outList[i];
fs.Write(content, 0, (int)content.Length);
fs.Flush();
}
}
Yes you can re-use fonts and the PDF specification actually encourages it. You should, however, keep in mind that some fonts may be embedded as subsets only.
The below code is adapted from this post (be careful, that site has nasty popups sometimes). See the comments in the code for more information. This code was tested against iTextSharp 5.4.4.
/// <summary>
/// Look for the given font name (not file name) in the supplied PdfReader's AcroForm dictionary.
/// </summary>
/// <param name="reader">An open PdfReader to search for fonts in.</param>
/// <param name="fontName">The font's name as listed in the PDF.</param>
/// <returns>A BaseFont object if the font is found or null.</returns>
static BaseFont findFontInForm(PdfReader reader, String fontName) {
//Get the document's acroform dictionary
PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(reader.Catalog.Get(PdfName.ACROFORM));
//Bail if there isn't one
if (acroForm == null) {
return null;
}
//Get the resource dictionary
var DR = acroForm.GetAsDict(PdfName.DR);
//Get the font dictionary (required per spec)
var FONT = DR.GetAsDict(PdfName.FONT);
//Look for the actual font and return it
return findFontInFontDict(FONT, fontName);
}
/// <summary>
/// Helper method to look at a specific font dictionary for a given font string.
/// </summary>
/// <remarks>
/// This method is a helper method and should not be called directly without knowledge of
/// the internals of the PDF spec.
/// </remarks>
/// <param name="fontDict">A /FONT dictionary.</param>
/// <param name="fontName">Optional. The font's name as listed in the PDF. If not supplied then the first font found is returned.</param>
/// <returns>A BaseFont object if the font is found or null.</returns>
static BaseFont findFontInFontDict(PdfDictionary fontDict, string fontName) {
//This code is adapted from http://osdir.com/ml/java.lib.itext.general/2004-09/msg00018.html
foreach (var internalFontName in fontDict.Keys) {
var internalFontDict = (PdfDictionary)PdfReader.GetPdfObject(fontDict.Get(internalFontName));
var baseFontName = (PdfName)PdfReader.GetPdfObject(internalFontDict.Get(PdfName.BASEFONT));
//// compare names, ignoring the initial '/' in the baseFontName
if (fontName == null || baseFontName.ToString().IndexOf(fontName) == 1) {
var iRef = (PRIndirectReference)fontDict.GetAsIndirectObject(internalFontName);
if (iRef != null) {
return BaseFont.CreateFont(iRef);
}
}
}
return null;
}
And here's the test code that runs this. It first creates a sample document with an embedded font and then it creates a second document based upon that and re-uses that font. In your code you'll need to actually know beforehand what the font name is that you're searching for. If you don't have ROCK.TTF (Rockwell) installed you'll need to pick a different font file to run this.
//Test file that we'll create with an embedded font
var file1 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
//Secondary file that we'll try to re-use the font above from
var file2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test2.pdf");
//Path to font file that we'd like to use
var fontFilePath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "ROCK.TTF");
//Create a basefont object
var font = BaseFont.CreateFont(fontFilePath, BaseFont.WINANSI, true);
//Get the name that we're going to be searching for later on.
var searchForFontName = font.PostscriptFontName;
//Step #1 - Create sample document
//The below block creates a sample PDF file with an embedded font in an AcroForm, nothing too special
using (var fs = new FileStream(file1, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Create our field, set the font and add it to the document
var tf = new TextField(writer, new iTextSharp.text.Rectangle(50, 50, 400, 150), "first-name");
tf.Font = font;
writer.AddAnnotation(tf.GetTextField());
doc.Close();
}
}
}
//Step #2 - Look for font
//This uses a stamper to draw on top of the existing PDF using a font already embedded
using (var fs = new FileStream(file2, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var reader = new PdfReader(file1)) {
using (var stamper = new PdfStamper(reader, fs)) {
//Try to get the font file
var f = findFontInForm(reader, searchForFontName);
//Make sure we found something
if (f != null) {
//Draw some text
var cb = stamper.GetOverContent(1);
cb.BeginText();
cb.MoveText(200, 400);
cb.SetFontAndSize(f, 72);
cb.ShowText("Hello!");
cb.EndText();
}
}
}
}
EDIT
I made a small modification to the findFontInFontDict method above. The second parameter is now optional. If null it returns the first font object that it finds in the supplied dictionary. This change allows me to introduce the below method which looks for a specific field by name and gets the font.
static BaseFont findFontByFieldName(PdfReader reader, String fieldName) {
//Get the document's acroform dictionary
PdfDictionary acroForm = (PdfDictionary)PdfReader.GetPdfObject(reader.Catalog.Get(PdfName.ACROFORM));
//Bail if there isn't one
if (acroForm == null) {
return null;
}
//Get the fields array
var FIELDS = acroForm.GetAsArray(PdfName.FIELDS);
if (FIELDS == null || FIELDS.Length == 0) {
return null;
}
//Loop through each field reference
foreach (var fieldIR in FIELDS) {
var field = (PdfDictionary)PdfReader.GetPdfObject(fieldIR);
//Check the field name against the supplied field name
if (field.GetAsString(PdfName.T).ToString() == fieldName) {
//Get the resource dictionary
var DR = acroForm.GetAsDict(PdfName.DR);
//Get the font dictionary (required per spec)
var FONT = DR.GetAsDict(PdfName.FONT);
return findFontInFontDict(FONT);
}
}
return null;
}
Because I use dynamic text, italic or bold text could be any where, cutting everything into chunks is not an option, so I have to use html parser.
Input string is
ąčęėįšųū90-žthis <i>is <b>bold ąčęėįšųū90-ž</i></b> text
String is formatted with iTextSharp html parser:
private Paragraph CreateSimpleHtmlParagraph(String text)
{
//Our return object
List<Chunk> c = new List<Chunk>();
Paragraph p = new Paragraph();
var styles = new StyleSheet();
using (StringReader sr = new StringReader(text))
{
//Parse and get a collection of elements
List<IElement> elements = iTextSharp.text.html.simpleparser.HTMLWorker.ParseToList(sr, styles);
foreach (IElement e in elements)
{
var chunks = e.Chunks;
foreach (var chunk in chunks) //list of chunks
{
chunk.Font.SetFamily(""); //how to set font family here
}
p.Add(e);
}
}
return p; //getting all the special chars (ąčęėįšųū90-ž...)
}
Code in the main form:
Paragraph pr1 = CreateSimpleHtmlParagraph("ąčęėįšųū90-žthis <i>is <b>bold ąčęėįšųū90-ž</i></b> text");
doc.Add(pr1);
But in PDF I see only
š90-žthis is bold š90-ž text
and no other chars (ąčęėį). I know it has something to do with Fonts, but can't find the problem where. The font should be the same for whole document, times new roman, arial, ect., anything, that could show me my special chars (cp1257, Baltic encoding).
Usually, when I have to format text I use Chunks and my own fonts:
Font arial10n = PdfFontManager.GetFont("c:\\windows\\fonts\\arial.ttf", 10);
colClientTxt.AddText(new Chunk(row["name"].ToString() + "\n", arial10n));
and in PdfFontManager class:
public static Font GetFont(string name, int size)
{
BaseFont baseFont = BaseFont.CreateFont(name, BaseFont.CP1257, BaseFont.EMBEDDED);
Font font = new Font(baseFont, size);
return font;
}
So, how to set font family, or maybe there is another way to dinamicaly format my text?
I want to create pdf file in c#. Pdf file contains text files and images. I want to arrange that text files and images at runtime and after arranging I want to save it as .pdf file. Please help me.
Thanks in advance.
You should try: http://itextpdf.com/
I net there is a lot examples how to use it for purpose you described.
Try This,
you need to download wnvhtmlconvert.dll
to use pdfconverter class
--html side
<table id="tbl" runat="server" style="width: 940px;" cellpadding="0" cellspacing="0" border="0">
<tr id="tr" runat="server">
<td id="td" runat="server" align="center" valign="top"></td>
</tr>
</table>
--code side
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.IO
Imports System.Collections.Generic
Imports System.Drawing
Public Sub ExportQuickScToPDF()
Dim stringWrite As New System.IO.StringWriter()
Dim htmlWrite As System.Web.UI.HtmlTextWriter = New HtmlTextWriter(stringWrite)
Dim pdfByte As [Byte]() = Nothing
Dim strPageBreak As String = "<br style=""page-break-before: always"" />"
Dim lblPageBreak As New Label
Dim lbltext As New Label
lblPageBreak.Text = strPageBreak
'add image
Dim imgqsc As New System.Web.UI.WebControls.Image
imgqsc.ImageUrl = "path"
td.Controls.Add(imgqsc)
tbl.RenderControl(htmlWrite)
'add text
lbltext.Text = "text"
lbltext.RenderControl(htmlWrite)
'add page break
lblPageBreak.Text = "text"
lblPageBreak.RenderControl(htmlWrite)
Dim objPdf As New PdfConverter()
objPdf.LicenseKey = "license key with dll"
objPdf.PdfFooterOptions.ShowPageNumber = False
objPdf.PdfFooterOptions.FooterTextFontSize = 10
objPdf.PdfDocumentOptions.ShowHeader = True
objPdf.PdfDocumentOptions.ShowFooter = False
objPdf.PdfDocumentOptions.EmbedFonts = True
objPdf.PdfDocumentOptions.LiveUrlsEnabled = True
objPdf.RightToLeftEnabled = False
objPdf.PdfSecurityOptions.CanPrint = True
objPdf.PdfSecurityOptions.CanEditContent = True
objPdf.PdfSecurityOptions.UserPassword = ""
objPdf.PdfDocumentOptions.PdfPageOrientation = PDFPageOrientation.Landscape
objPdf.PdfDocumentInfo.CreatedDate = DateTime.Now
objPdf.PdfDocumentInfo.AuthorName = ""
pdfByte = objPdf.GetPdfBytesFromHtmlString(stringWrite.ToString())
Session("pdfByte") = pdfByte
End Sub
you need to add reference of that dll
and also import it in code
Imports Winnovative.WnvHtmlConvert
You can use iTextSharp. There are some other libraries as well. Click here.
To create PDF i use 'iText' library, is open and it's really easy to use.
You can download iText here.
Me votes for iText too :) Rather easy and comfortable to start with:
string pdfFilename = #"c:\temp\test.pdf";
string imageFilename = #"C:\map.jpg";
// Create PDF writer, document and image to put
iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(imageFilename);
Document doc = new Document();
PdfWriter pdfW = PdfWriter.GetInstance(doc, new FileStream(pdfFilename, FileMode.Create));
// Open created PDF and insert image to it
doc.Open();
doc.Add(image);
doc.Close();
// paste on button click
Document pdfDoc = new Document(PageSize.A4, 25, 10, 25, 10);
PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, Response.OutputStream);
pdfDoc.Open();
Paragraph Text = new Paragraph("This is test file"); // hardcode text
pdfDoc.Add(new Phrase(this.lbl1.Text.Trim())); //from label
pdfDoc.Add(new Phrase(this.txt1.Text.Trim())); //from textbox
pdfDoc.Add(Text);
pdfWriter.CloseStream = false;
pdfDoc.Close();
Response.Buffer = true;
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=Example.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Write(pdfDoc);
Response.End();
Try to download and add the reference of bytescout then use this code :
using System.Diagnostics;
using Bytescout.PDF;
namespace WordSpacing
{
/// <summary>
/// This example demonstrates how to change the word spacing.
/// </summary>
class Program
{
static void Main()
{
// Create new document
Document pdfDocument = new Document();
pdfDocument.RegistrationName = "demo";
pdfDocument.RegistrationKey = "demo";
// Add page
Page page = new Page(PaperFormat.A4);
pdfDocument.Pages.Add(page);
Canvas canvas = page.Canvas;
Font font = new Font("Arial", 16);
Brush brush = new SolidBrush();
StringFormat stringFormat = new StringFormat();
// Standard word spacing
stringFormat.WordSpacing = 0.0f;
canvas.DrawString("Standard word spacing 0.0", font, brush, 20, 20, stringFormat);
// Increased word spacing
stringFormat.WordSpacing = 5.0f;
canvas.DrawString("Increased word spacing 5.0", font, brush, 20, 50, stringFormat);
// Reduced word spacing
stringFormat.WordSpacing = -2.5f;
canvas.DrawString("Reduced word spacing -2.5", font, brush, 20, 80, stringFormat);
// Save document to file
pdfDocument.Save("result.pdf");
// Cleanup
pdfDocument.Dispose();
// Open document in default PDF viewer app
Process.Start("result.pdf");
}
}
}
At first get reference, then try to use this code
using System.Runtime.InteropServices;
[DllImport("shell32.dll")]
public static extern int ShellExecute(int hWnd,
string lpszOp, string lpszFile, string lpszParams, string lpszDir,int FsShowCmd);
ShellExecute(0, "OPEN", args[0] + ".pdf", null, null, 0);
Or use this sharppdf or this itextsharp