Loading Documents
Documents arrive from files, databases, uploads and other applications, each in its own format. Beyond a single Load call, you decide whether a document replaces, extends or goes into the current content, control the import with LoadSettings, read information about the loaded document and handle uploads, passwords and errors.
The overloads of Load and the format enumeration for each source are in Load a Document, and PDF documents in Load and Modify a PDF. The examples below read their files from a Documents folder that is copied to the output directory.
Load, Append or Insert
Three methods load a document into a ServerTextControl. They take the same sources and formats and an optional LoadSettings object:
| Method | What happens to the existing content |
|---|---|
| ServerTextControl.Load | It's replaced completely |
| ServerTextControl.Append | It stays; the document is added at the end, as set by an AppendSettings value |
| Selection.Load | The selected text is replaced; with nothing selected, the document is inserted at the input position |
The following program loads a letter, appends a signature and inserts an attachment in place of a placeholder:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
// Load replaces the complete contents
tx.Load("Documents/letter.docx", StreamType.WordprocessingML);
// Append adds a document at the end, here in a new paragraph
tx.Append("Documents/signature.rtf", StreamType.RichTextFormat,
AppendSettings.StartWithNewParagraph);
// Selection.Load replaces the selected text, here a placeholder
const string placeholder = "[ATTACHMENT]";
int position = tx.Find(placeholder);
if (position >= 0)
{
tx.Select(position, placeholder.Length);
LoadSettings loadSettings = new LoadSettings()
{
// Create a new paragraph before the document is loaded
AddParagraph = true
};
tx.Selection.Load("Documents/attachment.docx", StreamType.WordprocessingML, loadSettings);
}
tx.Save("result.docx", StreamType.WordprocessingML);
}
LoadSettings.AddParagraph has an effect only with Selection.Load. With false, the default, the document is loaded into the existing paragraph, and the attributes of that paragraph and of the last loaded paragraph are merged; with true, a new paragraph is created first and takes the attributes of the last loaded paragraph. Creating Documents lists the AppendSettings values.
Control the Import With LoadSettings
Properties of LoadSettings that you set before loading decide what is imported and how:
| Property | Sets | Default |
|---|---|---|
| ApplicationFieldFormat | Whether fields of MS Word documents, or the fields of Heiler HighEdit in RTF, are imported as application fields, for DOCX, DOC and RTF | None |
| ApplicationFieldTypeNames | The field types to import, such as MERGEFIELD, when ApplicationFieldFormat is MSWord | null, all types |
| LoadSubTextParts | Whether bookmarks that extend over several characters become subtext parts, for DOCX, DOC and RTF | false |
| LoadImages | Whether images are loaded; otherwise a rectangle with the image's name is shown | true |
| LoadHypertextLinks | Whether hypertext links are loaded | true |
| LoadDocumentBackColor | Whether the background color of the document is loaded | true |
| ImageSearchPath | A folder that replaces the absolute file paths of linked images and other resources | — |
| DocumentBasePath | A base path that resolves the relative file paths of the document | — |
| PDFImportSettings | How the structure of a PDF document is rebuilt | GenerateTextFrames |
| DocumentPartName | The worksheet of an XLSX document to load | null, the first worksheet |
| UserPassword, MasterPassword | The passwords of an encrypted PDF document | — |
LoadSettings and SaveSettings share a base class, LoadSaveSettingsBase. It defines DocumentBasePath, the passwords, EmbeddedFiles, ReportingMergeBlockFormat and DefaultStreamType, so both classes have these properties. DefaultStreamType preselects a format in the Open and Save As dialog boxes of the desktop products and matters only where such a dialog box is shown; a server application passes the StreamType to Load and Save itself.
The following program loads a Word template with only its merge fields and its merge blocks, and without its hypertext links and background color:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
LoadSettings loadSettings = new LoadSettings()
{
ApplicationFieldFormat = ApplicationFieldFormat.MSWord,
ApplicationFieldTypeNames = new string[] { "MERGEFIELD" }, // only merge fields
LoadSubTextParts = true, // bookmarks over several characters become subtext parts
LoadHypertextLinks = false,
LoadDocumentBackColor = false
};
tx.Load("Documents/template.docx", StreamType.WordprocessingML, loadSettings);
Console.WriteLine($"Merge fields: {tx.ApplicationFields.Count}");
Console.WriteLine($"Subtext parts: {tx.SubTextParts.Count}");
}
Merge blocks of a mail merge template are stored as subtext parts, which is why Simple Mail Merge loads DOCX templates with LoadSubTextParts set to true. Subtext Parts describes how to work with them.
Read Information About the Loaded Document
After loading, the same LoadSettings object contains information about the document. These properties are read only:
| Property | Contains |
|---|---|
DocumentTitle, Author, CreationDate, UserDefinedDocumentProperties and the other metadata | The metadata of the document and its values when the document has none, as Where Metadata Lives lists |
| LoadedStreamType, BytesRead | The format that was loaded and the number of bytes read |
| PageSize, PageMargins | The page size, 0 if the document has none, and the page margins, -1 if the document has none |
| DocumentAccessPermissions | The access permissions of a PDF document |
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
LoadSettings loadSettings = new LoadSettings();
tx.Load("Documents/sample.docx", StreamType.WordprocessingML, loadSettings);
Console.WriteLine($"Format: {loadSettings.LoadedStreamType}, {loadSettings.BytesRead} bytes");
Console.WriteLine($"Title: {loadSettings.DocumentTitle}");
Console.WriteLine($"Author: {loadSettings.Author}");
Console.WriteLine($"Last modified: {loadSettings.LastModificationDate}");
if (loadSettings.UserDefinedDocumentProperties != null)
{
foreach (string name in loadSettings.UserDefinedDocumentProperties.Names)
{
Console.WriteLine($"{name}: {loadSettings.UserDefinedDocumentProperties[name]}");
}
}
Console.WriteLine($"Pages: {tx.Pages}");
}
ServerTextControl.DocumentSettings is filled with the same metadata and keeps it for the next save. User-defined properties and their values are described in Store Custom Properties.
Load Uploaded Documents in ASP.NET Core
An uploaded file reaches an ASP.NET Core controller as a stream. Load has no overload for such streams, so copy the stream into a byte array first. The following action converts an uploaded DOCX document to PDF:
using Microsoft.AspNetCore.Mvc;
using TXTextControl;
public class UploadController : Controller
{
[]
public IActionResult ConvertToPdf(IFormFile document)
{
// Copy the upload into a byte array
byte[] data;
using (MemoryStream memoryStream = new MemoryStream())
{
document.CopyTo(memoryStream);
data = memoryStream.ToArray();
}
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
try
{
tx.Load(data, BinaryStreamType.WordprocessingML);
}
catch (FilterException exception)
{
return BadRequest($"The document could not be loaded: {exception.Reason}");
}
byte[] pdf;
tx.Save(out pdf, BinaryStreamType.AdobePDF);
return File(pdf, "application/pdf",
Path.GetFileNameWithoutExtension(document.FileName) + ".pdf");
}
}
}
BinaryStreamType has values for DOCX, DOC, PDF, XLSX and the TX Text Control formats, but not for HTML and RTF. Load those formats from a string with StringStreamType or from a file with StreamType.
Load Password-Protected PDF Documents
A PDF document that is protected with a user password can only be opened with that password. Without it, Load throws a FilterException whose Reason is InvalidPassword:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
try
{
tx.Load("Documents/protected.pdf", StreamType.AdobePDF);
}
catch (FilterException exception) when (exception.Reason == FilterException.FilterError.InvalidPassword)
{
// The PDF requires a user password: load it again with the password
LoadSettings loadSettings = new LoadSettings()
{
UserPassword = "user1234"
};
tx.Load("Documents/protected.pdf", StreamType.AdobePDF, loadSettings);
Console.WriteLine($"Permissions: {loadSettings.DocumentAccessPermissions}");
}
catch (FilterException exception) when (exception.Reason == FilterException.FilterError.Encrypted)
{
Console.WriteLine("The encryption scheme of this PDF is not supported.");
}
}
Your application asks for the password and decides which operations it allows according to DocumentAccessPermissions; with a valid MasterPassword, the document has no restrictions. The PDF import supports RC4 encryption with 40 and 128 bits and AES encryption with 128 bits. For documents encrypted with 256-bit AES or with certificates, the reason is Encrypted.
Load HTML
HTML is loaded from a string with StringStreamType.HTMLFormat or from a file with StreamType.HTMLFormat. CSS in a style element is applied, and TX Text Control creates paragraph styles from the HTML. After loading, the result is a regular document to which you can add headers, footers and page settings. The following program loads an HTML page and changes the font of its root style BODY, which the other styles inherit:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
string html = "<html><head><style>h1 { color: #1a4d80; }</style></head>" +
"<body><h1>Newsletter</h1><p>The newsletter of this month.</p></body></html>";
tx.Load(html, StringStreamType.HTMLFormat);
// Change the root style of the styles created from the HTML
ParagraphStyle bodyStyle = tx.ParagraphStyles.GetItem("BODY");
if (bodyStyle != null)
{
bodyStyle.FontName = "Times New Roman";
bodyStyle.Apply();
}
tx.Save("newsletter.pdf", StreamType.AdobePDF);
}
The blog article Convert HTML to PDF in ASP.NET Core C# converts complete HTML pages, including images, this way.
Handle Errors
When a document can't be imported, Load throws a FilterException. Its Reason property names the cause, such as WrongFileType, InvalidPassword or Encrypted. The reasons and an example that handles them are listed in FilterException.
The DOC format can't be loaded with the Core engine, and AdobePDFA and CascadingStylesheet are formats for saving only. ServerTextControl.DocumentLoaded occurs when a document has been loaded.
Linked images are a common problem when documents move between servers: an image that was inserted from a file stores its path, and when that file doesn't exist on the new server, a rectangle with the file name is shown instead of the image. The blog article Check TX Text Control Template Dependencies Before Deployment finds such images and missing fonts before a template is used.
Next Steps
- Saving and Converting Documents: save loaded documents in another format.
- Creating Documents: assemble documents from several sources.
- Fields: work with the fields imported from Word documents.
- Supported File Formats: the formats you can load with each engine.