TX Text Control .NET for Windows Forms

PDF Import and Its Limitations

Topic

A PDF file describes how its pages look, not how the document behind them was built. When a Windows Forms application loads a PDF into a TextControl or a ServerTextControl, TX Text Control reconstructs an editable document from the pages. That works well for many PDF documents created digitally, and it has limits that are worth knowing before you promise users an editable copy of any PDF. What follows explains how the import works, how LoadSettings controls the result and when another tool of TX Text Control fits better.

Loading a password-protected PDF is covered in Open a Password-Protected PDF, and the other options of LoadSettings in Loading Documents.

What Happens When a PDF Is Loaded

PDF is a page description format, like PostScript. It states exactly what each character looks like and where on the page it is, but not always which Unicode character it is, and it usually has no information about the order of the text or about which text is a heading or a table cell. Most PDF files contain a character mapping, which lets a program convert the characters to text.

The PDF import filter of TX Text Control extracts all text it can find and rebuilds a document from it:

  • It restores the logical order of the text blocks and inserts missing spaces and paragraph breaks.
  • It keeps the formatting of the text: font names, sizes and styles.
  • It supports Unicode and reads PDF and PDF/A files, without Adobe Acrobat.
  • What else the document contains depends on LoadSettings.PDFImportSettings.

The result is a document that looks like the PDF, not the document the PDF was created from. Paragraphs, tables and text frames are rebuilt from the positions of the text on the page.

Choose How the Document Is Rebuilt

PDFImportSettings has these values:

ValueResult
GenerateLinesText only; images and paragraph formatting are discarded. Suited for searching PDF files.
GenerateParagraphsParagraphs generated from the text flow; images are discarded.
GenerateTextFramesDefault. Tables, images and text frames create a document that comes as close as possible to the appearance of the original.
GenerateTextFramesFirstPageOnlyLike GenerateTextFrames, but only the first page is loaded, for example for a preview.
LoadEmbeddedDataMetadata, form fields and text coordinates of the PDF are provided through LoadSettings.EmbeddedData.
LoadEmbeddedFilesDefault. Files embedded in the PDF are provided through EmbeddedFiles.

The first four values choose the layout, and the last two add data. Combine them with |, for example PDFImportSettings.GenerateParagraphs | PDFImportSettings.LoadEmbeddedFiles. GenerateXML is obsolete; use LoadEmbeddedData instead.

Choose by what the user does with the document:

  • Edit the text, for example to reuse it in a new document: GenerateParagraphs gives paragraphs that reflow like typed text.
  • Keep the look of forms and complex layouts: GenerateTextFrames places tables, images and text frames where they are on the page.
  • Search or index the content: GenerateLines.

Open a PDF in the Editor

The following handler in Form1.cs lets the user pick a PDF, loads it with paragraphs generated from the text flow and reports documents without text:

private void openPdfButton_Click(object sender, EventArgs e)
{
    using (OpenFileDialog dialog = new OpenFileDialog() { Filter = "PDF files|*.pdf" })
    {
        if (dialog.ShowDialog() != DialogResult.OK)
        {
            return;
        }

        LoadSettings loadSettings = new LoadSettings()
        {
            // Paragraphs from the text flow, without images
            PDFImportSettings = PDFImportSettings.GenerateParagraphs
        };

        try
        {
            textControl1.Load(dialog.FileName, StreamType.AdobePDF, loadSettings);
        }
        catch (FilterException exception)
        {
            MessageBox.Show("The PDF could not be loaded: " + exception.Reason);
            return;
        }

        if (textControl1.Text.Trim().Length == 0)
        {
            MessageBox.Show("The PDF contains no text that can be extracted.");
        }
    }
}

The code works as follows:

For a quick look at a long PDF, load only its first page and keep it read-only:

private void previewPdfButton_Click(object sender, EventArgs e)
{
    LoadSettings loadSettings = new LoadSettings()
    {
        PDFImportSettings = PDFImportSettings.GenerateTextFramesFirstPageOnly
    };

    textControl1.Load("report.pdf", StreamType.AdobePDF, loadSettings);
    textControl1.EditMode = EditMode.ReadAndSelect;
}

EditMode ReadAndSelect lets the user read and select the text but not change it.

Convert PDF Documents Without the Editor

Converting PDF documents to DOCX doesn't need the editor. The following handler converts every PDF of a folder with a ServerTextControl and lists the files it skipped:

private void convertPdfsButton_Click(object sender, EventArgs e)
{
    using (FolderBrowserDialog dialog = new FolderBrowserDialog())
    {
        if (dialog.ShowDialog() != DialogResult.OK)
        {
            return;
        }

        List<string> skipped = new List<string>();

        foreach (string file in Directory.GetFiles(dialog.SelectedPath, "*.pdf"))
        {
            using (ServerTextControl tx = new ServerTextControl())
            {
                // Initialize the new instance before using it
                tx.Create();

                LoadSettings loadSettings = new LoadSettings()
                {
                    PDFImportSettings = PDFImportSettings.GenerateParagraphs
                };

                try
                {
                    tx.Load(file, StreamType.AdobePDF, loadSettings);
                }
                catch (FilterException exception)
                {
                    // For example InvalidPassword or Encrypted
                    skipped.Add(Path.GetFileName(file) + ": " + exception.Reason);
                    continue;
                }

                if (tx.Text.Trim().Length == 0)
                {
                    skipped.Add(Path.GetFileName(file) + ": no text");
                    continue;
                }

                tx.Save(Path.ChangeExtension(file, ".docx"), StreamType.WordprocessingML);
            }
        }

        MessageBox.Show(skipped.Count == 0
            ? "All PDF documents were converted."
            : "Not converted:\n" + string.Join("\n", skipped));
    }
}

Each file gets a new ServerTextControl, whose Create must be called before any other member. ServerTextControl.Text returns the text of the loaded document, and StreamType.WordprocessingML saves it as DOCX.

Where the Import Reaches Its Limits

  • Scanned documents contain images of pages and no text. Run them through OCR software before you import them.
  • PDF files without a character mapping show text that can't be converted to characters. The import finds no text, or not all of it.
  • The structure is reconstructed. Most PDF files don't say which text is a heading or a table cell, or in which order the text flows, so the imported document approximates the structure from the positions on the page.
  • Images are part of the document with GenerateTextFrames and GenerateTextFramesFirstPageOnly; GenerateLines and GenerateParagraphs discard them.
  • Form field values are read with Forms.GetAcroFormFields rather than from the imported text, as Reading Form Fields and Values shows.

Encrypted PDF Documents

A PDF can be encrypted and protected with a user password, which is needed to open it, and an owner password, which protects its permissions. TX Text Control imports PDF documents encrypted with these algorithms:

EncryptionCreated by
40-bit RC4Acrobat 3.0 and later
128-bit RC4Acrobat 5.0 and later
128-bit AESAcrobat 7.0 and later

Documents encrypted with 256-bit AES (Acrobat 9.0 and later) or with certificates can't be imported: Load throws a FilterException whose Reason is Encrypted. A missing or wrong user password throws the reason InvalidPassword. Your application asks the user for the password and loads again with UserPassword, as Passwords and Access Permissions describes.

Other Ways to Get Data Out of a PDF

Many tasks need data from a PDF rather than an editable document:

Next Steps