Howto: Use Text Fields

Text Fields are markers which are inserted in the text. They can be used to implement a wide range of special functions in a text processor. To name just a few:

  • Mail Merge functions
  • Spreadsheet-like calculation fields
  • Bookmarks
  • Automatic table of contents and index generation
  • Hypertext links and targets

Any group of characters within the text can be a marked text field. The maximum number of fields is 65,535. Text Control maintains the positions and numbers of the fields. It also takes care of loading, saving and clipboard operations.

Additional information about text fields can be found in the Technical Articles part in the chapterText Fields and Hypertext Links.

The source code for this example is contained in the following directories:

  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\VB.NET\TextFields
  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\CSharp\TextFields

Used TX Text Control controls:

  • TXTextControl.TextControl
  • TXTextControl.ButtonBar
  • TXTextControl.RulerBar
  • TXTextControl.StatusBar

Relevant API Links

A Simple Example

This first sample program will show you how fields are created and what happens when they are clicked on. The code shown here is contained in the following directories:

  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\VB.NET\TextFields\Fields1
  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\CSharp\TextFields\Fields1

The program consists of a form with just one menu item,Insert Field!, with an exclamation mark to say that clicking on this item will cause an immediate action instead of dropping a menu. There are two Text Controls on the form, one of which is used as a normal text window (TextControl1), the other one as a pop-up window (TextControl2).

The following code is executed when the menu item is clicked on:

private void mnuInsertField_Click(object sender, System.EventArgs e)
{
    TXTextControl.TextField newField = new TXTextControl.TextField();
    newField.Text = "--------";
    newField.ID = fieldID;
    fieldID += 1;
    textControl1.TextFields.Add(newField);
}
Private Sub mnuInsertField_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles mnuInsertField.Click
    Dim NewField As New TXTextControl.TextField()
    NewField.Text = "--------"
    NewField.ID = FieldID
    FieldID += 1
    TextControl1.TextFields.Add(NewField)
End Sub

This inserts a field at the current caret position and assigns a unique number to the fields ID property. If you move the cursor over the field, Text Control changes the mouse pointer to a hand cursor to indicate that there is something to click on.

Image

If you click on the field, the application receives a TextFieldClicked event, to which it responds by popping up a window which displays the field number.

Image

Only two lines of code are required for this:

private void textControl1_TextFieldClicked(object sender, TXTextControl.TextFieldEventArgs e)
{
    // Field has been clicked on, update text of second TX and display it
    textControl2.Text = "Field clicked, ID: " + e.TextField.ID;
    textControl2.BringToFront();
}
Private Sub TextControl1_TextFieldClicked(ByVal sender As System.Object, _
ByVal e As TXTextControl.TextFieldEventArgs) Handles TextControl1.TextFieldClicked
    TextControl2.Text = "Field clicked, ID: " + CStr(e.TextField.ID())
    TextControl2.BringToFront()
End Sub

When the mouse button is released, the text window is moved to the front again:

private void textControl1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
    textControl1.BringToFront();
}
Private Sub TextControl1_MouseUp(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) Handles TextControl1.MouseUp
    TextControl1.BringToFront()
End Sub

Bookmarks

This example shows you how to use text fields to create bookmarks. The first version will reference the bookmarks simply by their field numbers. The source code for this example is contained in the following directories:

  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\VB.NET\TextFields\Fields2
  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\CSharp\TextFields\Fields2

The sample application has a Bookmark menu with two items which are named Insert and Go to.... Clicking Insert creates a text field at the current caret position. If a text selection exists, the selected text is converted into a text field.

private void mnuBookmark_Insert_Click(object sender, System.EventArgs e)
{
    if (textControl1.Text == "")
    {
        MessageBox.Show("Cannot insert a bookmark if the Text Control is empty.");
    }
    else if (textControl1.Selection.Length == 0)
    {
        textControl1.Selection.Length = 1;
    }
    else
    {
        TXTextControl.TextField newField = new TXTextControl.TextField();
        newField.ID = fieldID;
        newField.Text = textControl1.Selection.Text;
        textControl1.Selection.Text = "";
        fieldID += 1;
        textControl1.TextFields.Add(newField);
    }
}
Private Sub mnuBookmark_Insert_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles mnuBookmark_Insert.Click
    If TextControl1.Text = "" Then
        MsgBox("Cannot insert a bookmark if the Text Control is empty.")
    ElseIf TextControl1.Selection.Length = 0 Then
        TextControl1.Selection.Length = 1
    Else
        Dim NewField As New TXTextControl.TextField()

        NewField.ID = FieldID
        NewField.Text = TextControl1.Selection.Text
        TextControl1.Selection.Text = ""
        FieldID += 1
        TextControl1.TextFields.Add(NewField)
    End If
End Sub

After typing in some text and inserting a few bookmarks, select the Go To... menu item. This will launch a dialog box which allows you to enter the number of the bookmark to jump to.

Image

Clicking the OK button executes the following procedure:

private void cmdOK_Click(object sender, System.EventArgs e)
{
    if (Convert.ToInt32(textBox1.Text) > tx.TextFields.Count)
    {
        MessageBox.Show ("Invalid bookmark number!");
    }
    else
    {
        foreach (TXTextControl.TextField field in tx.TextFields)
        {
            if (field.ID == Convert.ToInt32(textBox1.Text))
            {
                tx.Selection.Start = field.Start - 1;
                tx.Selection.Length = field.Length;
            }
        }
    }
    Close();
}
Private Sub cmdOK_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdOK.Click
    Dim Field As TXTextControl.TextField

    If (CInt(TextBox1.Text) > tx.TextFields.Count) Then
        MsgBox("Invalid bookmark number!")
    Else
        For Each Field In tx.TextFields
            If (Field.ID = CInt(TextBox1.Text)) Then
                tx.Selection.Start = Field.Start - 1
                tx.Selection.Length = Field.Length
            End If
        Next
    End If
    Close()
End Sub

Adding Strings to Marked Text Fields

In commercial word processors, bookmarks are normally referenced by names, not just by numbers. The names are typed in by the user when he creates a bookmark. The Goto Bookmark dialog box then presents a listbox or combobox in which one of the strings can be selected.

The source code for this example is contained in the following directories:

  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\VB.NET\TextFields\Fields3
  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\CSharp\TextFields\Fields3

The Insert Bookmark... menu item in this version of the program creates a dialog box where the user can enter a label for the bookmark.

Image

When the OK button is clicked, the following code is executed:

private void cmdOK_Click(object sender, System.EventArgs e)
{
    TXTextControl.TextField field = new TXTextControl.TextField();

    field.Name = textBox1.Text;
    field.Text = tx.Selection.Text;
    tx.Selection.Text = "";


    tx.TextFields.Add(Field);
    Close();
}
Private Sub cmdOK_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdOK.Click
    Dim Field As New TXTextControl.TextField()

    Field.Name = TextBox1.Text
    Field.Text = tx.Selection.Text
    tx.Selection.Text = ""

    tx.TextFields.Add(field)
    Close()
End Sub

First, a marked text field is created at the current caret position. Second, the name of the bookmark, which is the text that has been typed in by the user, is stored in the TextField.Name property.

The Goto Bookmark dialog box contains a combo box which lists all of the bookmarks which have been created so far.

Image

The combo box is filled with the bookmark titles when its form is loaded:

private void frmGotoDialog_Load(object sender, System.EventArgs e)
{
    foreach (TXTextControl.TextField Field in tx.TextFields) {
        ComboBox1.Items.Add(Field.Name);
    }
}
Private Sub frmGotoDialog_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
    Dim field As TXTextControl.TextField

    For Each field In tx.TextFields
        ComboBox1.Items.Add(field.Name)
    Next
End Sub

When the OK button is clicked, the bookmark list is searched for the string which has been selected in the combo box, and the corresponding marked text field is selected.

private void cmdOK_Click(object sender, System.EventArgs e)
{
    foreach (TXTextControl.TextField field in tx.TextFields)
    {
        if (field.Name == comboBox1.Text)
        {
            tx.Selection.Start = field.Start - 1;
            tx.Selection.Length = field.Length;
        }
    }
    Close();
}
Private Sub cmdOK_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdOK.Click
    Dim Field As TXTextControl.TextField

    For Each Field In tx.TextFields
        If (Field.Name = ComboBox1.Items.Item(ComboBox1.SelectedIndex)) Then
            tx.Selection.Start = Field.Start - 1
            tx.Selection.Length = Field.Length
        End If
    Next
    Close()
End Sub

Importing and Exporting Fields from and to MS Word

TX Text Control imports and exports all fields that can be inserted into an MS Word document. As described in the technical article, the ApplicationField class provides a special interface to get and set the data and parameters of these fields.

The following two samples show how to use the two most common used fields of MS Word: MERGEFIELD and FORMTEXTBOX.

The source code for these samples is contained in the following directory:

  • Samples\WinForms\VB.NET\ApplicationFields
  • Samples\WinForms\CSharp\ApplicationFields

Used TX Text Control controls:

  • TXTextControl.TextControl
  • TXTextControl.ButtonBar
  • TXTextControl.RulerBar
  • TXTextControl.StatusBar
  • TXTextControl.ServerTextControl
  • TXTextControl.DocumentServer

Relevant API Links

Implementing a MERGEFIELD Class

The MS Word MergeField is the most commonly used field in MS Word and RTF documents. It enables template designers to add additional information to a text field, such as a specific text that should be displayed before or after the field text or the format of the text.

To handle these fields and it's functionality, this sample implements three different classes:

  • MergeField
  • MergeFieldCollection
  • CollectionSync

The MergeField class is inherited from the TextField base class and extends it's functionality to cover all properties of a MergeField. This MergeField gets a reference to the ApplicationField that will be manipulated by the class. Additionally, a MergeField contains the following parameters that are implemented through it's properties:

  • TextFormat
  • TextBefore
  • TextAfter
  • Mapped
  • MergeFieldName
  • PreserveFormatting
  • VerticalFormatting

If the TextBefore property of the MergeField is set, the Text property of this inherited class manipulates the referenced ApplicationField instance and it's Text. Additionally, this new setting is saved in the Parameters property in the appropriate format.

The MergeFieldCollection is the collection for the MergeField instances. It implements all common properties and methods of standard collection.

Finally, a synchronization object is required to synchronize the existing collections of a TextControl instance and the new MergeFieldCollection. It must be synchronized every time the ApplicationField collection is changed. This class attaches two important events to the parent TextControl class that listens for changes in this collection: TextFieldCreated and TextFieldDeleted.

After starting the sample, click on File / Load to load a sample document, which contains several merge fields. Set the input position inside an existing field, for sample COMPANY.

Image

Open the implemented merge field dialog by choosing Edit... from the MergeField main menu.

Image

Using this dialog, it is possible to manipulate all properties of the MergeField instance. Add some text that should be inserted after the field by checking the checkbox Text to be inserted after. Type some text in the appropriate text box and close the dialog by clicking OK.

Open the customer data grid form by clicking Merge fields... from the Merge menu entry. Choose a customer by clicking on a specific row and click Merge to merge all merge fields with the database content.

In this process, the MergeFieldCollection is used to loop through all inserted fields to replace the text. The following code shows this loop:

DataGridViewRow curRow = dataGridView1.SelectedRows[0];
foreach (MergeField curMergeField in m_mergeFieldCollection)
{
    foreach (DataGridViewTextBoxCell curCell in curRow.Cells)
    {
        if (curCell.OwningColumn.Name == curMergeField.MergeFieldName)
          curMergeField.Text = curCell.Value.ToString();
    }
}
Dim CurRow As DataGridViewRow = DataGridView1.SelectedRows(0)
For Each CurMergeField As MergeField In m_MergeFieldCollection
    For Each CurCell As DataGridViewTextBoxCell In CurRow.Cells
        If CurCell.OwningColumn.Name = CurMergeField.MergeFieldName then
            CurMergeField.Text = CurCell.Value.ToString()
        End if
    Next
Next

Implementing a FORMTEXT Class

The FormText field is used in MS Word to create fillable documents. In many applications, such documents are automated, so that these fields must be readable to be completed automatically. An ApplicationField object acts like a container for all settings (switches) of these fields.

In contrast to the first example, this sample implements a class for the FormText fields that is not inherited from the TextField base class. In this case, no separate collection is required to synchronize these fields. Everytime, an ApplicationField of type FORMTEXT should be edited, a new FormText object is created:

FormText curFormText = new FormText(textControl1.ApplicationFields.GetItem());
Dim curFormText As New FormText(TextControl1.ApplicationFields.GetItem())

A reference to the ApplicationField is stored in the FormText instance. Similar to the first sample, this ApplicationField is used to get or set the parameters that are mapped to the properties of the new implemented FormText object.

A dialog box is implemented to change the properties of the specific form text field. The dialog represents the properties of the implemented FormText field:

Image

After clicking OK, the specified values in the dialog box are set in the implemented FormText object which writes the parameters of the referenced ApplicationField.

Creating and Merging MS Word Compatible Templates

Mail merge is the most typical application for TX Text Control. The combination of TX Text Control's MS Word compatible field functionality and TX Text Control .NET Server's automated MailMerge component is a very powerful toolset to build high peformance and MS Word compatible mail merge applications.

TX Text Control supports not only the merge process, but also provides the required editor functionality to create templates with a true WYSIWYG interface.

This sample project shows most of the mail merge possibilities of TX Text Control. The following steps are included:

  • Database binding
  • Adding fields
  • Preview
  • Export the merged document

It is quite similar to MS Word mail merge capabilities, but it comes with the source code and can be customized completely. The following tutorial explains how to use this sample.

1. Connect to a database

  • Click on the Select recipients button in the toolbar or choose Select Recipients... from the Mail Merge menu.

Image

  • In the opened dialog box, browse for the shipped XML database file address.xml which is located in the sample root folder and load it by clicking Open.

Now you can see the contained DataTables in the drop down box of the toolbar. If the database would contain more DataTables, you could select the required DataTable from this box. Based on the selected database and DataTable, the contained merge fields are automatically added to the Insert Field drop down button and the Insert Merge Field menu item.

Image

2. Insert merge fields

  • Insert some merge fields from the above filled drop down list. These fields will be inserted at the current input position.

Image

  • You can switch the view mode of the fields using these three buttons in the toolbar:

Image

  • Field code: This view mode shows the MS Word field codes of the field.
  • Field text: This view mode shows the results or the field name.
  • Preview: This view mode merges the database content into the specific fields.
  • Click on the Preview button. The second database navigator toolbar gets enabled and you can navigate through the database in order to preview your template with the real data:

Image

3. Export the document

  • Finally, click the Export button to start the mail merge process:

Image

This opens a new form that consists of a TX Text Control and a simple toolbar. The DocumentServer.MailMerge component is used in the background to merge the created template with the data records from the selected database. The resulting document is copied into the visual TX Text Control instance on the form. The actual merge process is done in 3 lines of code:

mailMerge.TextComponent = tx;
mailMerge.LoadTemplateFromMemory(Document,
    TXTextControl.DocumentServer.FileFormat.InternalUnicodeFormat);
mailMerge.Merge(DataTable, true);
mailMerge.TextComponent = tx
mailMerge.LoadTemplateFromMemory(Document, _
    TXTextControl.DocumentServer.FileFormat.InternalUnicodeFormat)
mailMerge.Merge(DataTable, True)

Image

TX Quote Generator - An Advanced Example

This sample program shows how to use Text Control in office applications. The main task of an office application typically is to create documents from information taken from a set of databases. For instance, a quote is generated from a record in an address database and one or more records in an article database.

The program is built up in two steps, starting very simple with only a single address database, and adding more features later on.

The source code for this example is contained in the subfolders Step1 and Step2 of the following directories:

  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\VB.NET\Quote Generator
  • %USERPROFILE%\My Documents\TX Text Control 29.0.NET for Windows Forms\Samples\WinForms\CSharp\Quote Generator

Used TX Text Control controls:

  • TXTextControl.TextControl
  • TXTextControl.ButtonBar
  • TXTextControl.RulerBar
  • TXTextControl.StatusBar

Relevant API Links

Step 1: Creating a Quote from a Database

When the program is started, it displays an address database in a data grid control.

Image

The database is a simple XML file, which is displayed with just a few lines of ADO code:

DataSet dsAddress = new DataSet ("address");
dsAddress.ReadXml("..\..\address.xml");
gridAddress.DataSource = dsAddress;
gridAddress.DataMember = "address_record";
Dim DsAddress As New DataSet("address")
DsAddress.ReadXml("..\address.xml")
GridAddress.DataSource = DsAddress
GridAddress.DataMember = "address_record"

Selecting the File/New Quote menu item takes the current record from the database and creates a document from it. This is done in the following way:

A form containing a Text Control is opened, and a stylesheet is loaded. A stylesheet is a file that serves as a template for the final document. It contains all text parts which are equal to all documents, for instance a phrase like "In reply to your inquiry and according to our general terms of business we are pleased to..", and placeholders for information that is to be inserted from a database, like Address, Date, and so forth. It also defines the font, font size, company logo, and layout, so that all files will have the same look.

Image

Once the stylesheet has been loaded, the placeholders are updated from the database, so that they now contain the real address, name, customer number, and date.

Image

The stylesheet can be edited with the Advanced menu.

Step 2: Adding Articles with a Table

Before you read everything about how it is programmed, you may want to run it and see what it does, so here is a short user's guide first.

  • Start the program. You will see the main form, displaying some customer address records. Select one by clicking on it.
  • Select the File / New Quote menu item. A quote will be generated using the selected customer's name, address and customer number.
  • Click on the Insert / Article menu item. Select one of the articles displayed in the dialog box that pops up, and click OK. The product data will automatically be entered into the quote.
  • Enter the desired quantity. The total will be recalculated accordingly.
  • Repeat step 3 to enter more articles (clicking into an empty table row first). Delete the remaining empty lines by selecting them with the mouse and clicking Edit / Delete table rows.
  • Finished. Click File / Print to make a printout of the quote.

The first thing we need to do in order to add article descriptions and pricing to our quotes from Step 1 is to add another database. We call it the article database, and display it on the main form beside the address database.

Image

That's it for the main form. On the editor form, we now add a menu item which lets us insert items from the article data into a quote.

A list of articles is best displayed in a table, and Text Control offers all required table functions to let us insert product IDs, descriptions, and prices into the respective cells, as well as to perform calculations. We therefore add a table to the style sheet and adjust its column widths, text distances, and caption text so that later only the plain text needs to be filled in.

This is what the style sheet now looks like:

Image

A new menu item has been added to the Advanced menu, which allows to insert a table. Also, a Format/Table menu item has been created which calls Text Control's table attribute dialog box, so that we can adjust the table grid lines and background shading. The table's column widths and tabs are adjusted in the ruler bar. Note that the 2 rightmost columns have decimal tabs, so that the currency values they will contain will be properly aligned at the decimal sign.

We are now ready to fill in text from the article database into the table. Have a look at the sample program's ArticleTable class, which shows how to use the various table, row, columns and cell collections and objects.

After the user has selected a product in the article database, the program performs these steps:

  • It checks if the current input position is in a row of the article table, where a product can be inserted. If not, it uses the first row below the caption.
  • It inserts the selected product code, product description, and price.
  • Whenever Text Control sends a Changed event while the current input position was inside a table, the total is recalculated accordingly.