About the Demo
The Beneficiary Designation demo takes advantage
of some complex Microsoft Word functionality.
In this demo, the Word document is populated
with data from a SQL Server database. Upon
file open, the MailMerge fields automatically
update with the values that have been inserted
by WordWriter. The user can then modify values,
using the familiar interface of Microsoft
Word, and upon document close, the user can
choose to send the new values back to the
database.
|
Server-side code is marked in gray
Courier font.
| Note: |
This
explanation contains only portions
of the code necessary to run this
application.
To view the entire ASP.NET page,
use the corresponding "Source" link
on the demo
index page. |
|
How It Works
Step 1: Create a Template
Use Microsoft Word to create a template that
will be used by SoftArtisans
WordWriter.
The Beneficiary Designation template contains
very advanced Microsoft Word functionality,
such as graphics and drawing elements, mail
merge fields, text and checkbox form fields,
a footer with nested table, and complex VBA
code:

Graphic & Drawing Elements

Checkbox Form Fields

Text Form Fields and
MailMerge Fields
Step 2: Add MailMerge Fields - Allow WordWriter
To Populate Document With Data
WordWriter uses the Microsoft Word MailMerge
feature in order to populate the template
with data. Ensure that the values inside the
MailMerge fields can be accessed from macros,
and from the server-side application, by nesting
the MailMerge field inside a simple text form
field. Form fields automatically have bookmarks
associated. The bookmark value will help to
identify the MailMerge field in the VBA code.
Using Microsoft Word to modify the template,
create a WordWriter MailMerge field:
- Add A Text Form Field
- Select "View" from the
menu bar
- Choose "Toolbars" from
the drop-down menu
- Click on "Forms" in the
Toolbars fly-out
- Add a text form field (the
button looks like: [ab|]) to the document
- Right-click on the new
text field and choose "Properties"
to view the bookmark value. In order
to fetch the value of the Merge Field
to be created in the next step, you
must associate a name in the Bookmark
field in this screen. Leave the Type
set to "Regular Text". Note the "Run
macro on" property - you can also
connect macros to form fields.
The result should look like this:
- Insert a MailMerge MergeField
into the Text Form Field
- Select "Insert" from the
menu bar
- Choose "Field..." from
the drop-down menu
- Choose the "Mail Merge"
category and the "MergeField" field
name. In the textbox, after the text
"MERGEFIELD", add the same name you
gave to the Text Form Field bookmark.
The result should look like this:
- Protect the document to ensure
that end-users won't mistakenly delete the
MailMerge fields
Writing a macro is the best way to ensure
that fields are not deleted from the template
document.
|
VBA Code:
Sub Protect()
'
' Protect Macro
'
ActiveDocument.Protect wdAllowOnlyFormFields,
True
End Sub
|
Step 3: Enhance Document Functionality
With Macros
The Beneficiary Designation demo makes liberal
use of macros in order to provide the user
with advanced features, such as the ability
to update the server-side database from a
client-side Microsoft Word document.
Values from form fields are gathered and
stored so they can be used in the SendRequest
function.
|
VBA Code:
Public Sub Update()
Dim yn As VbMsgBoxResult
yn = MsgBox("Do you want
to update the database with your new
beneficiary selections?", vbYesNo,
"Update Database?")
If yn = vbNo Then
Exit Sub
End If
Dim vals(4) As Variant
Dim Status As Integer
If ActiveDocument.FormFields("chkA").CheckBox.Value
= True Then
Status = 1
ElseIf ActiveDocument.FormFields("chkB").CheckBox.Value
= True Then
Status = 2
ElseIf ActiveDocument.FormFields("chkC").CheckBox.Value
= True Then
Status = 3
End If
vals(0) = "BeneficiaryStatus="
& Status
vals(1) = "Primary1="
& Trim(ActiveDocument.FormFields("Primary1").Result)
vals(2) = "Primary2="
& Trim(ActiveDocument.FormFields("Primary2").Result)
vals(3) = "Contingent1="
& Trim(ActiveDocument.FormFields("Contingent1").Result)
vals(4) = "Contingent2="
& Trim(ActiveDocument.FormFields("Contingent2").Result)
Dim url As String
Dim reqname As String
Dim httpstatus As Integer
url = "http://localhost/Demos/OfficeWriter/PostOne/BeneficiarySelection.aspx"
reqname = "UpdateBeneficiaries"
On Error Resume Next
httpstatus
= HotCellRequest.SendRequest(url,
reqname, vals)
If Err.Number
<> 0 Then
MsgBox
"Error sending HotCell request. Could
not contact server database update
page." & _
vbCrLf
& "Details: " & Err.Description,
_
vbCritical,
"HotCell Request Failed"
Exit
Sub
End If
On Error GoTo 0
If httpstatus = 200 Then
MsgBox "You
have successfully submitted your Beneficiary
selections.", _
vbOKOnly,
"HotCell Update Succeeded"
Else
MsgBox "The
HotCell database update did not succeed.
The server-side database update "
& _
"page
returned an error. The server returned
status code: " & httpstatus, _
vbCritical,
"HotCell Update Error"
End If
End Sub
|
On document close, the SendRequest function
sends form values through HTTP to the ASP.NET
page which will update the database.
|
VBA Code:
Public Function SendRequest(url
As String, requestname As String,
pairs As Variant) As Integer
Dim strReq As String
Dim oHTTP As Object
'--- The XMLHTTP object
needs form values to be sent in this
form:
'--- "name1=value1&name2=value2&name3=value3",
etc
'--- we're forming a request
of that format here
strReq = Join(pairs, "&")
'--- Use the XMLHTTP object
to do the HTTP request
On Error Resume Next
Set oHTTP
= CreateObject("Msxml2.XMLHTTP.3.0")
If Err.Number
<> 0 Then
Err.Raise
Err.Number, "HotCellRequest", _
"Could
not create XMLHTTP object which is
required by HotCells."
Exit
Function
End If
On Error GoTo 0
On Error Resume Next
oHTTP.Open
"POST", url, False
If Err.Number
<> 0 Then
Err.Raise
Err.Number, "HotCellRequest", _
"HotCell
failed to connect to " & url &
" " & _
Err.Description
Exit
Function
End If
On Error GoTo 0
'--- We need to set this
whenever submitting form data
oHTTP.SetRequestHeader
"Content-Type", "application/x-www-form-urlencoded"
oHTTP.SetRequestHeader
"X-SaHotCellRequest", requestname
'--- Send the request
On Error Resume Next
oHTTP.Send
CStr(strReq)
If Err.Number
<> 0 Then
Err.Raise
Err.Number, "HotCellRequest", _
"HotCell
failed when sending data to " &
url &" " & _
Err.Description
Exit
Function
End If
On Error GoTo 0
SendRequest = oHTTP.Status
'--- Clean up
Set oHTTP = Nothing
End Function
|
Step 4: WordWriter Processes and Populates
the Word Template
Upon request of the document, WordWriter
is called from an ASP.NET page, which dynamically
populates the template created in the previous
steps.
|
ASP.NET Code:
//--- Instantiate the WordWriter.WordTemplate
object
oWW = new WordTemplate();
//--- Open the template file
oWW.Open(templatepath);
//--- Set the datasource with the
DataSet containing the recipient information
oWW.SetDataSource(oDT);
//--- Process the template
oWW.Process();
//--- Begin streaming the processed
template
oWW.Save(Page.Response, "BeneficiarySelection.doc",
false);
Page.Response.Close();
|
Step 5: Server-Side Code Updates SQL Server
Database
Upon document close, the user is prompted
to update the data source. The following ASP.NET
code pushes the values from the client-side
Word document into the SQL Server database.
|
ASP.NET Code:
//--- This function reads the
HotCell request and updates the database
private void DoHotCellUpdate()
{
int employeeID = (int)Session["empID"];
string primary1 = Request.Form["Primary1"];
string primary2 = Request.Form["Primary2"];
string contingent1 = Request.Form["Contingent1"];
string contingent2 = Request.Form["Contingent2"];
string status = Request.Form["BeneficiaryStatus"];
DataAccess data = null;
int ra = 0;
try
{
data = new
DataAccess();
ra = data.UpdateBeneficiaryInfo(employeeID,
primary1, primary2,
contingent1,
contingent2, status);
if(ra!=1)
throw
new Exception("Failed to update Beneficiary
info");
System.Diagnostics.Debug.Write("RA:
" + ra.ToString());
}
catch(Exception ex)
{
System.Diagnostics.Debug.Write("RA:
" + ra);
System.Diagnostics.Debug.Write(ex.ToString());
Response.StatusCode
= 500;
}
finally
{
if(data!=null)
data.Dispose();
}
}
|
End Result:
WordWriter dynamically populates MergeFields
from the SQL database into the generated document.
The document is then sent to the client, where
the end-user can modify values in the document's
unprotected form fields. When the end-user
closes the document, the client-side VBA script
posts the update back to the SQL database,
keeping the document in sync with the database.
Click on the graphic below to view a larger
version.
|