Creating Documents
Before a document has any content, it has a ServerTextControl instance and an empty page in US letter format. You create and dispose instances correctly in console applications and ASP.NET Core, set the page format of a new document, assemble content from text, HTML snippets and other documents, store document properties and make sure the fonts are available on the server.
Create a Document walks through inserting formatted text, a table and a header. Character formatting is covered in Text and paragraph formatting in Paragraphs. Input files of the console applications below are in a Documents folder that is copied to the output directory.
Create and Dispose Instances
Every piece of document processing code follows the same lifecycle:
- Create the instance with the ServerTextControl constructor.
- Initialize it with Create before you use any other member.
Createreturnstrueif the instance could be initialized andfalseif it couldn't. IsCreated tells you later whether the instance is completely created. - Work with the document, then dispose the instance. A
usingstatement releases its resources as soon as the block ends.
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
// Create returns false if the instance couldn't be initialized
if (!tx.Create())
{
throw new InvalidOperationException("ServerTextControl could not be created.");
}
tx.Text = "This document was created with ServerTextControl.";
tx.Save("created.docx", StreamType.WordprocessingML);
}
If Create fails and the instance is used anyway, its members throw the error "The TXTextControl object must have been completely loaded to use this method." On Windows, Create fails most often because no new window handle can be created, usually because instances weren't disposed. ResetContents deletes the entire contents of an instance; Clear, in contrast, deletes only the selected text or the character right of the input position.
In an ASP.NET Core application, create one instance inside the action or service method that produces the document, as the Save as DOCX and PDF tutorial does. TX Text Control is thread safe, but it uses critical sections for shared resources, so threads that use it can wait for each other. Performance and Scalability describes how to process many documents in parallel.
Set the Page Format of a New Document
A new document has one section with US letter pages (8.5 x 11 inches), page margins of 1 inch and the font Arial at 10 pt. ServerTextControl.PageSize and PageMargins are measured in the unit of PageUnit, which is 1/100 inch by default. The following program prints the default format and then changes the margins and the orientation of the document:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
// US letter with 1-inch margins, in 1/100 inch
Console.WriteLine($"Page size: {tx.PageSize.Width} x {tx.PageSize.Height}");
Console.WriteLine($"Margins: {tx.PageMargins.Left}, {tx.PageMargins.Top}, {tx.PageMargins.Right}, {tx.PageMargins.Bottom}");
// Margins of 0.5 inch on every side and landscape orientation
tx.PageMargins = new PageMargins(50, 50, 50, 50);
tx.Landscape = true;
tx.Text = "This document uses landscape pages with narrow margins.";
tx.Save("landscape.pdf", StreamType.AdobePDF);
}
The code works as follows:
- The PageMargins constructor takes the left, top, right and bottom margin, here 50/100 inch each.
- Landscape turns the pages to landscape orientation.
- ResetPageSize and ResetPageMargins set the page size and margins back to US letter and 1 inch.
A document whose parts need different page formats, such as a landscape page in a portrait report, is divided into sections, which Sections describes.
Build a Document From Pieces
Documents are rarely typed in one go. The following program builds a report from a heading and a paragraph and appends an HTML snippet:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
// Prepare text and formatting in a Selection object, then insert it in one step
tx.Selection = new Selection()
{
Text = "Quarterly Report\r\n",
FontName = "Arial",
FontSize = 480, // 24 pt
Bold = true
};
tx.Selection = new Selection()
{
Text = "Revenue grew in all regions this quarter.\r\n",
FontName = "Arial",
FontSize = 240 // 12 pt
};
// Append an HTML snippet in a new paragraph at the end of the document
tx.Append("<p>Prepared by the <strong>reporting service</strong>.</p>",
StringStreamType.HTMLFormat,
AppendSettings.StartWithNewParagraph);
tx.Save("report.docx", StreamType.WordprocessingML);
}
The code works as follows:
- Assigning a prepared Selection object inserts its text with all its attributes at the input position. This is faster than inserting text and formatting it afterward, as the blog article Speed Up Document Generation by Factor 2 Using Selection Objects measures.
- Append adds a document to the end of the existing content. It loads from a file, a byte array or a string, like
Load, but doesn't replace what is already there.
The last parameter of Append is a value of AppendSettings:
| Value | The appended document starts |
|---|---|
None | At the end of the last paragraph |
StartWithNewParagraph | In a new paragraph at the end of the document |
StartWithNewSection | In a new section at the end of the document |
To put a document in place of a placeholder or at the input position instead of at the end, use Selection.Load, as Load, Append or Insert shows.
Combine Several Documents
To combine documents such as a cover page and several chapters, load the first one and append the others. The following program starts each document in a new section and saves the result as one PDF:
using TXTextControl;
string[] files =
{
"Documents/cover.docx",
"Documents/chapter1.docx",
"Documents/chapter2.docx"
};
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
// The first document replaces the empty contents
tx.Load(files[0], StreamType.WordprocessingML);
// Every further document is appended in a new section
for (int i = 1; i < files.Length; i++)
{
tx.Append(files[i], StreamType.WordprocessingML, AppendSettings.StartWithNewSection);
}
Console.WriteLine($"Sections: {tx.Sections.Count}, pages: {tx.Pages}");
tx.Save("combined.pdf", StreamType.AdobePDF);
}
Documents that come from a database are appended from a byte array in the same way: tx.Append(bytes, BinaryStreamType.WordprocessingML, AppendSettings.StartWithNewSection);. Loading Documents compares Load, Append and Selection.Load in more detail.
Store Document Properties
ServerTextControl.DocumentSettings holds the title, author, subject, keywords and user-defined properties of a new or loaded document, and Save stores them with the document, for example tx.DocumentSettings.DocumentTitle = "Quarterly Report";. Document Metadata describes how DocumentSettings, SaveSettings and LoadSettings work together, and Document Properties in the Document Editor section lists which formats store which properties.
Make Fonts Available on the Server
A document looks the same on every server only if the fonts it uses are available there. The Core engine uses the fonts of the Fonts folder that its NuGet package adds to your application, not the fonts installed on the machine, and the Classic engine uses the fonts installed on Windows; Fonts in the Deployment Guide describes the folder, the fonts it contains and how to add your own.
When a font of a document isn't available, TX Text Control replaces it. To list the available fonts and find out which fonts were replaced, call GetSupportedFonts and handle the AdaptFont event:
using TXTextControl;
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
string[] fonts = tx.GetSupportedFonts();
if (fonts != null)
{
Console.WriteLine($"{fonts.Length} fonts available");
}
// Report every font that isn't available and its replacement
tx.FontSettings.AdaptFontEvent = true;
tx.AdaptFont += (sender, e) =>
Console.WriteLine($"{e.FontName} replaced with {e.AdaptedFontName}");
tx.Load("Documents/sample.docx", StreamType.WordprocessingML);
tx.Save("sample.pdf", StreamType.AdobePDF);
}
GetSupportedFonts returns the names of the fonts that are available. AdaptFont occurs only when FontSettings.AdaptFontEvent is true; its default is false, so set it before you load the document. In the event arguments, FontName is the original font and AdaptedFontName the font that replaces it. To choose the replacement yourself or to allow only certain kinds of fonts, see Use the Right Fonts in PDF Creation. Fonts in the Troubleshooting section helps when text looks different than expected.
Next Steps
- Loading Documents: load existing documents with all their options.
- Text: find, replace and format the text of a document.
- Sections: give parts of a document their own page format.
- Saving and Converting Documents: save the finished document in the format you need.