Convert HTML to PDF Using DynamicPDF HTML Converter

by James B

Tue, August 18 2020, 12:50 PM (US Eastern Time)

Introduction

The DynamicPDF HTML Converter product is available and included with any of our subscription plans (subscription pricing). You can also use DynamicPDF HTML Converter free if you accept a small footer stating "Created with the DynamicPDF Essentials Edition" and link to the DynamicPDF website from a public area of your website. DynamicPDF HTML Converter supports the following features,

  • quickly converts HTML to PDF,
  • supports the latest HTML, CSS, and JavaScript,
  • works with files, byte arrays, and URLs,
  • supports custom headers and footers,
  • supports .NET Framework and .NET Core (including Linux),
  • and supports a transparent pricing model.

As this tutorial will demonstrate, DynamicPDF HTML Converter is an intuitive yet powerful library for converting HTML files, URLs, and webpages into PDF documents. A video tutorial is also included if you prefer watching the video rather than reading this tutorial. Or better yet, watch the video and work through the written tutorial. All source is available on Github, and the video is available here or on our YouTube channel.

The Converter and ConversionOptions Classes

The DynamicPDF HTML Converter namespace (ceTe.DynamicPDF.HtmlConverter documentation), consists of four classes,

and two enumerations,

Of these, the two classes most important for understanding this tutorial are the Converter and ConversionOptions classes.  The Converter class is how we convert the document from HTML to PDF using the static Convert or AsyncConvert methods. Both methods are overloaded to support different ways of processing HTML conversion. Although these two methods are all that is required, if you wish to perform any formatting of a PDF document, then you must use the ConversionOptions class to format that PDF. The ConversionOptions class supports specifying a PDF document's metadata, such as author, subject, and name. It also supports formating a PDF document by specifying page size, page orientation, headers, footers, and margins.

Now that we discussed the Converter and ConversionOptions classes let's explore using these classes to convert and format HTML to PDF. 

Creating the Project

Start by creating or downloading the project. You can choose to follow the instructions here or download the project from GitHub (link).

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ceTe.DynamicPDF.HtmlConverter;

namespace ConsoleAppHtmlToPdf
{
    class Program
    {
       static void Main(string[] args)
       {
        Console.WriteLine("Hello World!");
       }
    }
}

Convert Dynamically Generate PDF

After creating the project, in this first example, we dynamically generate a PDF using an HTML table generated by sample form data.

  • Create a new method named ConvertDynamicHtmlToPdf and add a multidimensional array as a string parameter.
  • Create sample data to load and display as an HTML table.
static string[,] companyData = {{ "Grey Fox Brewing", "Mark Smith", "Canada" },
{"Deutsche Ingolstadt","Elias Schneider","Germany"},
{"Centro comercial Moctezuma","Alejandra Silva","Columbia"},
{"West Indies Trading Company","Helen Moore","UK"},
{"Bharat of India","Aarnav Chanda","India"},
{"Magazzini Alimentari Riuniti","Giovanni Esposito","Italy"},
{"Joyas de Cristal","Helena Garcia","Spain"},
{"Telemar Brasil","Elias Martinez","Brazil"},
{"Joe's Pizzaria","Joe Bowman","United States"} };
The data consists of an array containing each entry which consists of the company name, contact name, and the country the company is located.
static void ConvertDynamicHtmlToPdf(string[,] data)
{
     string head = "<html><head><style>"
         + "table {font-family:arial, sans-serif;border-collapse:collapse;width:100%;}"
         + "td,th {border:1px solid #dddddd;text-align:left;padding:8px;}"
         + "tr:nth-child(even){background-color:#dddddd;}"
         + "</style></head><body>";
     string title = "<h2>Company Contacts Listing</h2>";
     string rowHeader = "<tr><th>Company</th><th>Contact</th>"
         + "<th>Country</th></tr>";
     string[] tableTag = { "<table>", "</table>" };
     string close = "</body></html>";

     StringBuilder output = new StringBuilder(head).Append(title);
     output.Append(tableTag[0]);
     output.Append(rowHeader);

     int i = 0;
     foreach (string rec in companyData)
     {
          if (i++ % 3 == 0) output.Append("<tr>");
          output.Append("<td>").Append(rec).Append("</td>");
           if (i % 3 == 0) output.Append("</tr>");
      }

      output.Append(tableTag[1]).Append(close);
      Converter.Convert(output.ToString(), "example5.pdf");
}

After creating our newly created method, add it to the project's Main method.

  • Modify Main to call the newly created method.
  • Run the program and review the created PDF document.
static void Main(string[] args)
{
     ConvertSaveToFileNoInputHtml();
}

Example illustrating HTML with base tag.

As this first example illustrated, creating a PDF document from dynamically generated HTML data is straightforward and only required a document path as a URL and the PDF output.

Convert HTML to PDF Using URI

As the previous example illustrated, generating PDF from HTML is easy when using DynamicPDF HTML Converter. Now let's convert a PDF using a URI to an HTML document, only this time we use a large HTML document combined with ConversionOptions to format the PDF and then save it to a local file.  

  • Create a new static method named ConvertSaveToFileNoInputHtml.
  • Add the URL to the Project Guttenberg's "A Tale of Two Cities."
  • Create a ConversionOptions instance and add the margins, author, creator, title, subject, and the header and footer to the ConversionOptions properties.
  • Call the Converter.Convert method, passing the URL document to convert, the output path for the PDF document, and the conversion options.
  • The code for the ConvertUriToPdf method should appear as follows. 
static void ConvertUriToPdf()
{
     // method signature: public static void Convert(Uri uri, string outputPath, 
    // ConversionOptions conversionOptions = null);

    string outputDocumentPath = "./tale-two-cities--document.pdf";
    string taleOfTwoCities = "https://www.gutenberg.org/files/98/98-h/98-h.htm";
    Uri resolvePath = new Uri(taleOfTwoCities);
    double leftRightMarginsPts = 36;
    double topBottomMarginsPts = 144;

    ConversionOptions conversionOptions = new ConversionOptions(PageSize.Letter, 
           PageOrientation.Portrait, leftRightMarginsPts, topBottomMarginsPts);
           conversionOptions.Author = "Charles Dickens";
           conversionOptions.Creator = "James B";
           conversionOptions.Title = "A Tale of Two Cities";
           conversionOptions.Subject = "Guttenberg press version of Charles Dickens\'s"
               + " A Tale of Two Cities.";
           conversionOptions.Header = "<div style = 'text-align:center;width:100%"
               +";font-size:15em;'>A Tale of Two Cities</div>";
           conversionOptions.Footer = "<div style='text-align:left;"
               +"text-indent:10px;display:inline-block;"
               + "font-size:6em;'><span class=url></span></div>"
               + "<div style = 'text-align:center; display:inline-block; width:60%'></div>"
               + "<div style = 'text-align:right; display:inline-block;"
               +"font-size:6em;'>Page <span class=\"pageNumber\">"
               + "</span> of <span class=\"totalPages\"></span></div>";

     Converter.Convert(resolvePath, outputDocumentPath, conversionOptions);
}

Example illustraing HTML to PDF conversion.

As this second example illustrated, the conversion from HTML to PDF in this example was also straightforward. The ConversionOptions class, although optional, provides powerful options to format a PDF.  For example, in the code above, we created a header from CSS that wrote the title at the top of each page. We also created a footer from CSS that wrote the path and page number at the bottom of each page.

Convert with Base Path and URI

The Convert method consists of an overloaded method that takes an input HTML string, a URL, and an optional ConversionOptions parameter. The following is the method's signature.

public static void Convert(string inputHtml, string outputPath, Uri basePath = null,
     ConversionOptions conversionOptions = null);

The inputHtml is the string content containing HTML, while the basePath is the URL to the document's root path. This overloaded Convert method is how we can process an HTML document using a baseTag. Refer to HTML baseTag on W3Schools for more details on HTML base paths.

  • Create a static method named ConvertSaveToFileInputHtml.
  • Add an array with two relative paths.
  • Create a string containing links to the relative paths in the array.
  • Create a new URI containing the path listed below to Wikimedia Commons.
  • Call the Convert method, passing the input HTML, the output path, and the URI.
  • Create a new ConversionOptions instance and set the page size, page orientation, and the left/right and bottom/top margins.
  • Reduce the zoom to 25% by setting the Zoom property in ConversionOptions.
  • Add the ConvertSaveToFileInputHtml method call to the Main method.
static void ConvertSaveToFileInputHtml()
{
        // method signature: public static void Convert(string inputHtml, string outputPath,
        // Uri basePath = null, ConversionOptions conversionOptions = null);

       string[] filePaths = new string[]{ "./e/ea/Doel_-_Water_pump_1.jpg", 
           "./3/3a/The_Soviet_Union_1939_CPA_690_stamp_%28Plane%29_cancelled.jpg" 
        };
        
        string tempHtml = "<html><body><img src=\"" + filePaths[0] + "\">" 
             + "<img src=\"" + filePaths[1] + "\">" + "</body></html>";

        Uri resolvePath = new Uri("https://upload.wikimedia.org/wikipedia/commons/");
        Converter.Convert(tempHtml, "example1.pdf", resolvePath);

        ConversionOptions conversionOptions = new ConversionOptions(PageSize.Tabloid, 
                PageOrientation.Landscape, 1, 1);
        conversionOptions.Zoom = 0.25F;

        Converter.Convert(tempHtml, "secondTry.pdf", resolvePath,conversionOptions);
      
}
 
  • Run the program and review the PDF output.

Example illustrating HTML with base tag.

In this example, we created a PDF document by combining an HTML string with its base path URI (https://upload.wikimedia.org/wikipedia/commons/). The complete HTML resolved as follows.

<html><body>
<img src="https://upload.wikimedia.org/wikipedia/commons/./e/ea/Doel_-
_Water_pump_1.jpg">
<img src="https://upload.wikimedia.org/wikipedia/commons/./3/3a/The_Soviet_Union_1939_
CPA_690_stamp_%28Plane%29_cancelled.jpg">
</body></html>

We then added document formatting, followed by calling the  Convert method to write the PDF document. Note that the conversion options included formatting the output page as tabloid, the orientation as landscape, and the margins as 1 for the left/right and top/bottom margins.

Convert with CSS and JavaScript

Now let's create the method ConvertHtmlWithCssJavaScriptToPdf to illustrate converting embedded CSS and embedded JavaScript.

  • Add the samplePageWithCss and samplePageWithJavaScript variables to the Program class.
static string samplePageWithCss = "<!DOCTYPE html><html><head ><style>" 
    + "body {background-color: lightblue;}"
    + "h1 {color: white; text-align: center;} p " 
    + "{font-family: verdana;font - size: 20px;}</style>" 
    + "</head><body><h1>My First CSS Example</h1>"
    + "<p>This is a paragraph.</p></body></html>";

static string samplePageWithJavaScript = "<!DOCTYPE html><html><body>"
     + "<h2>My First Web Page</h2>"
     + "<p>My First Paragraph.</p><p id=\"demo\"></p>"
     + "<script>document.getElementById(\"demo\")"
     + ".innerHTML = 5 + 6;</script></body></html>";
  • Create a new method named ConvertHtmlWithCssJavaScriptPdf.
  • Convert the embedded CSS and embedded JavaScript to PDFs.
static void ConvertHtmlWithCssJavaScriptPdf()
{
    // method signature: public static void Convert(string inputHtml, string outputPath, 
    // Uri basePath = null, ConversionOptions conversionOptions = null);

     Converter.Convert(samplePageWithCss, "cssExample.pdf");
     Converter.Convert(samplePageWithJavaScript, "jscriptExample.pdf");
 }

After running the method, both PDF documents output formatted CSS and JavaScript. As the two examples illustrate, DynamicPDF HTML Converter seamlessly supports CSS and JavaScript embedded in HTML documents.

Example illustrating converting embedded CSS and JavaScript into a PDF.

Convert to Byte Array

You can also convert a PDF to a byte array rather than saving it to a file. In this example, we convert an HTML document into a byte array. 

  • Create a new static method named ConvertWriteToByteArrayNoInputHtml.
  • Create a new ConversionOptions instance and pass the PageSize.Tabloid, PageOrientation.Landscape, and the left/right margin and top/bottom margins as 28 points.
  • Create a new URI object instance and pass the CNN URL to the constructor.
  • Call the Convert method, passing the URI and ConversionOptions as parameters and return a byte array as the result.
  • Save the byte array to a file. 
static void ConvertWriteToByteArrayNoInputHtml()
{
   // public static byte[] Convert(Uri uri, ConversionOptions conversionOptions = null);

   ConversionOptions conversionOptions = new ConversionOptions(PageSize.Tabloid, PageOrientation.Landscape, 28, 28);
   Uri document = new Uri("https://cnn.com");
   byte[] output = Converter.Convert(document,conversionOptions);
   File.WriteAllBytes("./cnn-printiout.pdf", output);

This simple example illustrated converting an HTML document to a PDF as a byte array. For simplicity, we saved the byte array to a file to demonstrate that the PDF was printed and formatted correctly.

Convert to Byte Array Asynchronous

For the final example, we convert an HTML document to a byte array asynchronously. If you ran the application in the first example, where it converted A Tale of Two Cities from HTML to PDF, then you probably noticed it took several seconds for the conversion to complete, as the document consists of 330 pages. When processing large documents, it makes sense to convert the document asynchronously so it processes without blocking the main thread. In this example, we convert HTML to PDF asynchronously.

  • Create a new static method named ConvertAsyncReturnByteArray that specifies async and returns a Task.
  • Create strings that specify the output document's path and the input document's path.
  • Create a URI from the input document's path.
  • Create a ConversionOptions instance, passing the page size as letter, the page orientation as portrait, and the margins as 28 points.
  • Add a title and footer to the ConversionOptions instance.
  • Call the ConvertAsync method and pass the input URI document and the ConversionOptions to the method as parameters. Return the output as a byte array.
static async Task ConvertAsyncReturnByteArray()
{
     // public static Task<byte[]> ConvertAsync(Uri uri, ConversionOptions
     // conversionOptions = null);

     string outputDocumentPath = "./gibbons-document.pdf";
     string gibbons = "https://www.gutenberg.org/files/731/731-h/731-h.htm";
     Uri resolvePath = new Uri(gibbons);
     double leftRightMarginsPts = 28;
     double topBottomMarginsPts = 28;

     ConversionOptions conversionOptions = new ConversionOptions(PageSize.Letter, 
     PageOrientation.Portrait, leftRightMarginsPts, topBottomMarginsPts);
     conversionOptions.Title = "HISTORY OF THE DECLINE AND FALL OF THE ROMAN" 
         + " EMPIRE";
      conversionOptions.Footer = "<div style='text-align:left;text-indent:10px;"
          +" display:inline-block; font-size:6em;'><span class=url></span></div>"
          + "<div style = 'text-align:center; display:inline-block; width:60%'></div>"
          + "<div style = 'text-align:right; display:inline-block;font-size:6em;'>"
          + "Page <span class=\"pageNumber\"></span> of <span"
          + "class=\"totalPages\"></span></div>";

      byte[] vals = await Converter.ConvertAsync(resolvePath, conversionOptions); 
      File.WriteAllBytes(outputDocumentPath, vals);
}
  • Modify the Main method to call the ConvertAsyncReturnByteArray method as an asynchronous task. 
static void Main(string[] args)
{
     var task = ConvertAsyncReturnByteArray();
      int i = 0;
      while(task.IsCompleted == false) { Console.Write("\r" + i++); }
      task.Wait();
}

When we execute the program, it takes several seconds to build the PDF document. However, as the simple code in Main illustrates, it does not block the thread while making the PDF.

GitHub Project 

The GitHub project is available here at DynamicPDF/blog-convert-html-to-pdf (project file).

Summary

In this tutorial, we explored using DynamicPDF HTML Converter. DynamicPDF HTML Converter supports synchronous and asynchronous document conversion. It also supports HTML strings with Base URLs, embedded CSS, and embedded JavaScript. And, as the examples illustrated, DynamicPDF HTML Converter supports formatting PDF with many formatting options. As the examples shown, creating a PDF from HTML is straightforward. Get started using Dynamic HTML Converter today by using the free version or by purchasing a subscription today.

Tags: , , , , ,

Creating PDF Reports with Database Data (SQL)

Thu, July 11 2019, 11:04 AM (US Eastern Time)

DynamicPDF ReportWriter make’s it easy to create reports based on your business objects, but sometimes it may be preferred to access data directly from a database using an SQL query or stored procedure. This can easily be done by utilizing one of these report data classes:

Let’s take a look at the steps involved with doing this. First, attach an event to the DocumentLayout’s ReportDataRequired event. This event will be called anytime a report or sub report requires data.

// Create the document's layout from a DLEX template
DocumentLayout documentLayout = new DocumentLayout(Util.GetResourcePath("SimpleReport.dlex"));

// Attach to the ReportDataRequired event
documentLayout.ReportDataRequired += DocumentLayout_ReportDataRequired;

Now in that event, first check the elementId of the report or sub report that is requesting the data. This is necessary in case there are multiple reports or sub reports in your document layout. Next, create a DataReader or DataTable and use it to create a DataReaderReportData or DataTableReportData class. Then set the event’s RepartData event argument to it.

private static void DocumentLayout_ReportDataRequired(object sender, ReportDataRequiredEventArgs args)
{
    if (args.ElementId == "ProductsReport")
    {
        string sqlString =
            "SELECT ProductName, QuantityPerUnit, UnitPrice " +
            "FROM   Products ";

        SqlConnection connection = new SqlConnection(connectionString);
        SqlCommand command = new SqlCommand(sqlString, connection);
        connection.Open();
        SqlDataReader reader = command.ExecuteReader();
        args.ReportData = new DataReaderReportData(connection, reader);
    }
}

Lastly, layout your DocuementLayout to a Document and output the PDF.

// Specify the data
NameValueLayoutData layoutData = new NameValueLayoutData();
layoutData.Add("ReportCreatedFor", "Alex Smith");

// Layout the document and save the PDF
Document document = documentLayout.Layout(layoutData);
document.Draw(outputFilePath);
Wrap Up

A C# Visual Studio project demonstrating this is available on GitHub:

https://github.com/DynamicPDF/dotnet-pdf-report-from-database

If you have any questions or comments, I would love to hear from you.

Tags: , , , , , ,

DynamicPDF Rasterizer for .NET Version 3 is Released

Fri, February 8 2019, 10:50 AM (US Eastern Time)

DynamicPDF Rasterizer v3 for .NET has been released! The new version has support for .NET Standard 2.X including .NET Core 2.X and ASP.NET Core 2.X. It includes an updated and improved PDF rendering engine as well as many new features and the latest bug fixes. Also, the developer edition now allows for 100% royalty free distribution to an unlimited number of servers or machines at a lower price point.

Download v3 Today!

Tags: , , , , ,

Version 10 Release of Dynamic PDF for .NET Core Suite

by Anil S

Fri, August 3 2018, 2:32 PM (US Eastern Time)

We are happy to announce the release of DynamicPDF for .NET Core Suite v10 (this includes our Merger, Generator and ReportWriter products).

v10 now supports .NET Standard 2.0 for seamless cross-platform deployment.  

Download it Today!

Version 10 adds several useful and exciting new features:

  • Deployment to any .NET implementation including .NET Core, .NET Framework, Mono, UWP, Xamarin.iOS and Xamarin.Android.
  • HTML layout engine for rapid PDF development using HTML and CSS
  • All new report layout engine (DLEX templates)
  • Take a look at a full list of All Version 10 Full Features

Free upgrades for Maintenance customers, discounted upgrades for eligible existing customers, eligible upgrades can be accessed via our Customer Area, www.dynamicpdf.com/customerarea or we can be contacted directly, sales@dynamicpdf.com or +1 410.772.8620.

Version 9 Release of Dynamic PDF for .NET Core Suite

Tue, December 12 2017, 2:43 PM (US Eastern Time)

DynamicPDF for .NET Core Suite v9 (this includes our Merger, Generator and ReportWriter products) has now been fully released.  Download it Today!

Version 9 adds tons of useful and exciting new features including:

  • HTML Rendering (convert HTML pages including CSS)
  • Disk Buffering (incremental PDF rendering decreases memory usage)
  • Character Shaping (for fonts of complex scripts)
  • Over 20 New Barcodes (Aztec, Code 11, Code 93, GS1 Databar, Australia Post, etc.)
  • Package PDFs
  • XFA Static Form Filling
  • Document, Page and Field Actions
  • Take a look at a full list of All Version 9 Full Features

What might be our best feature...Lower Prices across the board (all editions, all license models).

Free upgrades for Maintenance customers, discounted upgrades for eligible existing customers, eligible upgrades can be accessed via our Customer Area, www.dynamicpdf.com/customerarea or we can be contacted directly, sales@cete.com or +1 410.772.8620.

Tags: , , , , , , , , , , , , , ,

DynamicPDF for .NET Core Suite Version 9 BETA Release

Thu, April 27 2017, 2:16 PM (US Eastern Time)

The DynamicPDF Core Suite for .NET Version 9.0 BETA has just been posted to our site for download and testing.

DynamicPDF Core Suite for .NET v9 Beta Download

We have added some great new features in version 9 including support for PDF portfolios, an HTML Area, XFA static form filling, improved memory handling for large PDFs, several new barcode types (Code 93, Aztec, GS1 Databar, Australia Post, Singapore Post etc.) and more. Take a look at the full list of new features.

Email support@cete.com with any questions or issues and thanks for taking part in our Version 9 BETA.

 

Tags: , , , , , , , , , ,

DynamicPDF PrintManager for .NET Version v3.0 Release

by Anil S

Tue, February 7 2017, 11:19 AM (US Eastern Time)

Our DynamicPDF PrintManager for .NET version 3.0 has now been fully released. 

Download it Today!

Version 3 adds lots of new features including support to print multiple pages per sheet, PDF Portfolios, quality based resolution settings, print specified area of a PDF page, retrieve a full list of printers (including installed network printers), print priority and many more. Take a look at our Version 3 Full Feature List.

For existing customers, eligible upgrades (free with Maintenance, discounted with previous versions) can be accessed via our Customer Area, or anyone can contact us directly, sales@cete.com or +1 410.772.8620.

Tags: , , , , ,

PrintManager – Setting Advanced Printer Options

by Anil S

Mon, April 27 2015, 10:24 AM (US Eastern Time)

The PrintManager for .NET API allows printing of PDF files through any .NET application.  The settings accessible to the PrintManager are limited to those exposed through a standard API (such as Win32 or .NET).  But a printer may have additional settings that are specific to that printer and are not readily available through a standard API. This means that there could be non-standard features or settings available that vary between printers that are not able to be exposed through the PrintManager API.  To remedy this, we have exposed a way to manually save and reuse a specific state of the native printer’s dialog box that when provided to the Printjob will affect that job as if those options where manually selected by a user.  A full example on how to accomplish this is outlined below.

We will start with the code to invoke printer’s native dialog box and save the settings to a file.

To invoke the printer's advanced setting dialog we will be using a Win32 function called "AdvancedDocumentProperties".

AdvancedDocumentProperties(IntPtr.Zero,IntPtr.Zero,e.PrintJob.Printer.Name,e.DevMode, e.DevMode);

In order to import the above function to a .NET application, use the following DllImport.

[DllImport("winspool.Drv", EntryPoint = "AdvancedDocumentPropertiesW", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]

static extern int AdvancedDocumentProperties(IntPtr hwnd, IntPtr hPrinter, [MarshalAs(UnmanagedType.LPWStr)] string pDeviceName, IntPtr pDevModeOutput, IntPtr pDevModeInput);

Calling the Print() method will fire the Printjob.Starting event. In the event handler, call AdvancedDocumentProperties to display the printer setting dialog box. Select the appropriate setting that you would like to save to file and click OK. The file can be generated with individual settings or with a group of settings.

PrintJob printJob = new PrintJob(Printer.Default, "DocumentA.pdf");

printJob.Starting += new PrintJobStartingEventHandler(this.onStartingPrint1);

printJob.Print();

PrintJobStartingEventArgs contains following properties that will be used to retrieve the printer settings from the dialog box.

Name Type Definition
Devmode Intptr Pointer towards Devmode structure
DevmodeSize Int Size of  Devmode
DevmodeDriverExtra Int Size of  DmDriverExtra
PrintJob PrintJob DynamicPDF Printmanager PrintJob object. Generic printer settings can be changed using this object.

Here is the code for the event handler to retrieve and save the selected printer setting.

private void onStartingPrint1(object sender, PrintJobStartingEventArgs e)
{
    //Invoke the printer options dialog box.
    int value = AdvancedDocumentProperties(IntPtr.Zero, IntPtr.Zero, e.PrintJob.Printer.Name, e.DevMode, e.DevMode);

    //Create a byte array to store Devmode and DmDriverExtra settings.
    byte[] bytearray = new byte[e.DevModeSize + e.DevModeDriverExtra];

    //Copy the contents of both Devmode and DmDriverExtra to the byte array.
    Marshal.Copy(e.DevMode, bytearray, 0, e.DevModeSize + e.DevModeDriverExtra);

    //Save the settings to disk.
    File.WriteAllBytes("SettingsFile.bin", bytearray); 
}

Next, we will print a PDF using the saved settings by overwriting the Devmode and DmDriverExtra structures with the file contents. Due to this, all settings applied to the PrintJob object before Printjob.Starting event handler call will be lost. However we can set the print settings after overwriting Devmode and DmDriverExtra in the event handler.

private void onStartingPrint2(object sender, PrintJobStartingEventArgs e)
{
    //Load the saved settings into a byte array. 
    byte[] bytearray = File.ReadAllBytes("SettingsFile.bin");

    //Overwrite the DevMode with the byte array restored from file. 
    IntPtr pdevmode = Marshal.AllocHGlobal(bytearray.Length);
    Marshal.Copy(bytearray, 0, e.DevMode, bytearray.Length);

    //The line below displays the print options dialog box, so the modified settings can be verified during development. 
    //It is not required for printing so it can removed, especially for non-interactive applications like windows services             
    int value = AdvancedDocumentProperties(IntPtr.Zero, IntPtr.Zero, e.PrintJob.Printer.Name, e.DevMode, e.DevMode);            

    //Set additional print settings as needed. 
    e.PrintJob.PrintOptions.Copies = 1;
}

Complete source code is available for download below.

Downloads:

PrinterAdvancedOptions.zip (21.2 kb)

Tags: , , , , ,

Creating PDFs in C# with Outlined or Invisible Text

Thu, August 30 2012, 1:51 PM (US Eastern Time)

DynamicPDF Generator has lots of predefined page elements which allow you to easily create different types of content, but you may occasionally have a need to do something that is not available in the API by default. Custom page elements is an easy way to extend the API to achieve these results.

We get questions from time to time on how to add outlined text to a PDF. By outlined text I mean text that is not completely filled in with a color but rather is just an outline of the font and nothing filled in the middle of the text.  This is a great situation for using a Custom page element and the C# code below shows how to extend the TextArea page element to add this functionality:

using System;
using ceTe.DynamicPDF;
using ceTe.DynamicPDF.PageElements;

public class OutlinedTextArea : TextArea
{
    // Member variable to store Border Width
    private float borderWidth = 1.0f;

    // Constructors. Additional ones can be added to model TextArea
    public OutlinedTextArea(string text, float x, float y, float width, float height)
        : base(text, x, y, width, height) { }
    public OutlinedTextArea(string text, float x, float y, float width, float height,
        Font font, float fontSize)
        : base(text, x, y, width, height, font, fontSize) { }

    // Border Width Property added
    public float BorderWidth
    {
        get { return this.borderWidth; }
        set { this.borderWidth = value; }
    }

    // Override Draw Method
    public override void Draw(ceTe.DynamicPDF.IO.PageWriter writer)
    {
        // Enter Graphics Mode
        writer.SetGraphicsMode();
        // Set Stroke Color and Border Width
        writer.SetStrokeColor(base.TextColor);
        writer.SetLineWidth(this.borderWidth);
        // Enter Text Mode
        writer.SetTextMode();
        // Set Text Rendering Mode
        writer.SetTextRenderingMode(TextRenderingMode.Stroke);
        // Call Draw on base class
        base.Draw(writer);
        // Enter Text Mode (in case underline is set to true)
        writer.SetTextMode();
        // Set Text Rendering Mode Back to Fill
        writer.SetTextRenderingMode(TextRenderingMode.Fill);
    }
}

More...

Tags: , , , , , , , , , , ,

Create AES Encrypted PDFs in C# and VB .NET

Tue, July 31 2012, 2:48 PM (US Eastern Time)

We recently released an update that introduces AES-256 bit and AES-128 bit encryption to our .NET PDF creation and merging library. We have offered encryption since 2002, but this was limited to RC4-40 bit and RC4-128 bit security until this release. We have also restructured the API a bit in order to easily accommodate new encryption methods in the future.

Encryption is now handled by 4 classes in a new ceTe.DynamicPDF.Cryptography namespace:

All security classes allow restrictions to be placed on a PDF to restrict printing, modification, copying content or updating/adding text annotations or form fields. The 128-bit and higher classes allow restrictions to be placed on a PDF to restrict filling in existing form fields, extracting text and graphics for accessibility purposes, modifying the pages included, high resolution printing or leaving the XMP metadata unencrypted. The AES classes also add the ability to encrypt only file attachments.

The C# code to add AES-256 bit encryption to a new document is very straight forward:

Document document = new Document();
Page page = new Page();
page.Elements.Add(new Label("AES-256 bit encrypted PDF.", 0, 0, 500, 15));
document.Pages.Add(page);
// Add the encryption
Aes256Security security = new Aes256Security("ownerpassword", "userpassword");
security.AllowHighResolutionPrinting = false;
// Set other encryption options
document.Security = security;
// Output the PDF
document.Draw("MyPDF.pdf");

More...

Tags: , , , ,

Month List