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.
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
I have pdf files in the "C:\\pdfs\\" directory. I want to get these pdf files and insert metadatas from the meta_data.txt file. With my lock of iTextSharp knowledge, I coded like this:
var pdf_files = Directory.GetFiles("C:\\pdfs\\", "*.pdf");
var i = 0;
foreach (var pdf_file in pdf_files)
{
var read = new PdfReader(pdf_file);
var size = read.GetPageSizeWithRotation(1);
var document = new Document(size);
var write = PdfWriter.GetInstance(document, new FileStream("C:\\temp\\" + "file_" + i, FileMode.Create, FileAccess.Write));
var datas = File.ReadAllLines("C:\\pdfs\\" + #"meta_data.txt");
var str = datas[i].Split('#');
document.AddTitle(str[1]);
document.AddSubject(str[2]);
document.AddCreator(str[3]);
document.AddAuthor(str[4]);
document.AddKeywords(str[5]);
document.Open();
var cb = write.DirectContent;
for (var pageNum = 1; pageNum <= read.NumberOfPages; pageNum++)
{
document.NewPage();
var page = write.GetImportedPage(read, pageNum);
cb.AddTemplate(page, 0, 0);
}
document.Close();
read.Close();
File.Delete(pdf_file);
File.Move("C:\\temp\\" + "file_" + i, "C:\\created\\" + "file_" + i);
i++;
}
This codes get an instance of main pdf files, while creation to temp directory, injects metadatas and later move the created directory. I don't find more practical method than this.
Anyway, in some pdf files (generated as an original pdf file) there is no problem like this:
But some other pdf files (generated from scan or very old dated pdf file) are rotated programmatically. And it seems disgusting like this:
Worse than all, I don't know how I fix the problem. Could you help me how I manage this problem.
The correct answer to this question looks like this:
PdfReader reader = new PdfReader(src);
using (PdfStamper stamper = new PdfStamper(reader,
new FileStream("C:\\temp\\" + "file_" + i, FileMode.Create, FileAccess.Write))) {
Dictionary<String, String> info = reader.Info;
info["Title"] = "Hello World stamped";
info["Subject"] = "Hello World with changed metadata";
info["Keywords"] = "iText in Action, PdfStamper";
info["Creator"] = "Silly standalone example";
info["Author"] = "Bruno Lowagie";
stamper.MoreInfo = info;
}
Habip OĞUZ ignored what I wrote in Chapter 6 of "iText in Action - Second Edition", namely that using Document, PdfWriter and AddTemplate() is wrong when you want to manipulate a single existing PDF. By using AddTemplate(), you throw away plenty of features, such as interactivity, structure, and so on. You also create a PDF that is suboptimal because every page will be stored as a Form XObject.
Currently I have this test code
File file = new File();
Document document = file.Document;
Page page = new Page(document);
document.Pages.Add(page);
PrimitiveComposer composer = new PrimitiveComposer(page);
composer.SetFont(new StandardType1Font(document, StandardType1Font.FamilyEnum.Courier, true, false), 32);
composer.ShowText("Hello World!", new PointF(32, 48));
composer.Flush();
file.Save("test.pdf", SerializationModeEnum.Incremental);
System.Diagnostics.Process.Start("explorer", System.IO.Directory.GetParent(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName).ToString());
How can I open a general windows explorer save as prompt instead of saving to the hard code path "test.pdf"? (In file.save())
Thanks
Use SaveFileDialog for that:
https://msdn.microsoft.com/en-us/library/sfezx97z(v=vs.110).aspx
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "PDF File|*.pdf";
saveFileDialog1.Title = "Save PDF";
if(saveFileDialog1.ShowDialog() == DialogResult.OK)
{
file.Save(saveFileDialog1.FileName, SerializationModeEnum.Incremental);
}
I try to print to XPS printer (it's not my default printer), but the program opens me a dialog.
Can I skip the dialog? This is the code:
pSettings = new PrinterSettings();
pSettings.PrintFileName = "test.xps";
RawPrinterHelper.SendStringToPrinter(pSettings.PrinterName, toSend);
spcn = new StandardPrintController();
printDocument1.PrinterSettings.PrinterName = "Microsoft XPS Document Writer";
printDocument1.PrintController = spcn;
printDocument1.PrintPage +=
new PrintPageEventHandler(printDocument1_PrintPage);
printDocument1.Print();
You can print PDF to XPS without a dialog using Aspose API
Aspose API
//Create PdfViewer object and bind PDF file
PdfViewer pdfViewer = new PdfViewer();
pdfViewer.OpenPdfFile("input.pdf");
//Set PrinterSettings and PageSettings
System.Drawing.Printing.PrinterSettings printerSetttings = new System.Drawing.Printing.PrinterSettings();
printerSetttings.Copies = 1;
printerSetttings.PrinterName = "Microsoft XPS Document Writer";
//Set output file name and PrintToFile attribute
printerSetttings.PrintFileName = "C:\\tempfiles\\printoutput.xps";
printerSetttings.PrintToFile = true;
**//Disable print page dialog**
**pdfViewer.PrintPageDialog = false;**
//Pass printer settings object to the method
pdfViewer.PrintDocumentWithSettings(printerSetttings);
pdfViewer.ClosePdfFile();
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