Net4x.PdfExporterLib 2.0.0.26253

dotnet add package Net4x.PdfExporterLib --version 2.0.0.26253
                    
NuGet\Install-Package Net4x.PdfExporterLib -Version 2.0.0.26253
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Net4x.PdfExporterLib" Version="2.0.0.26253" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Net4x.PdfExporterLib" Version="2.0.0.26253" />
                    
Directory.Packages.props
<PackageReference Include="Net4x.PdfExporterLib" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Net4x.PdfExporterLib --version 2.0.0.26253
                    
#r "nuget: Net4x.PdfExporterLib, 2.0.0.26253"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Net4x.PdfExporterLib@2.0.0.26253
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Net4x.PdfExporterLib&version=2.0.0.26253
                    
Install as a Cake Addin
#tool nuget:?package=Net4x.PdfExporterLib&version=2.0.0.26253
                    
Install as a Cake Tool

PdfExporterLib

WPF building blocks for a PDF viewer/exporter application — Esportazione di pdf in altri formati.

The package provides a reusable Window base class that hosts the PdfViewerLibrary control inside WPF, a secondary window for reviewing extracted text and tabular data, and a small set of data utilities (CSV export, batch file renaming, visual-tree lookup, case-insensitive string replacement).

Package id Net4x.PdfExporterLib
Target framework net452 (Windows only — WPF + Windows Forms interop)
License Apache-2.0

Installation

<PackageReference Include="Net4x.PdfExporterLib" Version="2.0.0.*" />
dotnet add package Net4x.PdfExporterLib

The consuming project must be a Windows desktop project that references PresentationCore, PresentationFramework, WindowsBase, System.Windows.Forms and WindowsFormsIntegration.

What is in the package

Type Purpose
PdfExporterLib.MainPdfWindow Window base class hosting a PdfViewerControl, with tray icon, open/export commands and batch folder processing
PdfExporterLib.NotepadWindow Ready-made window with a text editor and a hosted DataGridView
PdfExporterLib.ControlFinder Visual-tree lookup by type and name
PdfExporterLib.DataUtility.CsvTableExporter Writes a DataTable as delimited or fixed-width text
PdfExporterLib.DataUtility.FileRenamer Sequential renaming of a batch of files
PdfExporterLib.DataUtility.StringExtension ReplaceCaseInsensitive extension method

Hosting the PDF viewer

MainPdfWindow ships without markup of its own: derive your window from it and wire your XAML to the protected handlers it already implements.

<pdf:MainPdfWindow x:Class="MyApp.MainWindow"
                   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   xmlns:pdf="clr-namespace:PdfExporterLib;assembly=PdfExporterLib"
                   Title="PDF Exporter" Height="720" Width="1024"
                   AllowDrop="True"
                   Loaded="Window_Loaded" Drop="Window_Drop"
                   Closing="Window_Closing" StateChanged="Window_StateChanged">
    <Grid x:Name="ContentGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Menu Grid.Row="0">
            <MenuItem Header="File">
                <MenuItem Header="Apri..." Click="OpenMenu_Click" />
                <MenuItem Header="Esci" Click="ExitMenu_Click" />
            </MenuItem>
            <MenuItem Header="?">
                <MenuItem Header="Informazioni su..." Click="AboutMenu_Click" />
            </MenuItem>
        </Menu>
        
    </Grid>
</pdf:MainPdfWindow>
using PdfExporterLib;
using PdfViewerLibrary.Model;

public partial class MainWindow : MainPdfWindow
{
    public MainWindow()
    {
        InitializeComponent();

        // Adds a WindowsFormsHost carrying the PdfViewerControl to row 1 of the grid.
        // Pass null for the grid to let ControlFinder locate the first Grid in the window.
        LoadWfUserControl(ContentGrid);
    }

    protected override void OnPdfViewerControlPdfOpened(object sender, FileNameEventArgs e)
    {
        base.OnPdfViewerControlPdfOpened(sender, e);   // publishes MainPdfWindow.FileName
        Title = "PDF Exporter — " + MainPdfWindow.FileName;
    }
}

LoadWfUserControl(grid, printVisible, showOnlyFirstTab) gives control over the viewer chrome: printVisible: false hides the print command, showOnlyFirstTab: true collapses the viewer down to its first tab page.

Static helpers

MainPdfWindow.FileName;                              // last PDF opened by the viewer
MainPdfWindow.Unminimize(window);                    // restore a minimised window (no-op if not shown)
MainPdfWindow.GetTempFilePathWithExtension(".pdf");  // %TEMP%\<guid>.pdf
MainPdfWindow.GetTempFilePathWithoutExtension();     // %TEMP%\<guid>

Tray icon

The MainPdfWindow constructor installs a NotifyIcon with a Mostra / Nascondi / Esci context menu and shows it immediately. Minimising the window hides it to the tray; the Window_Closing handler removes the icon again, so wire your window's Closing event to it or the icon will outlive the window.

Batch folder processing

DoOpenFolder prompts for a folder, walks every *.pdf in it, opens and closes each document, and finally reports how many files were processed. The callback you pass is invoked once per file, before that file is opened, so the export destination can be prepared:

private void OpenFolderMenu_Click(object sender, RoutedEventArgs e)
{
    DoOpenFolder(PrepareAutomaticExport);
}

private void PrepareAutomaticExport()
{
    // Called once per PDF, just before it is opened.
}

Renaming before and after processing is driven by the application settings described below.

CsvTableExporter

using (var writer = new StreamWriter(path, false, Encoding.UTF8))
{
    CsvTableExporter.ExportDatatableToStream(writer, dataTable);
}

// or straight to a path
CsvTableExporter.ExportDatatableToStream(path, dataTable);

// fixed-width output, no header, no separators
CsvTableExporter.ExportDatatableToStream(
    putColumnNames: false,
    putColumnSeparators: false,
    columnLengths: new[] { 10, 30, 8 },
    outputFileStream: writer,
    dataReader: dataTable);

Behaviour worth knowing before you wire it up:

  • The separator is Thread.CurrentThread.CurrentCulture.TextInfo.ListSeparator; under it-IT, , under the invariant culture. Pin the culture if the output has to be stable.
  • A separator is written after every column, including the last, so each row ends with a trailing delimiter.
  • columnLengths pads short values with spaces and truncates long ones. Columns beyond the end of the array are written unpadded.
  • The method closes the TextWriter it is given — do not reuse the writer afterwards.
  • null and DBNull cells become empty fields. Combining them with columnLengths is not supported.
  • The path overload opens the file without truncating it; delete an existing file first if it may be longer than the new content.

FileRenamer

var files  = Directory.GetFiles(folder, "*.pdf");
var offset = 0;

for (var i = 0; i < files.Length; i++)
    FileRenamer.RenameFile(ref i, files, ref offset, "Processed_", "pdf", dontRenameFile: false);

// zeta.pdf, alpha.pdf, mu.pdf  ->  Processed_1.pdf, Processed_2.pdf, Processed_3.pdf

The new name is {prefix}{index + offset + 1}.{extension}, in the source file's own directory. With dontRenameFile: true the original file name is kept and only the prefix and extension are applied. When the computed name equals the current one the file is left untouched. The return value is the full path of the file after the call.

The target name must not already exist: the collision branch does not recompute the candidate name and will not terminate. Rename into a clean prefix/extension pair, or check for existing targets before calling.

ControlFinder

var grid   = ControlFinder.FindChild<Grid>(this, null);        // first Grid in the visual tree
var editor = ControlFinder.FindChild<TextBox>(this, "Notes");  // first TextBox named "Notes"

Returns null when parent is null or nothing matches. Name matching is case sensitive. The search does not descend into a child that already matches T but carries a different name, so a same-typed ancestor will hide the element you are looking for.

StringExtension

using PdfExporterLib.DataUtility;

"Hello World".ReplaceCaseInsensitive("WORLD", "Earth");  // "Hello Earth"

The search term is matched literally (regex metacharacters are escaped) and $ in the replacement is not treated as a substitution group.

NotepadWindow

var notepad = new NotepadWindow { Text = extractedText };
notepad.DataGridView.DataSource = table;   // hosted System.Windows.Forms.DataGridView

if (notepad.ShowDialog() == true && notepad.TextModified)
    Save(notepad.Text);

TextModified only becomes true for changes made while the window is visible, so pre-filling Text before showing it is not reported as a user edit.

Application settings

Batch renaming in DoOpenFolder reads the PdfExporterLib.Properties.Settings application-scoped settings. Override them in the host application's App.config:

<configSections>
  <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <section name="PdfExporterLib.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </sectionGroup>
</configSections>
<applicationSettings>
  <PdfExporterLib.Properties.Settings>
    <setting name="RenameBeforeProcess" serializeAs="String"><value>False</value></setting>
    <setting name="BeforePrefix" serializeAs="String"><value>Processed_</value></setting>
    <setting name="BeforeExtension" serializeAs="String"><value>pdf</value></setting>
    <setting name="RanameFileNameBefore" serializeAs="String"><value>False</value></setting>
    <setting name="RenameAfterProcess" serializeAs="String"><value>True</value></setting>
    <setting name="AfterPrefix" serializeAs="String"><value /></setting>
    <setting name="AfterExtension" serializeAs="String"><value>processedPdf</value></setting>
    <setting name="RanameFileNameAfter" serializeAs="String"><value>False</value></setting>
  </PdfExporterLib.Properties.Settings>
</applicationSettings>
Setting Default Meaning
RenameBeforeProcess False Rename every file in the folder before processing starts
BeforePrefix / BeforeExtension Processed_ / pdf Naming applied by the pre-processing pass
RanameFileNameBefore False True renumbers the files, False keeps their original names
RenameAfterProcess True Rename each file once it has been processed
AfterPrefix / AfterExtension (empty) / processedPdf Naming applied by the post-processing pass
RanameFileNameAfter False True renumbers the files, False keeps their original names

The setting names RanameFileNameBefore / RanameFileNameAfter are spelled as shown — the typo is part of the persisted configuration contract.

Dependencies

Localisation

The built-in user interface strings (tray menu, window titles, about text, progress message) are in Italian. Override the protected handlers if you need another language.


Copyright © Piero Viano 2016. Released under the Apache-2.0 license.

Product Compatible and additional computed target framework versions.
.NET Framework net452 is compatible.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0.26253 81 9/10/2026