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
Related
I added a sample project to reproduce the problem to the GitHub repo, I hope this helps:
Click to go to the Github repo
I need to add text and a number of page to a PDF, this PDF is from an invoice.
I already tried using events (but the examples are for java, and are incomplete, or I think they are), and it's not working, I'm getting the same error, and in that way text cannot be aligned.
As I said, I've trying to achieve this using a table and a canvas, the code works fine if the PDF has only one page.
But with more than one page I get this error:
This exception was originally thrown at this call stack: KernelExtensions.Get<TKey,
TValue>(System.Collections.Generic.IDictionary, TKey)
iText.Kernel.Pdf.PdfDictionary.Get(iText.Kernel.Pdf.PdfName, bool)
iText.Kernel.Pdf.PdfDictionary.GetAsNumber(iText.Kernel.Pdf.PdfName)
iText.Kernel.Pdf.PdfPage.GetRotation()
iText.Kernel.Pdf.Canvas.PdfCanvas.PdfCanvas(iText.Kernel.Pdf.PdfPage)
BoarGiveMeMoar.Invoices.InvoiceToPdf.AddFooter(iText.Layout.Document)
in InvoiceToPdf.cs
BoarGiveMeMoar.Invoices.InvoiceToPdf.FillPdf.AnonymousMethod__4() in InvoiceToPdf.cs
System.Threading.Tasks.Task.InnerInvoke() in Task.cs
System.Threading.Tasks.Task..cctor.AnonymousMethod__274_0(object) in Task.cs
System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread,
System.Threading.ExecutionContext, System.Threading.ContextCallback,
object) in ExecutionContext.cs
...
[Call Stack Truncated]
This is my code, but I get the error from above:
private readonly int smallFontSize = 6;
private readonly int stdFontSize = 7;
public void FillPdf(string filename)
{
using var pdfWriter = new PdfWriter(filename);
using var pdfDoc = new PdfDocument(pdfWriter);
using var doc = new Document(pdfDoc, PageSize.LETTER);
doc.SetMargins(12, 12, 36, 12);
AddData(doc);
AddFooter(doc);
doc.Close();
}
private void AddData(Document doc)
{
Table table = new Table(UnitValue.CreatePercentArray(5)).UseAllAvailableWidth();
PdfFont bold = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD);
for (int i = 0; i < 250; i++)
{
var cell = new Cell(1, 5)
.Add(new Paragraph($"My Favorite animals are boars and hippos")
.SetFontSize(stdFontSize).SetFont(bold));
cell.SetBorder(Border.NO_BORDER);
cell.SetPadding(0);
table.AddCell(cell);
}
doc.Add(table);
}
private void AddFooter(Document doc)
{
if (doc is null)
return;
Table table = new Table(UnitValue.CreatePercentArray(60)).UseAllAvailableWidth();
int numberOfPages = doc.GetPdfDocument().GetNumberOfPages();
for (int i = 1; i <= numberOfPages; i++)
{
PdfPage page = doc.GetPdfDocument().GetPage(i);
PdfCanvas pdfCanvas = new PdfCanvas(page);
Rectangle rectangle = new Rectangle(
0,
0,
page.GetPageSize().GetWidth(),
15);
Canvas canvas = new Canvas(pdfCanvas, doc.GetPdfDocument(), rectangle);
var cell = new Cell(1, 20).SetFontSize(smallFontSize);
cell.SetBorder(Border.NO_BORDER);
cell.SetPadding(0);
table.AddCell(cell);
cell = new Cell(1, 20).Add(new Paragraph("This document is an invoice")
.SetTextAlignment(TextAlignment.CENTER)).SetFontSize(smallFontSize);
cell.SetBorder(Border.NO_BORDER);
cell.SetPadding(0);
table.AddCell(cell);
cell = new Cell(1, 10).SetFontSize(smallFontSize);
cell.SetBorder(Border.NO_BORDER);
cell.SetPadding(0);
table.AddCell(cell);
cell = new Cell(1, 7)
.Add(new Paragraph($"Page {string.Format(CultureInfo.InvariantCulture, "{0:#,0}", i)} of {string.Format(CultureInfo.InvariantCulture, "{0:#,0}", numberOfPages)} ")
.SetTextAlignment(TextAlignment.RIGHT)).SetFontSize(smallFontSize);
cell.SetBorder(Border.NO_BORDER);
cell.SetPadding(0);
table.AddCell(cell);
cell = new Cell(1, 3).SetFontSize(smallFontSize);
cell.SetBorder(Border.NO_BORDER);
cell.SetPadding(0);
table.AddCell(cell);
canvas.Add(table).SetFontSize(smallFontSize);
canvas.Close();
}
}
Example way to call the code:
new InvoiceToPdf()
.FillPdf(#$"{Environment.GetFolderPath(Environment.SpecialFolder.Desktop)}\StackOverflow Invoice Test.pdf");
I get an error on this line that creates a new PdfCanvas
PdfCanvas pdfCanvas = new PdfCanvas(page);
So, anyone of you has a solution?
By default to decrease memory consumption a bit the pages of the PDF document you are creating are flushed as they fill up.
It means that when the content is written e.g. on page 3 of the document, the content of the page 1 is already written to the disk and it's too late to add more content there.
One option is to first create a document and close it, then open it with reader and writer, i.e.: new PdfDocument(PdfReader, PdfWriter), create Document around PdfDocument again and append content to the document as you do now:
public void FillPdf(string filename)
{
{
using var pdfWriter = new PdfWriter(tempFilename);
using var pdfDoc = new PdfDocument(pdfWriter);
using var doc = new Document(pdfDoc, PageSize.LETTER);
doc.SetMargins(12, 12, 36, 12);
AddData(doc);
doc.Close();
}
{
using var pdfWriter = new PdfWriter(filename);
using var pdfReader = new PdfReader(tempFilename);
using var pdfDoc = new PdfDocument(pdfReader, pdfWriter);
using var doc = new Document(pdfDoc, PageSize.LETTER);
doc.SetMargins(12, 12, 36, 12);
AddFooter(doc);
doc.Close();
}
}
Second option is not to flush the content as soon as possible and keep it in memory instead. You can do that by only making a slight modification in your code: pass third parameter to Document constructor
using var doc = new Document(pdfDoc, PageSize.LETTER, false);
Please keep in mind that second option might result in additional empty page being created at the end of your document in some corner cases (e.g. when you add such a large image to your document that it doesn't even fit into a full page), so use it carefully. It should not create any problems with you are dealing with regular simple content though
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)));
I want to insert a paragraph (which will word-wrap over several lines) into a PDF document using iTextSharp, but I want to restrict the width of the paragraph to the left half of the page. I see no "width" property for the Paragraph class, but surely there is a way to do this, stimmt?
UPDATE
The supposed answer doesn't work for me because it uses iText (Java) stuff apparently unavailable in iTextSharp (C#). Specifically (to begin with, there might be more):
ct.setSimpleColumn(myText, 60, 750, document.getPageSize().getWidth()
Although there is a "SetSimpleColumn" for *Sharp (uppercased initial 's'), there is no "GetPageSize".
UPDATE 2
I'm beginning to think that what I really need to do may be to create a 'borderless table' as suggested, and as articulated in "BestiTextQuestionsOnStackOverflowFull.pdf"
This is one way to do it - a borderless, single-row table with WidthPercentage set to 50 and Horizontal Alignment sent to Left:
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4, 50, 50, 25, 25)) {
//Create a writer that's bound to our PDF abstraction and our stream
using (var writer = PdfWriter.GetInstance(doc, ms))
{
//Open the document for writing
doc.Open();
var courier9RedFont = FontFactory.GetFont("Courier", 9, BaseColor.RED);
var importantNotice = new Paragraph("Sit on a potato pan Otis - if you don't agree that that's the best palindrome ever, I will sic Paladin on you, or at least say, 'All down but nine - set 'em up on the other alley, pard'", courier9RedFont);
importantNotice.Leading = 0;
importantNotice.MultipliedLeading = 0.9F; // reduce the width between lines in the paragraph with these two settings
// Add a single-cell, borderless, left-aligned, half-page, table
PdfPTable table = new PdfPTable(1);
PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.BorderWidth = PdfPCell.NO_BORDER;
table.WidthPercentage = 50;
table.HorizontalAlignment = Element.ALIGN_LEFT;
table.AddCell(cellImportantNote);
doc.Add(table);
doc.Close();
}
var bytes = ms.ToArray();
String PDFTestOutputFileName = String.Format("iTextSharp_{0}.pdf", DateTime.Now.ToShortTimeString());
PDFTestOutputFileName = PDFTestOutputFileName.Replace(":", "_");
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), PDFTestOutputFileName);
File.WriteAllBytes(testFile, bytes);
MessageBox.Show(String.Format("{0} written", PDFTestOutputFileName));
}
}
I'm publishing a windows form application which allows the user to save a PDF of the information they input. The PDF contains 2 images (logo.png & name.png). I'm currently storing those pictures in my bin>Debug folder.
My question is, if I publish the program, will the PDF still have access to these images or do they need to be placed in another folder in order for the PDF to generate correctly?
private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Filter = "New (*.pdf)|*.pdf|All Files (*.*|*.*";
dlg.AddExtension = true;
dlg.DefaultExt = ".pdf";
dlg.FilterIndex = 1;
if (dlg.ShowDialog() == DialogResult.OK)
{
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream(dlg.FileName.ToString(), FileMode.Create));
doc.Open();//Open Document to write
iTextSharp.text.Image logo = iTextSharp.text.Image.GetInstance("logo.png");
logo.ScalePercent(45f);
logo.SetAbsolutePosition(doc.PageSize.Width - 105f - 72f, doc.PageSize.Height - -15f - 216.6f);
doc.Add(logo);
iTextSharp.text.Image name = iTextSharp.text.Image.GetInstance("name.png");
name.ScalePercent(95f);
name.SetAbsolutePosition(doc.PageSize.Width - 500f - 72f, doc.PageSize.Height - -55f - 216.6f);
doc.Add(name);
var titleFont = FontFactory.GetFont("Times New Roman", 24);
var headerFont = FontFactory.GetFont("Times New Roman", 20);
var bodyFont = FontFactory.GetFont("Times New Roman", 16);
var fineFont = FontFactory.GetFont("Times New Roman", 8);
//Write pdf content
doc.Close();//Close document
I would just add the image as a resource to your project, this will bake it into the DLL/EXE itself. Right-click your project and select Properties and then click on Resources. Click Add Resource and then Add Existing File. Select your image and optionally rename it. Then in your code you can access it using its fully qualified name:
var img = WindowsFormsApplication1.Properties.Resources.logo;
var logo = iTextSharp.text.Image.GetInstance(img, BaseColor.WHITE);
doc.Add(logo);
Replace WindowsFormsApplication1 with whatever namespace you have setup for your project.
I am trying to Export Chart images to PPT i.e. each image in one slide, below is my code
String strTemplate, strPic;
strTemplate = "C:\\Program Files (x86)\\Microsoft Office\\Templates\\Presentation Designs\\Maple.GIF";
//strPic = #"C:\Users\rongala.ganesh\Pictures\arrow_left_green_large.png";
bool bAssistantOn;
Microsoft.Office.Interop.PowerPoint.Application objApp;
Microsoft.Office.Interop.PowerPoint.Presentations objPresSet;
Microsoft.Office.Interop.PowerPoint._Presentation objPres;
Microsoft.Office.Interop.PowerPoint.Slides objSlides;
Microsoft.Office.Interop.PowerPoint._Slide objSlide;
Microsoft.Office.Interop.PowerPoint.TextRange objTextRng;
Microsoft.Office.Interop.PowerPoint.Shapes objShapes;
Microsoft.Office.Interop.PowerPoint.Shape objShape;
Microsoft.Office.Interop.PowerPoint.SlideShowWindows objSSWs;
Microsoft.Office.Interop.PowerPoint.SlideShowTransition objSST;
Microsoft.Office.Interop.PowerPoint.SlideShowSettings objSSS;
Microsoft.Office.Interop.PowerPoint.SlideRange objSldRng;
//Create a new presentation based on a template.
objApp = new Microsoft.Office.Interop.PowerPoint.Application();
objApp.Visible = MsoTriState.msoTrue;
objPresSet = objApp.Presentations;
objPres = objPresSet.Open(strTemplate,
MsoTriState.msoFalse, MsoTriState.msoTrue, MsoTriState.msoTrue);
objSlides = objPres.Slides;
//Build Slide #1:
//Add text to the slide, change the font and insert/position a
//picture on the first slide.
objSlide = objSlides.Add(1, Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutTitleOnly);
objTextRng = objSlide.Shapes[1].TextFrame.TextRange;
// objTextRng.Text = "FAME Presentation";
objTextRng.Font.Name = "Comic Sans MS";
objTextRng.Font.Size = 25;
foreach (var ar in arr)
{
// ScriptManager.RegisterClientScriptBlock(this.Page,typeof(string),"alert"
objSlide = objSlides.Add(1, Microsoft.Office.Interop.PowerPoint.PpSlideLayout.ppLayoutTitleOnly);
objTextRng = objSlide.Shapes[1].TextFrame.TextRange;
// objTextRng.Text = "FAME Presentation";
objTextRng.Font.Name = "Comic Sans MS";
objTextRng.Font.Size = 25;
string[] str = (string[])ar;
strPic = str[0];
objSlide.Shapes.AddPicture(strPic, MsoTriState.msoFalse, MsoTriState.msoTrue,
150, 150, 500, 350);
objTextRng = objSlide.Shapes[1].TextFrame.TextRange;
objTextRng.Text = str[1];
objTextRng.Font.Name = "Comic Sans MS";
objTextRng.Font.Size = 48;
//Build Slide #2:
//Add text to the slide title, format the text. Also add a chart to the
//slide and change the chart type to a 3D pie chart.
//Build Slide #3:
//Change the background color of this slide only. Add a text effect to the slide
//and apply various color schemes and shadows to the text effect.
}
}
catch (Exception ex)
{
throw ex;
}
When I Run this, every thing is working fine in localHost, but when I host this application IIS7 it Throwing exception PowerPoint could not open file.
So what I thought is better to add Response Header, so I followed the below code
dt is the DataTable Name which contains paths of the images saved when I click on SaveImage
GridView1.AllowPaging = false;
GridView1.DataSource = dt;
GridView1.DataBind();////////write this code only if paging is enabled.
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=FileName.ppt");///////for text file write FileName.txt
Response.Charset = "";
// If you want the option to open the Excel file without saving than
// comment out the line below
// Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/vnd.ppt";//for text file write vnd.txt
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite =
new HtmlTextWriter(stringWrite);
GridView1.RenderControl(htmlWrite);
Response.Write(stringWrite.ToString());
Response.End();
Here I can add Images to PPT, but they are in same slide, and the images are overlapping each other.
Using Interop on the server (like ASP.NET) is NOT supported by MS - see http://support.microsoft.com/default.aspx?scid=kb;EN-US;q257757#kb2
Since Windows Vista MS introduced several security-related measures which prevent a Windows Service from doing "desktop-like" things... which means you would have to circumvent several security measures to get it to work (NOT recommended!).
To deal with PPT in a server-scenario there are some options (free and commercial) out there:
A free option (though for the newer pptx format only!) is for example OpenXML 2 from MS.
A commercial option is Aspose.Slides which can handle old (PPT) and new (PPTX) format.