Dynamic Template Generation
The third part of the Visual Basic mail merge sample turns the application into a mail merge layout editor. The user selects a database and inserts its fields into the active document with mouse clicks. When the mail merge starts, these fields are replaced by the data from the database.
The application doesn't know in advance how many fields a database has, so it must work with databases of varying size. Every piece of static code that deals with database fields is replaced by code that uses the field names at run time. The project files of this part are in the Samples\vb6\MailMerge\Step3 directory.
Select a Database
A menu item opens a Common Dialog in which the user selects a database. The database isn't loaded: only its name is stored in the curDBName variable. Holding an entire database in memory could cause problems when it is several terabytes in size.
Insert Database Fields Into the Template
The user may insert only fields that exist in the database into the active document. For this, the form has a combo box, which is filled with the field names of the database when the database is loaded. A button inserts the field selected in the combo box into the active document.
Create the Labels of the Browse Database Form
In the previous part, the labels of the Browse Database form that display the data were statically linked to the database. Now they are a control array: the labels are created when the form is loaded and then linked to the corresponding database field. The Form_Load event procedure of the form does this:
Private Sub Form_Load()
Data1.DatabaseName = curDBName
doPrint = False
TXHidden.Left = 10000 ' Move TX out of the visible area
Dim db As Database
Dim rs As Recordset
' Find record
Set db = OpenDatabase(curDBName)
Set rs = db.OpenRecordset(db.TableDefs(0).name)
lblField(0).Caption = rs.Fields(0).name
lblData(0).DataField = rs.Fields(0).name
' Create labels
For i = 1 To rs.Fields.Count - 1
Load lblField(i)
lblField(i).Top = 320 + (i * 300)
lblField(i).Caption = rs.Fields(i).name
lblField(i).Visible = True
Load lblData(i)
lblData(i).Top = 320 + (i * 300)
lblData(i).DataField = rs.Fields(i).name
lblData(i).Visible = True
' if i > 6 We need more space
If i > 6 Then
Form2.Height = Form2.Height + 300
Frame1.Height = Frame1.Height + 300
Data1.Top = Data1.Top + 300
cmdMerge.Top = cmdMerge.Top + 300
cmdCancel.Top = cmdCancel.Top + 300
End If
Next i
End Sub
The code works as follows:
- The data control
Data1is connected to the database named incurDBName, and the hiddenTXTextControlof the print queue is moved out of the visible area. - The field labels,
lblField, show the names of the database fields. The data labels,lblData, display the content from the database. - For each further field of the database, the loop loads a new field label and a new data label and places them below the previous ones.
- As soon as the database has more than seven fields, the form, its frame, the data control and the Merge and Cancel buttons are enlarged or moved, so that there is enough room for all labels.
Save the Database Name With the Template
When the fields of a database appear in the active document, the connected database must be loaded with the document. Therefore, the name of the database is saved in the document: the application writes a header to the file first, and only then saves the data of the TXTextControl. On loading, the header is read first.
The following code saves a template this way:
Private Sub mnuSaveTemplate_Click()
Dim FileID As Long
Dim lFilePos As Long
On Error Resume Next
' Create a "Save File" dialog box
CommonDialog1.Filter = "TX Demo (*.ttx)|*.ttx"
CommonDialog1.DialogTitle = "Save As"
CommonDialog1.Flags = cdlOFNOverwritePrompt Or cdlOFNHideReadOnly
CommonDialog1.CancelError = True
CommonDialog1.ShowSave
If Err Then Exit Sub
' Write Header
Open CommonDialog1.FileName For Binary As #1
FileID = FILE_ID
Put #1, , FileID
Put #1, , curDBName
Put #1, , vbCrLf
lFilePos = loc(1)
Close #1
TXTextControl1.Save CommonDialog1.FileName, lFilePos, 3
End Sub
The code works as follows:
- A Save As dialog box asks for the file name of the template, with the filter *.ttx. If the user cancels it, the procedure ends.
- The header, a file ID, the database name in
curDBNameand a line break, is written to the file, andlFilePosreceives the position after it. - Save writes the document to the same file at the position
lFilePos, in the internal TX Text Control format (3).
Next Steps
- Printing More Than One Record: the print queue and the hidden
TXTextControlthis part builds on. - Connecting to Databases: store a complete document in a database field.
- Marked Text Fields: the fields that receive the database data.